From be501aca718a3a495b2a209b78d9451fbe7e6f35 Mon Sep 17 00:00:00 2001 From: Igor Pecovnik Date: Sun, 9 Jun 2024 10:16:08 +0200 Subject: [PATCH 01/53] Adjust several desktop targets in order to be able to assemble them Images were tested for compiling with newly added Action script that generates x86 QEMU images upon (manual for now) execution https://github.com/armbian/os/actions/workflows/full-distro-build-and-test.yml --- .../environments/budgie/config_base/packages | 5 - .../environments/gnome/config_base/packages | 3 - .../environments/mate/config_base/packages | 1 - .../common/appgroups/browsers/packages | 1 + .../environments/budgie/config_base/packages | 1 - .../environments/mate/config_base/packages | 1 - .../jammy/environments/kde-neon/support | 2 +- .../kde-plasma/config_base/packages | 4 - .../noble/environments/i3-wm/architectures | 1 + .../i3-wm/armbian/create_desktop_package.sh | 14 ++ .../environments/i3-wm/config_base/packages | 154 ++++++++++++++++++ .../noble/environments/i3-wm/debian/postinst | 41 +++++ .../desktop/noble/environments/i3-wm/support | 1 + .../noble/environments/kde-neon/architectures | 1 + .../noble/environments/kde-neon/armbian | 1 + .../kde-neon/config_base/packages | 10 ++ .../kde-neon/config_base/packages.uninstall | 1 + .../noble/environments/kde-neon/debian | 1 + .../kde-neon/sources/apt/neon.gpg | Bin 0 -> 1108 bytes .../kde-neon/sources/apt/neon.source | 1 + .../noble/environments/kde-neon/support | 1 + config/desktop/noble/environments/kde-plasma | 1 + .../amd64/_config/cli/{mantic => oracular} | 0 .../amd64/_config/cli/trixie/main/packages | 2 + .../cli/trixie/main/packages.additional | 1 + .../cli/trixie => arm64/_config/cli/oracular} | 0 .../arm64/_config/cli/trixie/main/packages | 2 + .../cli/trixie/main/packages.additional | 1 + .../architectures/armhf/_config/cli/mantic | 1 - .../armhf/_config/cli/noble/main/packages | 1 - .../cli/mantic => armhf/_config/cli/oracular} | 0 .../architectures/armhf/_config/cli/trixie | 1 - .../armhf/_config/cli/trixie/main/packages | 2 + .../cli/trixie/main/packages.additional | 1 + 34 files changed, 239 insertions(+), 19 deletions(-) mode change 120000 => 100644 config/desktop/jammy/environments/kde-neon/support create mode 100644 config/desktop/noble/environments/i3-wm/architectures create mode 100644 config/desktop/noble/environments/i3-wm/armbian/create_desktop_package.sh create mode 100644 config/desktop/noble/environments/i3-wm/config_base/packages create mode 100644 config/desktop/noble/environments/i3-wm/debian/postinst create mode 100644 config/desktop/noble/environments/i3-wm/support create mode 120000 config/desktop/noble/environments/kde-neon/architectures create mode 120000 config/desktop/noble/environments/kde-neon/armbian create mode 100644 config/desktop/noble/environments/kde-neon/config_base/packages create mode 120000 config/desktop/noble/environments/kde-neon/config_base/packages.uninstall create mode 120000 config/desktop/noble/environments/kde-neon/debian create mode 100644 config/desktop/noble/environments/kde-neon/sources/apt/neon.gpg create mode 100644 config/desktop/noble/environments/kde-neon/sources/apt/neon.source create mode 100644 config/desktop/noble/environments/kde-neon/support create mode 120000 config/desktop/noble/environments/kde-plasma rename config/optional/architectures/amd64/_config/cli/{mantic => oracular} (100%) create mode 100644 config/optional/architectures/amd64/_config/cli/trixie/main/packages create mode 100644 config/optional/architectures/amd64/_config/cli/trixie/main/packages.additional rename config/optional/architectures/{amd64/_config/cli/trixie => arm64/_config/cli/oracular} (100%) create mode 100644 config/optional/architectures/arm64/_config/cli/trixie/main/packages create mode 100644 config/optional/architectures/arm64/_config/cli/trixie/main/packages.additional delete mode 120000 config/optional/architectures/armhf/_config/cli/mantic rename config/optional/architectures/{arm64/_config/cli/mantic => armhf/_config/cli/oracular} (100%) delete mode 120000 config/optional/architectures/armhf/_config/cli/trixie create mode 100644 config/optional/architectures/armhf/_config/cli/trixie/main/packages create mode 100644 config/optional/architectures/armhf/_config/cli/trixie/main/packages.additional diff --git a/config/desktop/bookworm/environments/budgie/config_base/packages b/config/desktop/bookworm/environments/budgie/config_base/packages index 3708bd6a61c0..876a4a36dfa5 100644 --- a/config/desktop/bookworm/environments/budgie/config_base/packages +++ b/config/desktop/bookworm/environments/budgie/config_base/packages @@ -26,7 +26,6 @@ budgie-kangaroo-applet budgie-keyboard-autoswitch-applet budgie-network-manager-applet budgie-previews -budgie-previews-applet budgie-quickchar budgie-quicknote-applet budgie-recentlyused-applet @@ -38,9 +37,7 @@ budgie-trash-applet budgie-visualspace-applet budgie-wallstreet budgie-weathershow-applet -budgie-window-mover-applet budgie-window-shuffler -budgie-workspace-overview-applet budgie-workspace-stopwatch-applet cifs-utils colord @@ -57,12 +54,10 @@ fontconfig fontconfig-config fonts-noto-mono fonts-ubuntu -fonts-ubuntu-font-family-console foomatic-db-compressed-ppds gdebi ghostscript-x gist -gnome-orca gnome-screenshot gnome-disk-utility gnome-system-monitor diff --git a/config/desktop/bookworm/environments/gnome/config_base/packages b/config/desktop/bookworm/environments/gnome/config_base/packages index 25b6306a3ac6..5c0e9a521abf 100644 --- a/config/desktop/bookworm/environments/gnome/config_base/packages +++ b/config/desktop/bookworm/environments/gnome/config_base/packages @@ -24,10 +24,7 @@ gnome-system-monitor gnome-terminal gnome-session gnome-shell -gnome-shell-extension-appindicator inputattach -libasound2 -libasound2-plugins libnotify-bin libpulsedsp gdm3 diff --git a/config/desktop/bookworm/environments/mate/config_base/packages b/config/desktop/bookworm/environments/mate/config_base/packages index f5858c5ffd0f..91aeafc79d9e 100644 --- a/config/desktop/bookworm/environments/mate/config_base/packages +++ b/config/desktop/bookworm/environments/mate/config_base/packages @@ -37,7 +37,6 @@ mate-desktop-environment-core mate-desktop-environment-extra mate-desktop-environment-extras mate-dock-applet -mate-equake-applet mate-icon-theme mate-indicator-applet mate-indicator-applet-common diff --git a/config/desktop/common/appgroups/browsers/packages b/config/desktop/common/appgroups/browsers/packages index f99c9a1640d4..6821f1236d30 100644 --- a/config/desktop/common/appgroups/browsers/packages +++ b/config/desktop/common/appgroups/browsers/packages @@ -1 +1,2 @@ chromium-browser +firefox diff --git a/config/desktop/common/environments/budgie/config_base/packages b/config/desktop/common/environments/budgie/config_base/packages index 9aedefd8df4a..269d710701e4 100644 --- a/config/desktop/common/environments/budgie/config_base/packages +++ b/config/desktop/common/environments/budgie/config_base/packages @@ -25,7 +25,6 @@ budgie-kangaroo-applet budgie-keyboard-autoswitch-applet budgie-network-manager-applet budgie-previews -budgie-previews-applet budgie-quickchar budgie-quicknote-applet budgie-recentlyused-applet diff --git a/config/desktop/common/environments/mate/config_base/packages b/config/desktop/common/environments/mate/config_base/packages index 356a951dc222..912e44c9693f 100644 --- a/config/desktop/common/environments/mate/config_base/packages +++ b/config/desktop/common/environments/mate/config_base/packages @@ -106,7 +106,6 @@ mate-desktop-environment-core mate-desktop-environment-extra mate-desktop-environment-extras mate-dock-applet -mate-equake-applet mate-hud mate-icon-theme mate-indicator-applet diff --git a/config/desktop/jammy/environments/kde-neon/support b/config/desktop/jammy/environments/kde-neon/support deleted file mode 120000 index 3c4d1d008a2c..000000000000 --- a/config/desktop/jammy/environments/kde-neon/support +++ /dev/null @@ -1 +0,0 @@ -../../../common/environments/kde-plasma/support \ No newline at end of file diff --git a/config/desktop/jammy/environments/kde-neon/support b/config/desktop/jammy/environments/kde-neon/support new file mode 100644 index 000000000000..bc2264ca197d --- /dev/null +++ b/config/desktop/jammy/environments/kde-neon/support @@ -0,0 +1 @@ +eos diff --git a/config/desktop/jammy/environments/kde-plasma/config_base/packages b/config/desktop/jammy/environments/kde-plasma/config_base/packages index ef8e6d50429e..3068b9c28363 100644 --- a/config/desktop/jammy/environments/kde-plasma/config_base/packages +++ b/config/desktop/jammy/environments/kde-plasma/config_base/packages @@ -37,7 +37,6 @@ foomatic-db-compressed-ppds gdebi ghostscript-x gist -gnome-orca gnome-disk-utility gnome-screenshot gnome-user-docs-de @@ -74,7 +73,6 @@ libatk-adaptor libcvc0 libfont-afm-perl libfontconfig1 -libfontembed1 libfontenc1 libgail-common libgl1-mesa-dri @@ -85,7 +83,6 @@ libproxy1-plugin-gsettings libproxy1-plugin-networkmanager libu2f-udev libwmf0.2-7-gtk -libxapp1 libxcursor1 sddm mesa-utils @@ -142,7 +139,6 @@ wswiss x11-apps x11-utils x11-xserver-utils -xapp xapps-common xarchiver xbacklight diff --git a/config/desktop/noble/environments/i3-wm/architectures b/config/desktop/noble/environments/i3-wm/architectures new file mode 100644 index 000000000000..f4ca77356932 --- /dev/null +++ b/config/desktop/noble/environments/i3-wm/architectures @@ -0,0 +1 @@ +armhf, arm64, amd64, riscv64 diff --git a/config/desktop/noble/environments/i3-wm/armbian/create_desktop_package.sh b/config/desktop/noble/environments/i3-wm/armbian/create_desktop_package.sh new file mode 100644 index 000000000000..12f8dca6157b --- /dev/null +++ b/config/desktop/noble/environments/i3-wm/armbian/create_desktop_package.sh @@ -0,0 +1,14 @@ +# install lightdm greeter +cp -R "${SRC}"/packages/blobs/desktop/lightdm "${destination}"/etc/armbian + +# install default desktop settings +mkdir -p "${destination}"/etc/skel +cp -R "${SRC}"/packages/blobs/desktop/skel/. "${destination}"/etc/skel + +# install logo for login screen +mkdir -p "${destination}"/usr/share/pixmaps/armbian +cp "${SRC}"/packages/blobs/desktop/icons/armbian.png "${destination}"/usr/share/pixmaps/armbian + +# install wallpapers +mkdir -p "${destination}"/usr/share/backgrounds/armbian/ +cp "${SRC}"/packages/blobs/desktop/desktop-wallpapers/armbian*.jpg "${destination}"/usr/share/backgrounds/armbian/ diff --git a/config/desktop/noble/environments/i3-wm/config_base/packages b/config/desktop/noble/environments/i3-wm/config_base/packages new file mode 100644 index 000000000000..1a8378b3b50b --- /dev/null +++ b/config/desktop/noble/environments/i3-wm/config_base/packages @@ -0,0 +1,154 @@ +anacron +apport-gtk +apt-xapian-index +arandr +blueman +bluez +bluez-cups +bluez-tools +brltty +brltty-x11 +caffeine +cifs-utils +compton +cups +cups-bsd +cups-client +cups-filters +dbus-x11 +dictionaries-common +dmz-cursor-theme +doc-base +dunst +evince +evince-common +feh +fontconfig +fontconfig-config +fonts-arphic-ukai +fonts-arphic-uming +fonts-dejavu-core +fonts-freefont-ttf +fonts-guru +fonts-guru-extra +fonts-khmeros-core +fonts-liberation +fonts-nanum +fonts-opensymbol +fonts-stix +fonts-symbola +fonts-ubuntu +foomatic-db-compressed-ppds +gdebi +ghostscript-x +gir1.2-appindicator3-0.1 +gnome-bluetooth +gnome-disk-utility +gnome-font-viewer +gnome-power-manager +gnome-system-monitor +gromit +gstreamer1.0-packagekit +gstreamer1.0-plugins-base-apps +gstreamer1.0-pulseaudio +gvfs-backends +hplip +i3 +i3lock +i3status +i3-wm +suckless-tools +indicator-printers +inputattach +kerneloops +keyutils +language-pack-en +laptop-detect +libanyevent-i3-perl +libatk-adaptor +libev4 +libfont-afm-perl +libfontconfig1 +libfontenc1 +libgail-common +libgl1-mesa-dri +libgnome-bluetooth13 +libgsettings-qt1 +libjson-xs-perl +libnotify-bin +libproxy1-plugin-gsettings +libproxy1-plugin-networkmanager +libu2f-udev +libwmf0.2-7-gtk +libxcb-cursor0 +libxcursor1 +lightdm +lightdm-gtk-greeter +lightdm-gtk-greeter-settings +lightdm-settings +lxappearance +mousetweaks +network-manager-openvpn-gnome +network-manager-vpnc +nitrogen +numix-gtk-theme +openprinting-ppds +overlay-scrollbar +overlay-scrollbar-gtk2 +p7zip-full +pamix +pasystray +pavucontrol +pavucontrol-qt +pavumeter +policykit-1 +policykit-1-gnome +policykit-desktop-privileges +printer-driver-all +profile-sync-daemon +pulseaudio-module-bluetooth +redshift +rofi +samba +slick-greeter +smbclient +system-config-printer +software-properties-gtk +speech-dispatcher +spice-vdagent +terminator +thunar +totem +totem-common +totem-plugins +ubuntu-docs +ubuntu-drivers-common +ubuntu-wallpapers +update-inetd +update-manager +update-manager-core +update-notifier +update-notifier-common +vifm +x11-apps +x11-xserver-utils +xarchiver +xbacklight +xcursor-themes +xdg-user-dirs +xdg-user-dirs-gtk +xfonts-100dpi +xfonts-75dpi +xfonts-base +xfonts-encodings +xfonts-scalable +xfonts-utils +xorg-docs +xorg-docs-core +xscreensaver +xserver-xorg +xserver-xorg-video-fbdev +xauth +xtitle +xttitle +xwallpaper diff --git a/config/desktop/noble/environments/i3-wm/debian/postinst b/config/desktop/noble/environments/i3-wm/debian/postinst new file mode 100644 index 000000000000..5eeeaa17ff47 --- /dev/null +++ b/config/desktop/noble/environments/i3-wm/debian/postinst @@ -0,0 +1,41 @@ +# overwrite stock lightdm greeter configuration +if [ -d /etc/armbian/lightdm ]; then cp -R /etc/armbian/lightdm /etc/; fi + +# Disable Pulseaudio timer scheduling which does not work with sndhdmi driver +if [ -f /etc/pulse/default.pa ]; then sed "s/load-module module-udev-detect$/& tsched=0/g" -i /etc/pulse/default.pa; fi + +# set wallpapper to armbian +echo "exec_always --no-startup-id feh --bg-scale --zoom fill --no-fehbg /usr/share/backgrounds/armbian/armbian03-Dre0x-Minum-dark-3840x2160.jpg" | tee -a /etc/i3/config + +# lightdm wallpaper +mv /etc/lightdm/slick-greeter.conf /etc/lightdm/slick-greeter.conf.bak +touch /etc/lightdm/slick-greeter.conf +echo "[Greeter] +background=/usr/share/backgrounds/armbian/armbian03-Dre0x-Minum-dark-3840x2160.jpg +theme-name = Numix +icon-theme-name = Numix +font-name = Sans 11 +draw-user-background = false +show-keyboard = true +onscreen-keyboard = false +screen-reader = true +draw-grid = true" | tee -a /etc/lightdm/slick-greeter.conf + +echo "Finished preparing /etc/lightdm/slick-greeter.conf..." + +mv /etc/lightdm/lightdm-gtk-greeter.conf /etc/lightdm/lightdm-gtk-greeter.conf.bak +touch /etc/lightdm/lightdm-gtk-greeter.conf +echo "[greeter] +background=/usr/share/backgrounds/armbian/armbian03-Dre0x-Minum-dark-3840x2160.jpg +theme-name = Numix +icon-theme-name = Numix +font-name = Sans 11 +draw-user-background = false +show-keyboard = true +onscreen-keyboard = false +screen-reader = true +draw-grid = true" | tee -a /etc/lightdm/lightdm-gtk-greeter.conf + +echo "Finished preparing /etc/lightdm/lightdm-gtk-greeter.conf..." + +slick-greeter -h #applies wallpaper diff --git a/config/desktop/noble/environments/i3-wm/support b/config/desktop/noble/environments/i3-wm/support new file mode 100644 index 000000000000..0b0206d21c91 --- /dev/null +++ b/config/desktop/noble/environments/i3-wm/support @@ -0,0 +1 @@ +supported \ No newline at end of file diff --git a/config/desktop/noble/environments/kde-neon/architectures b/config/desktop/noble/environments/kde-neon/architectures new file mode 120000 index 000000000000..d93144c069b0 --- /dev/null +++ b/config/desktop/noble/environments/kde-neon/architectures @@ -0,0 +1 @@ +../../../common/environments/kde-plasma/architectures \ No newline at end of file diff --git a/config/desktop/noble/environments/kde-neon/armbian b/config/desktop/noble/environments/kde-neon/armbian new file mode 120000 index 000000000000..66eb11f76328 --- /dev/null +++ b/config/desktop/noble/environments/kde-neon/armbian @@ -0,0 +1 @@ +../../../common/environments/kde-plasma/armbian \ No newline at end of file diff --git a/config/desktop/noble/environments/kde-neon/config_base/packages b/config/desktop/noble/environments/kde-neon/config_base/packages new file mode 100644 index 000000000000..713143abaf67 --- /dev/null +++ b/config/desktop/noble/environments/kde-neon/config_base/packages @@ -0,0 +1,10 @@ +neon-desktop +kde-standard +sddm +plasma-nm +plasma-pa +plasma-discover +plasma-vault +scdaemon +kscreen +bluedevil diff --git a/config/desktop/noble/environments/kde-neon/config_base/packages.uninstall b/config/desktop/noble/environments/kde-neon/config_base/packages.uninstall new file mode 120000 index 000000000000..f569eddb09c9 --- /dev/null +++ b/config/desktop/noble/environments/kde-neon/config_base/packages.uninstall @@ -0,0 +1 @@ +../../../../common/environments/kde-plasma/config_base/packages.uninstall \ No newline at end of file diff --git a/config/desktop/noble/environments/kde-neon/debian b/config/desktop/noble/environments/kde-neon/debian new file mode 120000 index 000000000000..1ff8b65acc03 --- /dev/null +++ b/config/desktop/noble/environments/kde-neon/debian @@ -0,0 +1 @@ +../../../common/environments/kde-plasma/debian \ No newline at end of file diff --git a/config/desktop/noble/environments/kde-neon/sources/apt/neon.gpg b/config/desktop/noble/environments/kde-neon/sources/apt/neon.gpg new file mode 100644 index 0000000000000000000000000000000000000000..fe91a10436cb6d0599d7731f2adea22069a4ed63 GIT binary patch literal 1108 zcmV-a1gra*0u2OKbI5c75CEz7)|OqslF_biIeQ7|CZVL=__SR^k(jK5Luvi(fG3D+ zS#^whp>7Av-Y6bPkU(beL5Sk1@lj70bo&&Am1PHY{kCo8Yg_YkAO*+E7*T*gftR_Z zqmC6utIMI4*S-8S`6v#=EhX0qFyQ)^(wapcj-sBRi*7xbqLuBkF7J>`mZ|(~!z!UD!TLTk0-2d{M!ae?k&gzVhEJ?qQx$ z{A3OGEof~~=l%bqo*E{tJJl?eC$ z1a(@M>ayp}IrdX$o^?stJjxzck$-Jt+MLhqp|LuJ_he??8$iE%;o=KNDZ#wA@iH=* zJP#)iIaz*Nz&~B5-lk1?X#k9b=aZN{L7&h2^A}0nn$VmE_QL#(!ho5eOio74qRueE z&TsLC5_<;&YT!Xl;FWQVaO~!L+P3Zs*B=0+!+5Q-rNIPWoPIAIC2@4So|NKY`&zRZH)vu`aH=un~@eo;F)p5*fIFa?nJ>rd164eA@_V;RVofGCwqhXXkUr4Ni+B z@xqX5+8aQ}2oP2L#h(F#sMHyT2Z$Olc|K&U#{koLaNcY`^5rE*c6z8>c49}=2(Yr> aE~KuGi7;J4pa`jAR9>oX%R%U@c}ZwbZW8 Date: Mon, 10 Jun 2024 02:33:06 +0800 Subject: [PATCH 02/53] Fix board firefly-itx-3588j bluetooth --- config/boards/firefly-itx-3588j.csc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/config/boards/firefly-itx-3588j.csc b/config/boards/firefly-itx-3588j.csc index e254ec5fdd5f..d7d3c65ef715 100644 --- a/config/boards/firefly-itx-3588j.csc +++ b/config/boards/firefly-itx-3588j.csc @@ -18,3 +18,23 @@ function post_family_config__firefly-itx-3588j_use_vendor_uboot() { BOOTDIR="u-boot-${BOARD}" BOOTPATCHDIR="u-boot-firefly-itx-3588j" } + +function post_family_tweaks_bsp__firefly-itx-3588j() { + display_alert "$BOARD" "Installing rk3588-bluetooth.service" "info" + + # Bluetooth on this board is handled by a Broadcom (AP6275PR3) chip and requires + # a custom brcm_patchram_plus binary, plus a systemd service to run it at boot time + install -m 755 $SRC/packages/bsp/rk3399/brcm_patchram_plus_rk3399 $destination/usr/bin + cp $SRC/packages/bsp/rk3399/rk3399-bluetooth.service $destination/lib/systemd/system/rk3588-bluetooth.service + + # Reuse the service file, ttyS0 -> ttyS6; BCM4345C5.hcd -> BCM4362A2.hcd + sed -i 's/ttyS0/ttyS6/g' $destination/lib/systemd/system/rk3588-bluetooth.service + sed -i 's/BCM4345C5.hcd/BCM4362A2.hcd/g' $destination/lib/systemd/system/rk3588-bluetooth.service + return 0 +} + +function post_family_tweaks__firefly-itx-3588j_enable_services() { + display_alert "$BOARD" "Enabling rk3588-bluetooth.service" "info" + chroot_sdcard systemctl enable rk3588-bluetooth.service + return 0 +} From 36eb4aeeda75ea28bed5172880bb6a493dffd962 Mon Sep 17 00:00:00 2001 From: Igor Pecovnik Date: Mon, 10 Jun 2024 12:35:28 +0200 Subject: [PATCH 03/53] Oracular i3wm: Remove deprecated packages --- config/desktop/noble/environments/i3-wm/config_base/packages | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/desktop/noble/environments/i3-wm/config_base/packages b/config/desktop/noble/environments/i3-wm/config_base/packages index 1a8378b3b50b..9d2567f5ce05 100644 --- a/config/desktop/noble/environments/i3-wm/config_base/packages +++ b/config/desktop/noble/environments/i3-wm/config_base/packages @@ -66,13 +66,11 @@ language-pack-en laptop-detect libanyevent-i3-perl libatk-adaptor -libev4 libfont-afm-perl libfontconfig1 libfontenc1 libgail-common libgl1-mesa-dri -libgnome-bluetooth13 libgsettings-qt1 libjson-xs-perl libnotify-bin From b33c41d76fbad6f3551fdf948eadcd2c2ecbd4b0 Mon Sep 17 00:00:00 2001 From: Ricardo Pardini Date: Mon, 10 Jun 2024 19:37:09 +0200 Subject: [PATCH 04/53] s5p6818-legacy: rewrite patches, no changes --- .../s5p6818-4.14/0001-aufs4.14-20190902.patch | 598 +- .../0147-si2168-fix-cmd-timeout.patch | 8 +- .../s5p6818-4.14/nexcell-support-v3.patch | 33642 ++++++++-------- .../set-DMA-coherent-pool-to-2M.patch | 62 +- .../update-nanopi-fire3-support.patch | 64 +- 5 files changed, 18202 insertions(+), 16172 deletions(-) diff --git a/patch/kernel/archive/s5p6818-4.14/0001-aufs4.14-20190902.patch b/patch/kernel/archive/s5p6818-4.14/0001-aufs4.14-20190902.patch index 8e10b672078b..6fee70de0909 100644 --- a/patch/kernel/archive/s5p6818-4.14/0001-aufs4.14-20190902.patch +++ b/patch/kernel/archive/s5p6818-4.14/0001-aufs4.14-20190902.patch @@ -1,6 +1,299 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Igor Pecovnik +Date: Wed, 22 Feb 2017 18:44:01 +0100 +Subject: [ARCHEOLOGY] Added AuFS and few other changes to XU4 NEXT kernel + +> X-Git-Archeology: - Revision 92768a527340b34a912712d661fbfa0cc54d95d5: https://github.com/armbian/build/commit/92768a527340b34a912712d661fbfa0cc54d95d5 +> X-Git-Archeology: Date: Wed, 22 Feb 2017 18:44:01 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Added AuFS and few other changes to XU4 NEXT kernel +> X-Git-Archeology: +> X-Git-Archeology: - Revision 84b173d2bbe6a98e1824347d6f910b7e8924f930: https://github.com/armbian/build/commit/84b173d2bbe6a98e1824347d6f910b7e8924f930 +> X-Git-Archeology: Date: Thu, 23 Feb 2017 16:33:33 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Cubox NEXT kernel configuration update, added AUFS +> X-Git-Archeology: +> X-Git-Archeology: - Revision 28af765cb021652a1a0d826a2992d1b8bacf936b: https://github.com/armbian/build/commit/28af765cb021652a1a0d826a2992d1b8bacf936b +> X-Git-Archeology: Date: Tue, 28 Feb 2017 12:19:19 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Cubox family patch fixes +> X-Git-Archeology: +> X-Git-Archeology: - Revision f37196cad0b4417554a770845beb0ce36306334a: https://github.com/armbian/build/commit/f37196cad0b4417554a770845beb0ce36306334a +> X-Git-Archeology: Date: Fri, 23 Jun 2017 13:03:16 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Adjusting CUBOX and CLEARFOG next branches for kernel 4.9.x +> X-Git-Archeology: +> X-Git-Archeology: - Revision 40953b2b68664714150445ecd8599b0e8f01a0ed: https://github.com/armbian/build/commit/40953b2b68664714150445ecd8599b0e8f01a0ed +> X-Git-Archeology: Date: Fri, 23 Jun 2017 14:43:05 +0300 +> X-Git-Archeology: From: zador-blood-stained +> X-Git-Archeology: Subject: Revert "Adjusting CUBOX and CLEARFOG next branches for kernel 4.9.x" +> X-Git-Archeology: +> X-Git-Archeology: - Revision 4cd7bd0e684a0aa2798328d5301692e53ab5130d: https://github.com/armbian/build/commit/4cd7bd0e684a0aa2798328d5301692e53ab5130d +> X-Git-Archeology: Date: Sun, 03 Sep 2017 20:52:27 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Update Odroid C2 NEXT and DEV kernel config, update Docker compatibility, AUFS patch +> X-Git-Archeology: +> X-Git-Archeology: - Revision e1716759ae5b611daa4537567128dd989afca761: https://github.com/armbian/build/commit/e1716759ae5b611daa4537567128dd989afca761 +> X-Git-Archeology: Date: Sun, 03 Sep 2017 23:04:13 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Enabling UUID for Cubox, tested. Remove deprecated AUFS patch and add working one, enabling ZSWAP and various docker optimisations +> X-Git-Archeology: +> X-Git-Archeology: - Revision 3ccd308a8ee772f019120b2ad29dd1682ebac448: https://github.com/armbian/build/commit/3ccd308a8ee772f019120b2ad29dd1682ebac448 +> X-Git-Archeology: Date: Sat, 23 Sep 2017 23:16:59 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: MVEBU64 adding AC USB drivers and kernel config adjustement +> X-Git-Archeology: +> X-Git-Archeology: - Revision 13e94e58f04be27db51d18b7dac1d15a1864b79e: https://github.com/armbian/build/commit/13e94e58f04be27db51d18b7dac1d15a1864b79e +> X-Git-Archeology: Date: Fri, 27 Oct 2017 16:14:21 +0300 +> X-Git-Archeology: From: zador-blood-stained +> X-Git-Archeology: Subject: Remove random executable bits from patch files +> X-Git-Archeology: +> X-Git-Archeology: - Revision 0df07cba2cb86de1098d6bd6c64b7ab051030f70: https://github.com/armbian/build/commit/0df07cba2cb86de1098d6bd6c64b7ab051030f70 +> X-Git-Archeology: Date: Fri, 03 Nov 2017 13:00:18 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Adding better 8812AU driver with support for 8811 and 8814, AUFS and bootlogo to ODROIDXU4 dev kernel +> X-Git-Archeology: +> X-Git-Archeology: - Revision 28502a0472819829b574176074591b519950ad69: https://github.com/armbian/build/commit/28502a0472819829b574176074591b519950ad69 +> X-Git-Archeology: Date: Sat, 11 Nov 2017 17:49:39 +0300 +> X-Git-Archeology: From: zador-blood-stained +> X-Git-Archeology: Subject: Clean up executable bits in patch files +> X-Git-Archeology: +> X-Git-Archeology: - Revision 01991871c3324c95fd1c3385b98bdffb3eb7475f: https://github.com/armbian/build/commit/01991871c3324c95fd1c3385b98bdffb3eb7475f +> X-Git-Archeology: Date: Thu, 23 Nov 2017 18:50:36 -0500 +> X-Git-Archeology: From: Tony McKahan +> X-Git-Archeology: Subject: meson64 NEXT 4.14 +> X-Git-Archeology: +> X-Git-Archeology: - Revision ee58610a2543634150dba8359df9d3db1ebbdc9b: https://github.com/armbian/build/commit/ee58610a2543634150dba8359df9d3db1ebbdc9b +> X-Git-Archeology: Date: Thu, 08 Feb 2018 15:27:42 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: MVEBU64 next and default update +> X-Git-Archeology: +> X-Git-Archeology: - Revision 865a9386d39e7d187f2bdba5e67aae908d3901d2: https://github.com/armbian/build/commit/865a9386d39e7d187f2bdba5e67aae908d3901d2 +> X-Git-Archeology: Date: Thu, 08 Feb 2018 17:23:27 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: mvebu next and default update +> X-Git-Archeology: +> X-Git-Archeology: - Revision dfa99d9b60939377fc9d123520f92539547929d8: https://github.com/armbian/build/commit/dfa99d9b60939377fc9d123520f92539547929d8 +> X-Git-Archeology: Date: Thu, 08 Feb 2018 17:39:58 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: cubox, meson64, c2 and udoo NEXT update +> X-Git-Archeology: +> X-Git-Archeology: - Revision e2741240eb29ab3536230d732785dbf729ab73f9: https://github.com/armbian/build/commit/e2741240eb29ab3536230d732785dbf729ab73f9 +> X-Git-Archeology: Date: Thu, 24 May 2018 12:39:49 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Merge Meson64 from development to stable +> X-Git-Archeology: +> X-Git-Archeology: - Revision 7baa822baddf9935317a382643ba0bc44423f68d: https://github.com/armbian/build/commit/7baa822baddf9935317a382643ba0bc44423f68d +> X-Git-Archeology: Date: Fri, 25 May 2018 10:31:01 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Merging Cubox to stable. Changing NEXT from 4.16 back to 4.14 due to problems with optical audio, DEV is now 4.16, removing Solidrun 2nd stock kernel +> X-Git-Archeology: +> X-Git-Archeology: - Revision d92e11fccf1248318b2c7900c07ecced4cb4e813: https://github.com/armbian/build/commit/d92e11fccf1248318b2c7900c07ecced4cb4e813 +> X-Git-Archeology: Date: Tue, 19 Jun 2018 15:14:42 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Odroid C2 DEV / 4.17.y patches update, kernel configuration update +> X-Git-Archeology: +> X-Git-Archeology: - Revision 65368a323a71489d12a06b6b25096bceae36aa75: https://github.com/armbian/build/commit/65368a323a71489d12a06b6b25096bceae36aa75 +> X-Git-Archeology: Date: Mon, 25 Jun 2018 17:36:58 +0000 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Move Espressobin NEXT to 4.16.y and DEV to 4.17.y, adjusted patches, tested for building and booting +> X-Git-Archeology: +> X-Git-Archeology: - Revision fcb85f17675990514d8fadc905e6ccc3bded7138: https://github.com/armbian/build/commit/fcb85f17675990514d8fadc905e6ccc3bded7138 +> X-Git-Archeology: Date: Thu, 28 Jun 2018 08:27:08 +0000 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Major Amlogic RFC and cleanup +> X-Git-Archeology: +> X-Git-Archeology: - Revision 6e7e01af0b7cea388f192ba4d3d3f99777861edb: https://github.com/armbian/build/commit/6e7e01af0b7cea388f192ba4d3d3f99777861edb +> X-Git-Archeology: Date: Tue, 03 Jul 2018 14:13:25 +0000 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Adjust cubox-i / HB DEV to 4.17.y +> X-Git-Archeology: +> X-Git-Archeology: - Revision 38ae7a5495e0d3c22534590e841700ce20588225: https://github.com/armbian/build/commit/38ae7a5495e0d3c22534590e841700ce20588225 +> X-Git-Archeology: Date: Thu, 16 Aug 2018 23:16:37 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Switch Cubox DEV to 4.18.y, adjust patches and configuration +> X-Git-Archeology: +> X-Git-Archeology: - Revision c51fdc6c4ae178eee433b3133e40bf7555f34346: https://github.com/armbian/build/commit/c51fdc6c4ae178eee433b3133e40bf7555f34346 +> X-Git-Archeology: Date: Thu, 23 Aug 2018 15:13:12 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Add AUFS4.18, adjust several board configs +> X-Git-Archeology: +> X-Git-Archeology: - Revision 4188a0b260a71cfaebfe37f8c4b43ad48d23ab55: https://github.com/armbian/build/commit/4188a0b260a71cfaebfe37f8c4b43ad48d23ab55 +> X-Git-Archeology: Date: Mon, 05 Nov 2018 13:26:40 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: [espressobin] Cleanup and bump to 4.19.y +> X-Git-Archeology: +> X-Git-Archeology: - Revision 32ce48f01d9d2a999349341d1382b1240858080d: https://github.com/armbian/build/commit/32ce48f01d9d2a999349341d1382b1240858080d +> X-Git-Archeology: Date: Tue, 06 Nov 2018 18:39:31 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: [cubox-i] Drop K3.14.y and move 4.14.y to default, next -> 4.19.y, dev -> 4.19.y + mainline u-boot. Adjust 8188EU for K4.19.y +> X-Git-Archeology: +> X-Git-Archeology: - Revision f04ca8bd587e28fd65b075f0c40fbbfbc21f64e8: https://github.com/armbian/build/commit/f04ca8bd587e28fd65b075f0c40fbbfbc21f64e8 +> X-Git-Archeology: Date: Mon, 12 Nov 2018 17:21:05 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: [mvebu dev] moving to 4.19.y +> X-Git-Archeology: +> X-Git-Archeology: - Revision 78999fc94bdbf2907ae64a2c30437da4c3f1a035: https://github.com/armbian/build/commit/78999fc94bdbf2907ae64a2c30437da4c3f1a035 +> X-Git-Archeology: Date: Tue, 20 Nov 2018 19:56:43 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: [ K4.14 aufs ] Upgrading AUFS patch on kernel 4.14.y +> X-Git-Archeology: +> X-Git-Archeology: - Revision 150ac0c2afa147d9e3b036c8ecd8238fe5648cf3: https://github.com/armbian/build/commit/150ac0c2afa147d9e3b036c8ecd8238fe5648cf3 +> X-Git-Archeology: Date: Tue, 19 Nov 2019 23:25:39 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Remove K<4, change branches, new features (#1586) +> X-Git-Archeology: +> X-Git-Archeology: - Revision c1fbf0ab087e1be71a4b8edcf4736f5a6ffe211a: https://github.com/armbian/build/commit/c1fbf0ab087e1be71a4b8edcf4736f5a6ffe211a +> X-Git-Archeology: Date: Sat, 04 Jan 2020 11:25:11 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Address XU4 instability issues, add upstream patches and update AUFS +> X-Git-Archeology: +> X-Git-Archeology: - Revision 9bb8b71e3b54c60eb895891c5b0bc31a7b90846b: https://github.com/armbian/build/commit/9bb8b71e3b54c60eb895891c5b0bc31a7b90846b +> X-Git-Archeology: Date: Sat, 04 Jan 2020 12:17:01 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Address XU4 instability issues, add upstream patches and update AUFS (#1716) +> X-Git-Archeology: +> X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153 +> X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704) +> X-Git-Archeology: +--- + Documentation/ABI/testing/debugfs-aufs | 55 + + Documentation/ABI/testing/sysfs-aufs | 31 + + Documentation/filesystems/aufs/README | 402 ++ + Documentation/filesystems/aufs/design/01intro.txt | 171 + + Documentation/filesystems/aufs/design/02struct.txt | 258 ++ + Documentation/filesystems/aufs/design/03atomic_open.txt | 85 + + Documentation/filesystems/aufs/design/03lookup.txt | 113 + + Documentation/filesystems/aufs/design/04branch.txt | 74 + + Documentation/filesystems/aufs/design/05wbr_policy.txt | 64 + + Documentation/filesystems/aufs/design/06dirren.dot | 31 + + Documentation/filesystems/aufs/design/06dirren.txt | 102 + + Documentation/filesystems/aufs/design/06fhsm.txt | 120 + + Documentation/filesystems/aufs/design/06mmap.txt | 72 + + Documentation/filesystems/aufs/design/06xattr.txt | 96 + + Documentation/filesystems/aufs/design/07export.txt | 58 + + Documentation/filesystems/aufs/design/08shwh.txt | 52 + + Documentation/filesystems/aufs/design/10dynop.txt | 47 + + MAINTAINERS | 13 + + drivers/block/loop.c | 18 + + fs/Kconfig | 1 + + fs/Makefile | 1 + + fs/aufs/Kconfig | 199 + + fs/aufs/Makefile | 46 + + fs/aufs/aufs.h | 62 + + fs/aufs/branch.c | 1422 +++++++ + fs/aufs/branch.h | 366 ++ + fs/aufs/conf.mk | 40 + + fs/aufs/cpup.c | 1449 +++++++ + fs/aufs/cpup.h | 100 + + fs/aufs/dbgaufs.c | 526 +++ + fs/aufs/dbgaufs.h | 53 + + fs/aufs/dcsub.c | 226 ++ + fs/aufs/dcsub.h | 137 + + fs/aufs/debug.c | 440 +++ + fs/aufs/debug.h | 226 ++ + fs/aufs/dentry.c | 1153 ++++++ + fs/aufs/dentry.h | 268 ++ + fs/aufs/dinfo.c | 554 +++ + fs/aufs/dir.c | 762 ++++ + fs/aufs/dir.h | 134 + + fs/aufs/dirren.c | 1316 +++++++ + fs/aufs/dirren.h | 140 + + fs/aufs/dynop.c | 370 ++ + fs/aufs/dynop.h | 75 + + fs/aufs/export.c | 838 ++++ + fs/aufs/f_op.c | 819 ++++ + fs/aufs/fhsm.c | 428 ++ + fs/aufs/file.c | 863 ++++ + fs/aufs/file.h | 342 ++ + fs/aufs/finfo.c | 149 + + fs/aufs/fstype.h | 401 ++ + fs/aufs/hbl.h | 65 + + fs/aufs/hfsnotify.c | 290 ++ + fs/aufs/hfsplus.c | 60 + + fs/aufs/hnotify.c | 720 ++++ + fs/aufs/i_op.c | 1508 +++++++ + fs/aufs/i_op_add.c | 934 +++++ + fs/aufs/i_op_del.c | 512 +++ + fs/aufs/i_op_ren.c | 1249 ++++++ + fs/aufs/iinfo.c | 286 ++ + fs/aufs/inode.c | 528 +++ + fs/aufs/inode.h | 698 ++++ + fs/aufs/ioctl.c | 220 ++ + fs/aufs/lcnt.h | 186 + + fs/aufs/loop.c | 148 + + fs/aufs/loop.h | 55 + + fs/aufs/magic.mk | 31 + + fs/aufs/module.c | 273 ++ + fs/aufs/module.h | 166 + + fs/aufs/mvdown.c | 705 ++++ + fs/aufs/opts.c | 1880 +++++++++ + fs/aufs/opts.h | 225 ++ + fs/aufs/plink.c | 516 +++ + fs/aufs/poll.c | 54 + + fs/aufs/posix_acl.c | 103 + + fs/aufs/procfs.c | 171 + + fs/aufs/rdu.c | 382 ++ + fs/aufs/rwsem.h | 73 + + fs/aufs/sbinfo.c | 313 ++ + fs/aufs/super.c | 1043 +++++ + fs/aufs/super.h | 589 +++ + fs/aufs/sysaufs.c | 93 + + fs/aufs/sysaufs.h | 102 + + fs/aufs/sysfs.c | 373 ++ + fs/aufs/sysrq.c | 160 + + fs/aufs/vdir.c | 895 +++++ + fs/aufs/vfsub.c | 903 +++++ + fs/aufs/vfsub.h | 362 ++ + fs/aufs/wbr_policy.c | 830 ++++ + fs/aufs/whout.c | 1062 +++++ + fs/aufs/whout.h | 86 + + fs/aufs/wkq.c | 392 ++ + fs/aufs/wkq.h | 89 + + fs/aufs/xattr.c | 356 ++ + fs/aufs/xino.c | 1965 ++++++++++ + fs/dcache.c | 4 +- + fs/exec.c | 1 + + fs/fcntl.c | 5 +- + fs/file_table.c | 4 + + fs/inode.c | 3 +- + fs/namespace.c | 9 + + fs/notify/group.c | 3 + + fs/notify/mark.c | 4 + + fs/open.c | 2 + + fs/proc/base.c | 2 +- + fs/proc/nommu.c | 5 +- + fs/proc/task_mmu.c | 7 +- + fs/proc/task_nommu.c | 5 +- + fs/read_write.c | 26 + + fs/splice.c | 12 +- + fs/sync.c | 3 +- + fs/xattr.c | 1 + + include/linux/file.h | 1 + + include/linux/fs.h | 10 + + include/linux/lockdep.h | 3 + + include/linux/mm.h | 22 + + include/linux/mm_types.h | 2 + + include/linux/mnt_namespace.h | 3 + + include/linux/splice.h | 6 + + include/uapi/linux/aufs_type.h | 452 +++ + kernel/fork.c | 2 +- + kernel/locking/lockdep.c | 4 +- + kernel/task_work.c | 1 + + mm/Makefile | 2 +- + mm/filemap.c | 2 +- + mm/mmap.c | 33 +- + mm/nommu.c | 10 +- + mm/prfile.c | 86 + + security/device_cgroup.c | 1 + + security/security.c | 9 + + 130 files changed, 38133 insertions(+), 31 deletions(-) + diff --git a/Documentation/ABI/testing/debugfs-aufs b/Documentation/ABI/testing/debugfs-aufs new file mode 100644 -index 000000000..4a6694194 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/ABI/testing/debugfs-aufs @@ -0,0 +1,55 @@ @@ -61,7 +354,7 @@ index 000000000..4a6694194 + will be empty. About XINO files, see the aufs manual. diff --git a/Documentation/ABI/testing/sysfs-aufs b/Documentation/ABI/testing/sysfs-aufs new file mode 100644 -index 000000000..82f951849 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-aufs @@ -0,0 +1,31 @@ @@ -98,7 +391,7 @@ index 000000000..82f951849 + will be empty. About XINO files, see the aufs manual. diff --git a/Documentation/filesystems/aufs/README b/Documentation/filesystems/aufs/README new file mode 100644 -index 000000000..029c3e5df +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/README @@ -0,0 +1,402 @@ @@ -506,7 +799,7 @@ index 000000000..029c3e5df +# End: ; diff --git a/Documentation/filesystems/aufs/design/01intro.txt b/Documentation/filesystems/aufs/design/01intro.txt new file mode 100644 -index 000000000..609bf0e9b +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/01intro.txt @@ -0,0 +1,171 @@ @@ -683,7 +976,7 @@ index 000000000..609bf0e9b +about it. But currently I have implemented it in kernel space. diff --git a/Documentation/filesystems/aufs/design/02struct.txt b/Documentation/filesystems/aufs/design/02struct.txt new file mode 100644 -index 000000000..2467788c7 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/02struct.txt @@ -0,0 +1,258 @@ @@ -947,7 +1240,7 @@ index 000000000..2467788c7 +For this purpose, use "aumvdown" command in aufs-util.git. diff --git a/Documentation/filesystems/aufs/design/03atomic_open.txt b/Documentation/filesystems/aufs/design/03atomic_open.txt new file mode 100644 -index 000000000..9f16ac1e0 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/03atomic_open.txt @@ -0,0 +1,85 @@ @@ -1038,7 +1331,7 @@ index 000000000..9f16ac1e0 + be implemented in aufs, but not all I am afraid. diff --git a/Documentation/filesystems/aufs/design/03lookup.txt b/Documentation/filesystems/aufs/design/03lookup.txt new file mode 100644 -index 000000000..08b443d94 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/03lookup.txt @@ -0,0 +1,113 @@ @@ -1157,7 +1450,7 @@ index 000000000..08b443d94 + by over-mounting something (or another method). diff --git a/Documentation/filesystems/aufs/design/04branch.txt b/Documentation/filesystems/aufs/design/04branch.txt new file mode 100644 -index 000000000..3ab3682a4 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/04branch.txt @@ -0,0 +1,74 @@ @@ -1237,7 +1530,7 @@ index 000000000..3ab3682a4 + same named entry on the upper branch. diff --git a/Documentation/filesystems/aufs/design/05wbr_policy.txt b/Documentation/filesystems/aufs/design/05wbr_policy.txt new file mode 100644 -index 000000000..1f9b86bc6 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/05wbr_policy.txt @@ -0,0 +1,64 @@ @@ -1307,7 +1600,7 @@ index 000000000..1f9b86bc6 + copyup policy. diff --git a/Documentation/filesystems/aufs/design/06dirren.dot b/Documentation/filesystems/aufs/design/06dirren.dot new file mode 100644 -index 000000000..2d62bb6dd +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/06dirren.dot @@ -0,0 +1,31 @@ @@ -1344,7 +1637,7 @@ index 000000000..2d62bb6dd +} diff --git a/Documentation/filesystems/aufs/design/06dirren.txt b/Documentation/filesystems/aufs/design/06dirren.txt new file mode 100644 -index 000000000..3b80f8659 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/06dirren.txt @@ -0,0 +1,102 @@ @@ -1452,7 +1745,7 @@ index 000000000..3b80f8659 +equivalen to udba=reval case. diff --git a/Documentation/filesystems/aufs/design/06fhsm.txt b/Documentation/filesystems/aufs/design/06fhsm.txt new file mode 100644 -index 000000000..8b498d0af +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/06fhsm.txt @@ -0,0 +1,120 @@ @@ -1578,7 +1871,7 @@ index 000000000..8b498d0af +should restore the original file state after an error happens. diff --git a/Documentation/filesystems/aufs/design/06mmap.txt b/Documentation/filesystems/aufs/design/06mmap.txt new file mode 100644 -index 000000000..cdd84ea77 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/06mmap.txt @@ -0,0 +1,72 @@ @@ -1656,7 +1949,7 @@ index 000000000..cdd84ea77 +I have to give up this "looks-smater" approach. diff --git a/Documentation/filesystems/aufs/design/06xattr.txt b/Documentation/filesystems/aufs/design/06xattr.txt new file mode 100644 -index 000000000..edd7553f3 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/06xattr.txt @@ -0,0 +1,96 @@ @@ -1758,7 +2051,7 @@ index 000000000..edd7553f3 +now, aufs implements the branch attributes to ignore the error. diff --git a/Documentation/filesystems/aufs/design/07export.txt b/Documentation/filesystems/aufs/design/07export.txt new file mode 100644 -index 000000000..9b983f3dd +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/07export.txt @@ -0,0 +1,58 @@ @@ -1822,7 +2115,7 @@ index 000000000..9b983f3dd + lookup_one_len(), vfs_getattr(), encode_fh() and others. diff --git a/Documentation/filesystems/aufs/design/08shwh.txt b/Documentation/filesystems/aufs/design/08shwh.txt new file mode 100644 -index 000000000..647a86a65 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/08shwh.txt @@ -0,0 +1,52 @@ @@ -1880,7 +2173,7 @@ index 000000000..647a86a65 +initramfs will use it to replace the old one at the next boot. diff --git a/Documentation/filesystems/aufs/design/10dynop.txt b/Documentation/filesystems/aufs/design/10dynop.txt new file mode 100644 -index 000000000..13e8583f2 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/filesystems/aufs/design/10dynop.txt @@ -0,0 +1,47 @@ @@ -1932,7 +2225,7 @@ index 000000000..13e8583f2 +Currently this approach is applied to address_space_operations for +regular files only. diff --git a/MAINTAINERS b/MAINTAINERS -index 029f96c43..4b98496c4 100644 +index 111111111111..222222222222 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2465,6 +2465,19 @@ F: include/linux/audit.h @@ -1956,7 +2249,7 @@ index 029f96c43..4b98496c4 100644 M: Miguel Ojeda Sandonis W: http://miguelojeda.es/auxdisplay.htm diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index 453e3728e..023376f3b 100644 +index 111111111111..222222222222 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -720,6 +720,24 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, @@ -1985,7 +2278,7 @@ index 453e3728e..023376f3b 100644 static ssize_t loop_attr_show(struct device *dev, char *page, diff --git a/fs/Kconfig b/fs/Kconfig -index 7aee6d699..ec9203120 100644 +index 111111111111..222222222222 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -248,6 +248,7 @@ source "fs/pstore/Kconfig" @@ -1997,7 +2290,7 @@ index 7aee6d699..ec9203120 100644 endif # MISC_FILESYSTEMS diff --git a/fs/Makefile b/fs/Makefile -index ef772f1ea..51779e68c 100644 +index 111111111111..222222222222 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -129,3 +129,4 @@ obj-y += exofs/ # Multiple modules @@ -2007,7 +2300,7 @@ index ef772f1ea..51779e68c 100644 +obj-$(CONFIG_AUFS_FS) += aufs/ diff --git a/fs/aufs/Kconfig b/fs/aufs/Kconfig new file mode 100644 -index 000000000..9f4364257 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/Kconfig @@ -0,0 +1,199 @@ @@ -2212,7 +2505,7 @@ index 000000000..9f4364257 +endif diff --git a/fs/aufs/Makefile b/fs/aufs/Makefile new file mode 100644 -index 000000000..2c819a649 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/Makefile @@ -0,0 +1,46 @@ @@ -2264,7 +2557,7 @@ index 000000000..2c819a649 +aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o diff --git a/fs/aufs/aufs.h b/fs/aufs/aufs.h new file mode 100644 -index 000000000..a62a85211 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/aufs.h @@ -0,0 +1,62 @@ @@ -2332,7 +2625,7 @@ index 000000000..a62a85211 +#endif /* __AUFS_H__ */ diff --git a/fs/aufs/branch.c b/fs/aufs/branch.c new file mode 100644 -index 000000000..598cf370a +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/branch.c @@ -0,0 +1,1422 @@ @@ -3760,7 +4053,7 @@ index 000000000..598cf370a +} diff --git a/fs/aufs/branch.h b/fs/aufs/branch.h new file mode 100644 -index 000000000..012459ad5 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/branch.h @@ -0,0 +1,366 @@ @@ -4132,7 +4425,7 @@ index 000000000..012459ad5 +#endif /* __AUFS_BRANCH_H__ */ diff --git a/fs/aufs/conf.mk b/fs/aufs/conf.mk new file mode 100644 -index 000000000..12782f8e0 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/conf.mk @@ -0,0 +1,40 @@ @@ -4178,7 +4471,7 @@ index 000000000..12782f8e0 +-include ${srctree}/${src}/conf_priv.mk diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c new file mode 100644 -index 000000000..8fdaf6329 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/cpup.c @@ -0,0 +1,1449 @@ @@ -5633,7 +5926,7 @@ index 000000000..8fdaf6329 +} diff --git a/fs/aufs/cpup.h b/fs/aufs/cpup.h new file mode 100644 -index 000000000..c932e6b60 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/cpup.h @@ -0,0 +1,100 @@ @@ -5739,7 +6032,7 @@ index 000000000..c932e6b60 +#endif /* __AUFS_CPUP_H__ */ diff --git a/fs/aufs/dbgaufs.c b/fs/aufs/dbgaufs.c new file mode 100644 -index 000000000..e32d91d1f +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dbgaufs.c @@ -0,0 +1,526 @@ @@ -6271,7 +6564,7 @@ index 000000000..e32d91d1f +} diff --git a/fs/aufs/dbgaufs.h b/fs/aufs/dbgaufs.h new file mode 100644 -index 000000000..1ea241bf0 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dbgaufs.h @@ -0,0 +1,53 @@ @@ -6330,7 +6623,7 @@ index 000000000..1ea241bf0 +#endif /* __DBGAUFS_H__ */ diff --git a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c new file mode 100644 -index 000000000..ec5e2bbac +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dcsub.c @@ -0,0 +1,226 @@ @@ -6562,7 +6855,7 @@ index 000000000..ec5e2bbac +} diff --git a/fs/aufs/dcsub.h b/fs/aufs/dcsub.h new file mode 100644 -index 000000000..5e578995c +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dcsub.h @@ -0,0 +1,137 @@ @@ -6705,7 +6998,7 @@ index 000000000..5e578995c +#endif /* __AUFS_DCSUB_H__ */ diff --git a/fs/aufs/debug.c b/fs/aufs/debug.c new file mode 100644 -index 000000000..e8b122e35 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/debug.c @@ -0,0 +1,440 @@ @@ -7151,7 +7444,7 @@ index 000000000..e8b122e35 +} diff --git a/fs/aufs/debug.h b/fs/aufs/debug.h new file mode 100644 -index 000000000..9c52470a6 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/debug.h @@ -0,0 +1,226 @@ @@ -7383,7 +7676,7 @@ index 000000000..9c52470a6 +#endif /* __AUFS_DEBUG_H__ */ diff --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c new file mode 100644 -index 000000000..55bb0dad2 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dentry.c @@ -0,0 +1,1153 @@ @@ -8542,7 +8835,7 @@ index 000000000..55bb0dad2 +}; diff --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h new file mode 100644 -index 000000000..3b443fc7e +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dentry.h @@ -0,0 +1,268 @@ @@ -8816,7 +9109,7 @@ index 000000000..3b443fc7e +#endif /* __AUFS_DENTRY_H__ */ diff --git a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c new file mode 100644 -index 000000000..86140548f +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dinfo.c @@ -0,0 +1,554 @@ @@ -9376,7 +9669,7 @@ index 000000000..86140548f +} diff --git a/fs/aufs/dir.c b/fs/aufs/dir.c new file mode 100644 -index 000000000..ab117dfd4 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dir.c @@ -0,0 +1,762 @@ @@ -10144,7 +10437,7 @@ index 000000000..ab117dfd4 +}; diff --git a/fs/aufs/dir.h b/fs/aufs/dir.h new file mode 100644 -index 000000000..ff578fc5e +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dir.h @@ -0,0 +1,134 @@ @@ -10284,7 +10577,7 @@ index 000000000..ff578fc5e +#endif /* __AUFS_DIR_H__ */ diff --git a/fs/aufs/dirren.c b/fs/aufs/dirren.c new file mode 100644 -index 000000000..0c19b9c73 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dirren.c @@ -0,0 +1,1316 @@ @@ -11606,7 +11899,7 @@ index 000000000..0c19b9c73 +} diff --git a/fs/aufs/dirren.h b/fs/aufs/dirren.h new file mode 100644 -index 000000000..a98673646 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dirren.h @@ -0,0 +1,140 @@ @@ -11752,7 +12045,7 @@ index 000000000..a98673646 +#endif /* __AUFS_DIRREN_H__ */ diff --git a/fs/aufs/dynop.c b/fs/aufs/dynop.c new file mode 100644 -index 000000000..7c7d8432d +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dynop.c @@ -0,0 +1,370 @@ @@ -12128,7 +12421,7 @@ index 000000000..7c7d8432d +} diff --git a/fs/aufs/dynop.h b/fs/aufs/dynop.h new file mode 100644 -index 000000000..f3301c2a6 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/dynop.h @@ -0,0 +1,75 @@ @@ -12209,7 +12502,7 @@ index 000000000..f3301c2a6 +#endif /* __AUFS_DYNOP_H__ */ diff --git a/fs/aufs/export.c b/fs/aufs/export.c new file mode 100644 -index 000000000..1da2ca0a9 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/export.c @@ -0,0 +1,838 @@ @@ -13053,7 +13346,7 @@ index 000000000..1da2ca0a9 +} diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c new file mode 100644 -index 000000000..5254b5cd3 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/f_op.c @@ -0,0 +1,819 @@ @@ -13878,7 +14171,7 @@ index 000000000..5254b5cd3 +}; diff --git a/fs/aufs/fhsm.c b/fs/aufs/fhsm.c new file mode 100644 -index 000000000..d5fca9596 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/fhsm.c @@ -0,0 +1,428 @@ @@ -14312,7 +14605,7 @@ index 000000000..d5fca9596 +} diff --git a/fs/aufs/file.c b/fs/aufs/file.c new file mode 100644 -index 000000000..dbb33855d +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/file.c @@ -0,0 +1,863 @@ @@ -15181,7 +15474,7 @@ index 000000000..dbb33855d +}; diff --git a/fs/aufs/file.h b/fs/aufs/file.h new file mode 100644 -index 000000000..4ee95dde0 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/file.h @@ -0,0 +1,342 @@ @@ -15529,7 +15822,7 @@ index 000000000..4ee95dde0 +#endif /* __AUFS_FILE_H__ */ diff --git a/fs/aufs/finfo.c b/fs/aufs/finfo.c new file mode 100644 -index 000000000..448c5e9cd +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/finfo.c @@ -0,0 +1,149 @@ @@ -15684,7 +15977,7 @@ index 000000000..448c5e9cd +} diff --git a/fs/aufs/fstype.h b/fs/aufs/fstype.h new file mode 100644 -index 000000000..88cfefac7 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/fstype.h @@ -0,0 +1,401 @@ @@ -16091,7 +16384,7 @@ index 000000000..88cfefac7 +#endif /* __AUFS_FSTYPE_H__ */ diff --git a/fs/aufs/hbl.h b/fs/aufs/hbl.h new file mode 100644 -index 000000000..6db65b16b +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/hbl.h @@ -0,0 +1,65 @@ @@ -16162,7 +16455,7 @@ index 000000000..6db65b16b +#endif /* __AUFS_HBL_H__ */ diff --git a/fs/aufs/hfsnotify.c b/fs/aufs/hfsnotify.c new file mode 100644 -index 000000000..e92d73141 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/hfsnotify.c @@ -0,0 +1,290 @@ @@ -16458,7 +16751,7 @@ index 000000000..e92d73141 +}; diff --git a/fs/aufs/hfsplus.c b/fs/aufs/hfsplus.c new file mode 100644 -index 000000000..3bd869a69 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/hfsplus.c @@ -0,0 +1,60 @@ @@ -16524,7 +16817,7 @@ index 000000000..3bd869a69 +} diff --git a/fs/aufs/hnotify.c b/fs/aufs/hnotify.c new file mode 100644 -index 000000000..af35561f3 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/hnotify.c @@ -0,0 +1,720 @@ @@ -17250,7 +17543,7 @@ index 000000000..af35561f3 +} diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c new file mode 100644 -index 000000000..14cbe48ee +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/i_op.c @@ -0,0 +1,1508 @@ @@ -18764,7 +19057,7 @@ index 000000000..14cbe48ee +}; diff --git a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c new file mode 100644 -index 000000000..f8c0724c8 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/i_op_add.c @@ -0,0 +1,934 @@ @@ -19704,7 +19997,7 @@ index 000000000..f8c0724c8 +} diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c new file mode 100644 -index 000000000..f4e2ef352 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/i_op_del.c @@ -0,0 +1,512 @@ @@ -20222,7 +20515,7 @@ index 000000000..f4e2ef352 +} diff --git a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c new file mode 100644 -index 000000000..8524b0852 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/i_op_ren.c @@ -0,0 +1,1249 @@ @@ -21477,7 +21770,7 @@ index 000000000..8524b0852 +} diff --git a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c new file mode 100644 -index 000000000..098fd1150 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/iinfo.c @@ -0,0 +1,286 @@ @@ -21769,7 +22062,7 @@ index 000000000..098fd1150 +} diff --git a/fs/aufs/inode.c b/fs/aufs/inode.c new file mode 100644 -index 000000000..2db13c0aa +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/inode.c @@ -0,0 +1,528 @@ @@ -22303,7 +22596,7 @@ index 000000000..2db13c0aa +} diff --git a/fs/aufs/inode.h b/fs/aufs/inode.h new file mode 100644 -index 000000000..741b5b835 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/inode.h @@ -0,0 +1,698 @@ @@ -23007,7 +23300,7 @@ index 000000000..741b5b835 +#endif /* __AUFS_INODE_H__ */ diff --git a/fs/aufs/ioctl.c b/fs/aufs/ioctl.c new file mode 100644 -index 000000000..fb2fb7582 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/ioctl.c @@ -0,0 +1,220 @@ @@ -23233,7 +23526,7 @@ index 000000000..fb2fb7582 +#endif diff --git a/fs/aufs/lcnt.h b/fs/aufs/lcnt.h new file mode 100644 -index 000000000..d8508f875 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/lcnt.h @@ -0,0 +1,186 @@ @@ -23425,7 +23718,7 @@ index 000000000..d8508f875 +#endif /* __AUFS_LCNT_H__ */ diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c new file mode 100644 -index 000000000..cef7d9636 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/loop.c @@ -0,0 +1,148 @@ @@ -23579,7 +23872,7 @@ index 000000000..cef7d9636 +} diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h new file mode 100644 -index 000000000..7fc394e72 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/loop.h @@ -0,0 +1,55 @@ @@ -23640,7 +23933,7 @@ index 000000000..7fc394e72 +#endif /* __AUFS_LOOP_H__ */ diff --git a/fs/aufs/magic.mk b/fs/aufs/magic.mk new file mode 100644 -index 000000000..7bc9eef3f +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/magic.mk @@ -0,0 +1,31 @@ @@ -23677,7 +23970,7 @@ index 000000000..7bc9eef3f +endif diff --git a/fs/aufs/module.c b/fs/aufs/module.c new file mode 100644 -index 000000000..295736adf +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/module.c @@ -0,0 +1,273 @@ @@ -23956,7 +24249,7 @@ index 000000000..295736adf +module_exit(aufs_exit); diff --git a/fs/aufs/module.h b/fs/aufs/module.h new file mode 100644 -index 000000000..3036754b9 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/module.h @@ -0,0 +1,166 @@ @@ -24128,7 +24421,7 @@ index 000000000..3036754b9 +#endif /* __AUFS_MODULE_H__ */ diff --git a/fs/aufs/mvdown.c b/fs/aufs/mvdown.c new file mode 100644 -index 000000000..59ce2d700 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/mvdown.c @@ -0,0 +1,705 @@ @@ -24839,7 +25132,7 @@ index 000000000..59ce2d700 +} diff --git a/fs/aufs/opts.c b/fs/aufs/opts.c new file mode 100644 -index 000000000..1663e7901 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/opts.c @@ -0,0 +1,1880 @@ @@ -26725,7 +27018,7 @@ index 000000000..1663e7901 +} diff --git a/fs/aufs/opts.h b/fs/aufs/opts.h new file mode 100644 -index 000000000..6326b5434 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/opts.h @@ -0,0 +1,225 @@ @@ -26956,7 +27249,7 @@ index 000000000..6326b5434 +#endif /* __AUFS_OPTS_H__ */ diff --git a/fs/aufs/plink.c b/fs/aufs/plink.c new file mode 100644 -index 000000000..8a3bf96b6 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/plink.c @@ -0,0 +1,516 @@ @@ -27478,7 +27771,7 @@ index 000000000..8a3bf96b6 +} diff --git a/fs/aufs/poll.c b/fs/aufs/poll.c new file mode 100644 -index 000000000..d25202722 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/poll.c @@ -0,0 +1,54 @@ @@ -27538,7 +27831,7 @@ index 000000000..d25202722 +} diff --git a/fs/aufs/posix_acl.c b/fs/aufs/posix_acl.c new file mode 100644 -index 000000000..64c504002 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/posix_acl.c @@ -0,0 +1,103 @@ @@ -27647,7 +27940,7 @@ index 000000000..64c504002 +} diff --git a/fs/aufs/procfs.c b/fs/aufs/procfs.c new file mode 100644 -index 000000000..582dd486f +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/procfs.c @@ -0,0 +1,171 @@ @@ -27824,7 +28117,7 @@ index 000000000..582dd486f +} diff --git a/fs/aufs/rdu.c b/fs/aufs/rdu.c new file mode 100644 -index 000000000..bf0233a28 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/rdu.c @@ -0,0 +1,382 @@ @@ -28212,7 +28505,7 @@ index 000000000..bf0233a28 +#endif diff --git a/fs/aufs/rwsem.h b/fs/aufs/rwsem.h new file mode 100644 -index 000000000..2f8988fa1 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/rwsem.h @@ -0,0 +1,73 @@ @@ -28291,7 +28584,7 @@ index 000000000..2f8988fa1 +#endif /* __AUFS_RWSEM_H__ */ diff --git a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c new file mode 100644 -index 000000000..7318df0fe +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/sbinfo.c @@ -0,0 +1,313 @@ @@ -28610,7 +28903,7 @@ index 000000000..7318df0fe +} diff --git a/fs/aufs/super.c b/fs/aufs/super.c new file mode 100644 -index 000000000..25d8b27ec +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/super.c @@ -0,0 +1,1043 @@ @@ -29659,7 +29952,7 @@ index 000000000..25d8b27ec +}; diff --git a/fs/aufs/super.h b/fs/aufs/super.h new file mode 100644 -index 000000000..74571acf3 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/super.h @@ -0,0 +1,589 @@ @@ -30254,7 +30547,7 @@ index 000000000..74571acf3 +#endif /* __AUFS_SUPER_H__ */ diff --git a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c new file mode 100644 -index 000000000..32a0811c5 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/sysaufs.c @@ -0,0 +1,93 @@ @@ -30353,7 +30646,7 @@ index 000000000..32a0811c5 +} diff --git a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h new file mode 100644 -index 000000000..195fe279b +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/sysaufs.h @@ -0,0 +1,102 @@ @@ -30461,7 +30754,7 @@ index 000000000..195fe279b +#endif /* __SYSAUFS_H__ */ diff --git a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c new file mode 100644 -index 000000000..927f6b252 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/sysfs.c @@ -0,0 +1,373 @@ @@ -30840,7 +31133,7 @@ index 000000000..927f6b252 +} diff --git a/fs/aufs/sysrq.c b/fs/aufs/sysrq.c new file mode 100644 -index 000000000..db10ec528 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/sysrq.c @@ -0,0 +1,160 @@ @@ -31006,7 +31299,7 @@ index 000000000..db10ec528 +} diff --git a/fs/aufs/vdir.c b/fs/aufs/vdir.c new file mode 100644 -index 000000000..13ec60bb4 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/vdir.c @@ -0,0 +1,895 @@ @@ -31907,7 +32200,7 @@ index 000000000..13ec60bb4 +} diff --git a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c new file mode 100644 -index 000000000..a9074da42 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/vfsub.c @@ -0,0 +1,903 @@ @@ -32816,7 +33109,7 @@ index 000000000..a9074da42 +} diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h new file mode 100644 -index 000000000..2953aa410 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/vfsub.h @@ -0,0 +1,362 @@ @@ -33184,7 +33477,7 @@ index 000000000..2953aa410 +#endif /* __AUFS_VFSUB_H__ */ diff --git a/fs/aufs/wbr_policy.c b/fs/aufs/wbr_policy.c new file mode 100644 -index 000000000..64954145c +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/wbr_policy.c @@ -0,0 +1,830 @@ @@ -34020,7 +34313,7 @@ index 000000000..64954145c +}; diff --git a/fs/aufs/whout.c b/fs/aufs/whout.c new file mode 100644 -index 000000000..6c9c85015 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/whout.c @@ -0,0 +1,1062 @@ @@ -35088,7 +35381,7 @@ index 000000000..6c9c85015 +} diff --git a/fs/aufs/whout.h b/fs/aufs/whout.h new file mode 100644 -index 000000000..06f69b24e +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/whout.h @@ -0,0 +1,86 @@ @@ -35180,7 +35473,7 @@ index 000000000..06f69b24e +#endif /* __AUFS_WHOUT_H__ */ diff --git a/fs/aufs/wkq.c b/fs/aufs/wkq.c new file mode 100644 -index 000000000..b0dd8df4e +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/wkq.c @@ -0,0 +1,392 @@ @@ -35578,7 +35871,7 @@ index 000000000..b0dd8df4e +} diff --git a/fs/aufs/wkq.h b/fs/aufs/wkq.h new file mode 100644 -index 000000000..235370d91 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/wkq.h @@ -0,0 +1,89 @@ @@ -35673,7 +35966,7 @@ index 000000000..235370d91 +#endif /* __AUFS_WKQ_H__ */ diff --git a/fs/aufs/xattr.c b/fs/aufs/xattr.c new file mode 100644 -index 000000000..4b25f2f14 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/xattr.c @@ -0,0 +1,356 @@ @@ -36035,7 +36328,7 @@ index 000000000..4b25f2f14 +} diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c new file mode 100644 -index 000000000..35ea33469 +index 000000000000..111111111111 --- /dev/null +++ b/fs/aufs/xino.c @@ -0,0 +1,1965 @@ @@ -38005,7 +38298,7 @@ index 000000000..35ea33469 + return err; +} diff --git a/fs/dcache.c b/fs/dcache.c -index 9ac1290ae..c4fe6f8db 100644 +index 111111111111..222222222222 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1217,7 +1217,7 @@ enum d_walk_ret { @@ -38017,7 +38310,7 @@ index 9ac1290ae..c4fe6f8db 100644 enum d_walk_ret (*enter)(void *, struct dentry *), void (*finish)(void *)) { -@@ -1325,6 +1325,7 @@ static void d_walk(struct dentry *parent, void *data, +@@ -1325,6 +1325,7 @@ rename_retry: seq = 1; goto again; } @@ -38034,7 +38327,7 @@ index 9ac1290ae..c4fe6f8db 100644 /** * d_ancestor - search for an ancestor diff --git a/fs/exec.c b/fs/exec.c -index 7def97f6a..20c38005d 100644 +index 111111111111..222222222222 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -109,6 +109,7 @@ bool path_noexec(const struct path *path) @@ -38046,7 +38339,7 @@ index 7def97f6a..20c38005d 100644 #ifdef CONFIG_USELIB /* diff --git a/fs/fcntl.c b/fs/fcntl.c -index 0345a46b8..e8c9dc38c 100644 +index 111111111111..222222222222 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -32,7 +32,7 @@ @@ -38076,10 +38369,10 @@ index 0345a46b8..e8c9dc38c 100644 static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, int force) diff --git a/fs/file_table.c b/fs/file_table.c -index 61517f57f..c6bab39c1 100644 +index 111111111111..222222222222 100644 --- a/fs/file_table.c +++ b/fs/file_table.c -@@ -148,6 +148,7 @@ struct file *get_empty_filp(void) +@@ -148,6 +148,7 @@ over: } return ERR_PTR(-ENFILE); } @@ -38112,10 +38405,10 @@ index 61517f57f..c6bab39c1 100644 void __init files_init(void) { diff --git a/fs/inode.c b/fs/inode.c -index 76f7535fe..5e0542f25 100644 +index 111111111111..222222222222 100644 --- a/fs/inode.c +++ b/fs/inode.c -@@ -1656,7 +1656,7 @@ EXPORT_SYMBOL(generic_update_time); +@@ -1664,7 +1664,7 @@ EXPORT_SYMBOL(generic_update_time); * This does the actual work of updating an inodes time or version. Must have * had called mnt_want_write() before calling this. */ @@ -38124,7 +38417,7 @@ index 76f7535fe..5e0542f25 100644 { int (*update_time)(struct inode *, struct timespec *, int); -@@ -1665,6 +1665,7 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) +@@ -1673,6 +1673,7 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) return update_time(inode, time, flags); } @@ -38133,7 +38426,7 @@ index 76f7535fe..5e0542f25 100644 /** * touch_atime - update the access time diff --git a/fs/namespace.c b/fs/namespace.c -index e9c13eedd..3e03d3633 100644 +index 111111111111..222222222222 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -517,6 +517,7 @@ void __mnt_drop_write(struct vfsmount *mnt) @@ -38167,7 +38460,7 @@ index e9c13eedd..3e03d3633 100644 static void cleanup_group_ids(struct mount *mnt, struct mount *end) { diff --git a/fs/notify/group.c b/fs/notify/group.c -index 32357534d..952690873 100644 +index 111111111111..222222222222 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -109,6 +109,7 @@ void fsnotify_get_group(struct fsnotify_group *group) @@ -38195,7 +38488,7 @@ index 32357534d..952690873 100644 int fsnotify_fasync(int fd, struct file *file, int on) { diff --git a/fs/notify/mark.c b/fs/notify/mark.c -index 258d99087..cd0dd398f 100644 +index 111111111111..222222222222 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -245,6 +245,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) @@ -38231,7 +38524,7 @@ index 258d99087..cd0dd398f 100644 /* * Destroy all marks in destroy_list, waits for SRCU period to finish before diff --git a/fs/open.c b/fs/open.c -index 29a2cdcbc..41d8c00fb 100644 +index 111111111111..222222222222 100644 --- a/fs/open.c +++ b/fs/open.c @@ -64,6 +64,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, @@ -38251,7 +38544,7 @@ index 29a2cdcbc..41d8c00fb 100644 static int do_dentry_open(struct file *f, struct inode *inode, diff --git a/fs/proc/base.c b/fs/proc/base.c -index 64695dcf8..eeaad0f45 100644 +index 111111111111..222222222222 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2031,7 +2031,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path) @@ -38264,7 +38557,7 @@ index 64695dcf8..eeaad0f45 100644 rc = 0; } diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c -index 75634379f..7c0dc0ff4 100644 +index 111111111111..222222222222 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c @@ -45,7 +45,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region) @@ -38280,7 +38573,7 @@ index 75634379f..7c0dc0ff4 100644 ino = inode->i_ino; } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index 309d24118..c6288e71e 100644 +index 111111111111..222222222222 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -310,7 +310,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) @@ -38305,7 +38598,7 @@ index 309d24118..c6288e71e 100644 struct mm_walk walk = { .hugetlb_entry = gather_hugetlb_stats, diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c -index 5b62f57bd..dfb4a3bd0 100644 +index 111111111111..222222222222 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c @@ -156,7 +156,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma, @@ -38321,7 +38614,7 @@ index 5b62f57bd..dfb4a3bd0 100644 ino = inode->i_ino; pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT; diff --git a/fs/read_write.c b/fs/read_write.c -index e8136a72c..bdb1d223a 100644 +index 111111111111..222222222222 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -454,6 +454,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) @@ -38372,7 +38665,7 @@ index e8136a72c..bdb1d223a 100644 static inline loff_t file_pos_read(struct file *file) { diff --git a/fs/splice.c b/fs/splice.c -index c84ac7e97..3724bd22e 100644 +index 111111111111..222222222222 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -837,8 +837,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); @@ -38413,7 +38706,7 @@ index c84ac7e97..3724bd22e 100644 /** * splice_direct_to_actor - splices data directly between two non-pipes diff --git a/fs/sync.c b/fs/sync.c -index 83ac79a96..e3386eabb 100644 +index 111111111111..222222222222 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -28,7 +28,7 @@ @@ -38434,7 +38727,7 @@ index 83ac79a96..e3386eabb 100644 /* * Write out and wait upon all dirty data associated with this diff --git a/fs/xattr.c b/fs/xattr.c -index 50029811f..ee34b7256 100644 +index 111111111111..222222222222 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -297,6 +297,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, @@ -38446,7 +38739,7 @@ index 50029811f..ee34b7256 100644 ssize_t __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, diff --git a/include/linux/file.h b/include/linux/file.h -index 279720db9..76e38eade 100644 +index 111111111111..222222222222 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -20,6 +20,7 @@ struct dentry; @@ -38458,10 +38751,10 @@ index 279720db9..76e38eade 100644 static inline void fput_light(struct file *file, int fput_needed) { diff --git a/include/linux/fs.h b/include/linux/fs.h -index f0fddf4ea..85ac9197c 100644 +index 111111111111..222222222222 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h -@@ -1270,6 +1270,7 @@ extern void fasync_free(struct fasync_struct *); +@@ -1271,6 +1271,7 @@ extern void fasync_free(struct fasync_struct *); /* can be called from interrupts */ extern void kill_fasync(struct fasync_struct **, int, int); @@ -38469,7 +38762,7 @@ index f0fddf4ea..85ac9197c 100644 extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); extern int f_setown(struct file *filp, unsigned long arg, int force); extern void f_delown(struct file *filp); -@@ -1717,6 +1718,7 @@ struct file_operations { +@@ -1718,6 +1719,7 @@ struct file_operations { ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); @@ -38477,7 +38770,7 @@ index f0fddf4ea..85ac9197c 100644 int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); -@@ -1787,6 +1789,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, +@@ -1788,6 +1790,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, struct iovec *fast_pointer, struct iovec **ret_pointer); @@ -38490,7 +38783,7 @@ index f0fddf4ea..85ac9197c 100644 extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *); extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); -@@ -2191,6 +2199,7 @@ extern int current_umask(void); +@@ -2192,6 +2200,7 @@ extern int current_umask(void); extern void ihold(struct inode * inode); extern void iput(struct inode *); extern int generic_update_time(struct inode *, struct timespec *, int); @@ -38498,7 +38791,7 @@ index f0fddf4ea..85ac9197c 100644 /* /sys/fs */ extern struct kobject *fs_kobj; -@@ -2471,6 +2480,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb) +@@ -2472,6 +2481,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb) return false; } #endif @@ -38507,7 +38800,7 @@ index f0fddf4ea..85ac9197c 100644 extern const struct file_operations def_blk_fops; extern const struct file_operations def_chr_fops; diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h -index f301d31b4..c26f5b420 100644 +index 111111111111..222222222222 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -406,6 +406,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock, @@ -38528,7 +38821,7 @@ index f301d31b4..c26f5b420 100644 #define lockdep_assert_held(l) do { (void)(l); } while (0) diff --git a/include/linux/mm.h b/include/linux/mm.h -index 858ce84ac..977676601 100644 +index 111111111111..222222222222 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1358,6 +1358,28 @@ static inline int fixup_user_fault(struct task_struct *tsk, @@ -38561,7 +38854,7 @@ index 858ce84ac..977676601 100644 unsigned int gup_flags); extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h -index be5d445ba..dca97e717 100644 +index 111111111111..222222222222 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -258,6 +258,7 @@ struct vm_region { @@ -38581,7 +38874,7 @@ index be5d445ba..dca97e717 100644 atomic_long_t swap_readahead_info; diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h -index 35942084c..24f5fd1a7 100644 +index 111111111111..222222222222 100644 --- a/include/linux/mnt_namespace.h +++ b/include/linux/mnt_namespace.h @@ -6,11 +6,14 @@ @@ -38600,7 +38893,7 @@ index 35942084c..24f5fd1a7 100644 extern const struct file_operations proc_mountinfo_operations; extern const struct file_operations proc_mountstats_operations; diff --git a/include/linux/splice.h b/include/linux/splice.h -index 74b4911ac..19789fbea 100644 +index 111111111111..222222222222 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h @@ -87,4 +87,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *); @@ -38616,7 +38909,7 @@ index 74b4911ac..19789fbea 100644 #endif diff --git a/include/uapi/linux/aufs_type.h b/include/uapi/linux/aufs_type.h new file mode 100644 -index 000000000..d8e39df98 +index 000000000000..111111111111 --- /dev/null +++ b/include/uapi/linux/aufs_type.h @@ -0,0 +1,452 @@ @@ -39073,7 +39366,7 @@ index 000000000..d8e39df98 + +#endif /* __AUFS_TYPE_H__ */ diff --git a/kernel/fork.c b/kernel/fork.c -index 0a328cf0c..dc9ce1b30 100644 +index 111111111111..222222222222 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -670,7 +670,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, @@ -39086,7 +39379,7 @@ index 0a328cf0c..dc9ce1b30 100644 atomic_dec(&inode->i_writecount); i_mmap_lock_write(mapping); diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c -index 90a3469a7..6d8e312df 100644 +index 111111111111..222222222222 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -143,7 +143,7 @@ static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES]; @@ -39108,7 +39401,7 @@ index 90a3469a7..6d8e312df 100644 #ifdef CONFIG_LOCK_STAT static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats); diff --git a/kernel/task_work.c b/kernel/task_work.c -index 0fef39566..83fb1ecfc 100644 +index 111111111111..222222222222 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c @@ -116,3 +116,4 @@ void task_work_run(void) @@ -39117,7 +39410,7 @@ index 0fef39566..83fb1ecfc 100644 } +EXPORT_SYMBOL_GPL(task_work_run); diff --git a/mm/Makefile b/mm/Makefile -index e7ebd176f..d6bcfb01b 100644 +index 111111111111..222222222222 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -39,7 +39,7 @@ obj-y := filemap.o mempool.o oom_kill.o \ @@ -39130,7 +39423,7 @@ index e7ebd176f..d6bcfb01b 100644 obj-y += init-mm.o diff --git a/mm/filemap.c b/mm/filemap.c -index a30dbf93d..c1fdca33d 100644 +index 111111111111..222222222222 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2612,7 +2612,7 @@ int filemap_page_mkwrite(struct vm_fault *vmf) @@ -39143,10 +39436,10 @@ index a30dbf93d..c1fdca33d 100644 if (page->mapping != inode->i_mapping) { unlock_page(page); diff --git a/mm/mmap.c b/mm/mmap.c -index db0e29239..60bf78943 100644 +index 111111111111..222222222222 100644 --- a/mm/mmap.c +++ b/mm/mmap.c -@@ -172,7 +172,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) +@@ -166,7 +166,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) if (vma->vm_ops && vma->vm_ops->close) vma->vm_ops->close(vma); if (vma->vm_file) @@ -39155,7 +39448,7 @@ index db0e29239..60bf78943 100644 mpol_put(vma_policy(vma)); kmem_cache_free(vm_area_cachep, vma); return next; -@@ -897,7 +897,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, +@@ -891,7 +891,7 @@ again: if (remove_next) { if (file) { uprobe_munmap(next, next->vm_start, next->vm_end); @@ -39164,7 +39457,7 @@ index db0e29239..60bf78943 100644 } if (next->anon_vma) anon_vma_merge(vma, next); -@@ -1747,8 +1747,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr, +@@ -1773,8 +1773,8 @@ out: return addr; unmap_and_free_vma: @@ -39174,7 +39467,7 @@ index db0e29239..60bf78943 100644 /* Undo any partial mapping done by a device driver. */ unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); -@@ -2575,7 +2575,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -2601,7 +2601,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, goto out_free_mpol; if (new->vm_file) @@ -39183,7 +39476,7 @@ index db0e29239..60bf78943 100644 if (new->vm_ops && new->vm_ops->open) new->vm_ops->open(new); -@@ -2594,7 +2594,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -2620,7 +2620,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, if (new->vm_ops && new->vm_ops->close) new->vm_ops->close(new); if (new->vm_file) @@ -39192,7 +39485,7 @@ index db0e29239..60bf78943 100644 unlink_anon_vmas(new); out_free_mpol: mpol_put(vma_policy(new)); -@@ -2756,7 +2756,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, +@@ -2782,7 +2782,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, struct vm_area_struct *vma; unsigned long populate = 0; unsigned long ret = -EINVAL; @@ -39201,7 +39494,7 @@ index db0e29239..60bf78943 100644 pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.txt.\n", current->comm, current->pid); -@@ -2831,10 +2831,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, +@@ -2857,10 +2857,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, } } @@ -39230,7 +39523,7 @@ index db0e29239..60bf78943 100644 out: up_write(&mm->mmap_sem); if (populate) -@@ -3145,7 +3162,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, +@@ -3171,7 +3188,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, if (anon_vma_clone(new_vma, vma)) goto out_free_mempol; if (new_vma->vm_file) @@ -39240,10 +39533,10 @@ index db0e29239..60bf78943 100644 new_vma->vm_ops->open(new_vma); vma_link(mm, new_vma, prev, rb_link, rb_parent); diff --git a/mm/nommu.c b/mm/nommu.c -index 17c00d93d..4bcdf9448 100644 +index 111111111111..222222222222 100644 --- a/mm/nommu.c +++ b/mm/nommu.c -@@ -641,7 +641,7 @@ static void __put_nommu_region(struct vm_region *region) +@@ -645,7 +645,7 @@ static void __put_nommu_region(struct vm_region *region) up_write(&nommu_region_sem); if (region->vm_file) @@ -39252,7 +39545,7 @@ index 17c00d93d..4bcdf9448 100644 /* IO memory and memory shared directly out of the pagecache * from ramfs/tmpfs mustn't be released here */ -@@ -799,7 +799,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma) +@@ -803,7 +803,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma) if (vma->vm_ops && vma->vm_ops->close) vma->vm_ops->close(vma); if (vma->vm_file) @@ -39261,7 +39554,7 @@ index 17c00d93d..4bcdf9448 100644 put_nommu_region(vma->vm_region); kmem_cache_free(vm_area_cachep, vma); } -@@ -1321,7 +1321,7 @@ unsigned long do_mmap(struct file *file, +@@ -1325,7 +1325,7 @@ unsigned long do_mmap(struct file *file, goto error_just_free; } } @@ -39270,7 +39563,7 @@ index 17c00d93d..4bcdf9448 100644 kmem_cache_free(vm_region_jar, region); region = pregion; result = start; -@@ -1396,10 +1396,10 @@ unsigned long do_mmap(struct file *file, +@@ -1400,10 +1400,10 @@ error_just_free: up_write(&nommu_region_sem); error: if (region->vm_file) @@ -39285,7 +39578,7 @@ index 17c00d93d..4bcdf9448 100644 diff --git a/mm/prfile.c b/mm/prfile.c new file mode 100644 -index 000000000..024cdcfae +index 000000000000..111111111111 --- /dev/null +++ b/mm/prfile.c @@ -0,0 +1,86 @@ @@ -39376,7 +39669,7 @@ index 000000000..024cdcfae +} +#endif /* !CONFIG_MMU */ diff --git a/security/device_cgroup.c b/security/device_cgroup.c -index ea014df89..92120f60e 100644 +index 111111111111..222222222222 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -850,6 +850,7 @@ int __devcgroup_inode_permission(struct inode *inode, int mask) @@ -39388,7 +39681,7 @@ index ea014df89..92120f60e 100644 int devcgroup_inode_mknod(int mode, dev_t dev) { diff --git a/security/security.c b/security/security.c -index 4fbe4e495..640687ed1 100644 +index 111111111111..222222222222 100644 --- a/security/security.c +++ b/security/security.c @@ -532,6 +532,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry) @@ -39463,3 +39756,6 @@ index 4fbe4e495..640687ed1 100644 int security_mmap_addr(unsigned long addr) { +-- +Armbian + diff --git a/patch/kernel/archive/s5p6818-4.14/0147-si2168-fix-cmd-timeout.patch b/patch/kernel/archive/s5p6818-4.14/0147-si2168-fix-cmd-timeout.patch index 453b98a363f4..6921a4213cb1 100644 --- a/patch/kernel/archive/s5p6818-4.14/0147-si2168-fix-cmd-timeout.patch +++ b/patch/kernel/archive/s5p6818-4.14/0147-si2168-fix-cmd-timeout.patch @@ -1,7 +1,7 @@ -From 2e01cc074cc426da4b390af025a736eda9aef80c Mon Sep 17 00:00:00 2001 +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Koumes Date: Sat, 1 Jun 2019 21:20:26 +0000 -Subject: [PATCH] si2168: fix cmd timeout +Subject: si2168: fix cmd timeout Some demuxer si2168 commands may take 130-140 ms. (DVB-T/T2 tuner MyGica T230C v2). @@ -11,7 +11,7 @@ Details: https://github.com/CoreELEC/CoreELEC/pull/208 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c -index b05e6772c..ffaba6f81 100644 +index 111111111111..222222222222 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -42,7 +42,7 @@ static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd) @@ -24,5 +24,5 @@ index b05e6772c..ffaba6f81 100644 while (!time_after(jiffies, timeout)) { ret = i2c_master_recv(client, cmd->args, cmd->rlen); -- -2.17.1 +Armbian diff --git a/patch/kernel/archive/s5p6818-4.14/nexcell-support-v3.patch b/patch/kernel/archive/s5p6818-4.14/nexcell-support-v3.patch index 51e3535bb4a6..9cfff6b1c361 100644 --- a/patch/kernel/archive/s5p6818-4.14/nexcell-support-v3.patch +++ b/patch/kernel/archive/s5p6818-4.14/nexcell-support-v3.patch @@ -1,7 +1,838 @@ -diff -ENwbur a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile ---- a/arch/arm64/boot/dts/Makefile 2018-05-06 08:47:35.345263577 +0200 -+++ b/arch/arm64/boot/dts/Makefile 2018-05-06 08:49:48.242657438 +0200 -@@ -14,6 +14,7 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Igor Pecovnik +Date: Wed, 6 Dec 2017 22:27:43 +0100 +Subject: [ARCHEOLOGY] Added FriendlyARM Nanopi M3 mainline target (NEXT). + Based on @rafaello7 work - kudos! Tested both CLI http://sprunge.us/bHRO and + desktop image: https://www.armbian.com/nanopi-m3 Changed status from CSC to + WIP. + +> X-Git-Archeology: - Revision a134e34af8522a933c701fdbe1151494e79950dc: https://github.com/armbian/build/commit/a134e34af8522a933c701fdbe1151494e79950dc +> X-Git-Archeology: Date: Wed, 06 Dec 2017 22:27:43 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Added FriendlyARM Nanopi M3 mainline target (NEXT). Based on @rafaello7 work - kudos! Tested both CLI http://sprunge.us/bHRO and desktop image: https://www.armbian.com/nanopi-m3 Changed status from CSC to WIP. +> X-Git-Archeology: +> X-Git-Archeology: - Revision 62854bed97e0e91d5e1ee1f0cd44ab091212dcb8: https://github.com/armbian/build/commit/62854bed97e0e91d5e1ee1f0cd44ab091212dcb8 +> X-Git-Archeology: Date: Sun, 31 Dec 2017 14:31:28 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Update Nanopi M3 NEXT patch. +> X-Git-Archeology: +> X-Git-Archeology: - Revision 6fac04fb08d6f296667bcb13d37fe9de7285072e: https://github.com/armbian/build/commit/6fac04fb08d6f296667bcb13d37fe9de7285072e +> X-Git-Archeology: Date: Sat, 27 Jan 2018 22:23:00 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: NanoPI m3 NEXT patches update, docker support +> X-Git-Archeology: +> X-Git-Archeology: - Revision b241f5bca00270fd712f1bbe9d24ac26e4f88828: https://github.com/armbian/build/commit/b241f5bca00270fd712f1bbe9d24ac26e4f88828 +> X-Git-Archeology: Date: Thu, 24 May 2018 15:46:51 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Merge S5P6818 into stable +> X-Git-Archeology: +> X-Git-Archeology: - Revision 150ac0c2afa147d9e3b036c8ecd8238fe5648cf3: https://github.com/armbian/build/commit/150ac0c2afa147d9e3b036c8ecd8238fe5648cf3 +> X-Git-Archeology: Date: Tue, 19 Nov 2019 23:25:39 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Remove K<4, change branches, new features (#1586) +> X-Git-Archeology: +> X-Git-Archeology: - Revision cc0df750bbe0a1b5c139d9f42b6b052b13697f19: https://github.com/armbian/build/commit/cc0df750bbe0a1b5c139d9f42b6b052b13697f19 +> X-Git-Archeology: Date: Sun, 29 Dec 2019 21:39:01 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Adjust s5p6918 general patch and update kernel configuration +> X-Git-Archeology: +> X-Git-Archeology: - Revision 5b7c1131a51c41f1927aff92a3cbfb6d3a841020: https://github.com/armbian/build/commit/5b7c1131a51c41f1927aff92a3cbfb6d3a841020 +> X-Git-Archeology: Date: Sun, 01 Nov 2020 19:54:39 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Detach s5p6818 kernel from specific commit to our private fork +> X-Git-Archeology: +> X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153 +> X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704) +> X-Git-Archeology: +--- + Documentation/devicetree/bindings/pinctrl/nexell,s5p6818-pinctrl.txt | 95 + + Documentation/devicetree/bindings/reset/nexell,reset.txt | 32 + + Makefile | 2 + + arch/arm64/Kconfig | 23 +- + arch/arm64/Kconfig.platforms | 14 + + arch/arm64/boot/dts/Makefile | 1 + + arch/arm64/boot/dts/nexell/Makefile | 5 + + arch/arm64/boot/dts/nexell/s5p6818-nanopi-m3.dts | 750 + + arch/arm64/boot/dts/nexell/s5p6818-pinctrl.dtsi | 519 + + arch/arm64/boot/dts/nexell/s5p6818-soc.dtsi | 667 + + arch/arm64/boot/dts/nexell/s5p6818-tmu-sensor-conf.dtsi | 31 + + arch/arm64/boot/dts/nexell/s5p6818.dtsi | 959 + + arch/arm64/configs/nanopim3_defconfig | 4592 +++ + arch/arm64/include/asm/arch_timer.h | 29 + + arch/arm64/include/asm/tlbflush.h | 25 + + arch/arm64/kernel/time.c | 4 + + arch/arm64/mm/context.c | 11 + + drivers/clk/Makefile | 1 + + drivers/clk/nexell/Makefile | 1 + + drivers/clk/nexell/clk-s5pxx18-pll.c | 838 + + drivers/clk/nexell/clk-s5pxx18-pll.h | 76 + + drivers/clk/nexell/clk-s5pxx18.c | 589 + + drivers/clk/nexell/clk-s5pxx18.h | 159 + + drivers/clocksource/Kconfig | 7 + + drivers/clocksource/Makefile | 1 + + drivers/clocksource/s5pxx18_timer.c | 498 + + drivers/cpufreq/Kconfig.arm | 42 + + drivers/cpufreq/Makefile | 1 + + drivers/cpufreq/nexell-cpufreq.c | 902 + + drivers/cpufreq/s5p6818-cpufreq.h | 302 + + drivers/cpuidle/Kconfig.arm | 7 + + drivers/cpuidle/Makefile | 1 + + drivers/cpuidle/cpuidle-nexell.c | 105 + + drivers/devfreq/Kconfig | 8 + + drivers/devfreq/Makefile | 1 + + drivers/devfreq/nx-devfreq.c | 592 + + drivers/gpu/Makefile | 2 +- + drivers/gpu/arm/Kbuild | 13 + + drivers/gpu/arm/Kconfig | 15 + + drivers/gpu/arm/mali400/.gitignore | 1 + + drivers/gpu/arm/mali400/Kbuild | 261 + + drivers/gpu/arm/mali400/Kconfig | 152 + + drivers/gpu/arm/mali400/Makefile | 206 + + drivers/gpu/arm/mali400/common/mali_broadcast.c | 142 + + drivers/gpu/arm/mali400/common/mali_broadcast.h | 57 + + drivers/gpu/arm/mali400/common/mali_control_timer.c | 128 + + drivers/gpu/arm/mali400/common/mali_control_timer.h | 28 + + drivers/gpu/arm/mali400/common/mali_dlbu.c | 213 + + drivers/gpu/arm/mali400/common/mali_dlbu.h | 45 + + drivers/gpu/arm/mali400/common/mali_dvfs_policy.c | 312 + + drivers/gpu/arm/mali400/common/mali_dvfs_policy.h | 34 + + drivers/gpu/arm/mali400/common/mali_executor.c | 2693 ++ + drivers/gpu/arm/mali400/common/mali_executor.h | 102 + + drivers/gpu/arm/mali400/common/mali_gp.c | 357 + + drivers/gpu/arm/mali400/common/mali_gp.h | 127 + + drivers/gpu/arm/mali400/common/mali_gp_job.c | 302 + + drivers/gpu/arm/mali400/common/mali_gp_job.h | 324 + + drivers/gpu/arm/mali400/common/mali_group.c | 1865 ++ + drivers/gpu/arm/mali400/common/mali_group.h | 460 + + drivers/gpu/arm/mali400/common/mali_hw_core.c | 47 + + drivers/gpu/arm/mali400/common/mali_hw_core.h | 149 + + drivers/gpu/arm/mali400/common/mali_kernel_common.h | 181 + + drivers/gpu/arm/mali400/common/mali_kernel_core.c | 1339 + + drivers/gpu/arm/mali400/common/mali_kernel_core.h | 57 + + drivers/gpu/arm/mali400/common/mali_kernel_utilization.c | 440 + + drivers/gpu/arm/mali400/common/mali_kernel_utilization.h | 72 + + drivers/gpu/arm/mali400/common/mali_kernel_vsync.c | 45 + + drivers/gpu/arm/mali400/common/mali_l2_cache.c | 534 + + drivers/gpu/arm/mali400/common/mali_l2_cache.h | 124 + + drivers/gpu/arm/mali400/common/mali_mem_validation.c | 65 + + drivers/gpu/arm/mali400/common/mali_mem_validation.h | 19 + + drivers/gpu/arm/mali400/common/mali_mmu.c | 433 + + drivers/gpu/arm/mali400/common/mali_mmu.h | 124 + + drivers/gpu/arm/mali400/common/mali_mmu_page_directory.c | 495 + + drivers/gpu/arm/mali400/common/mali_mmu_page_directory.h | 110 + + drivers/gpu/arm/mali400/common/mali_osk.h | 1389 + + drivers/gpu/arm/mali400/common/mali_osk_bitops.h | 162 + + drivers/gpu/arm/mali400/common/mali_osk_list.h | 273 + + drivers/gpu/arm/mali400/common/mali_osk_mali.h | 151 + + drivers/gpu/arm/mali400/common/mali_osk_profiling.h | 146 + + drivers/gpu/arm/mali400/common/mali_osk_types.h | 471 + + drivers/gpu/arm/mali400/common/mali_pm.c | 1362 + + drivers/gpu/arm/mali400/common/mali_pm.h | 91 + + drivers/gpu/arm/mali400/common/mali_pm_domain.c | 209 + + drivers/gpu/arm/mali400/common/mali_pm_domain.h | 104 + + drivers/gpu/arm/mali400/common/mali_pm_metrics.c | 255 + + drivers/gpu/arm/mali400/common/mali_pm_metrics.h | 74 + + drivers/gpu/arm/mali400/common/mali_pmu.c | 270 + + drivers/gpu/arm/mali400/common/mali_pmu.h | 123 + + drivers/gpu/arm/mali400/common/mali_pp.c | 502 + + drivers/gpu/arm/mali400/common/mali_pp.h | 138 + + drivers/gpu/arm/mali400/common/mali_pp_job.c | 315 + + drivers/gpu/arm/mali400/common/mali_pp_job.h | 591 + + drivers/gpu/arm/mali400/common/mali_scheduler.c | 1548 + + drivers/gpu/arm/mali400/common/mali_scheduler.h | 131 + + drivers/gpu/arm/mali400/common/mali_scheduler_types.h | 29 + + drivers/gpu/arm/mali400/common/mali_session.c | 155 + + drivers/gpu/arm/mali400/common/mali_session.h | 136 + + drivers/gpu/arm/mali400/common/mali_soft_job.c | 438 + + drivers/gpu/arm/mali400/common/mali_soft_job.h | 190 + + drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.c | 77 + + drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.h | 70 + + drivers/gpu/arm/mali400/common/mali_timeline.c | 1748 + + drivers/gpu/arm/mali400/common/mali_timeline.h | 548 + + drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.c | 202 + + drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.h | 67 + + drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.c | 158 + + drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.h | 51 + + drivers/gpu/arm/mali400/common/mali_ukk.h | 551 + + drivers/gpu/arm/mali400/common/mali_user_settings_db.c | 147 + + drivers/gpu/arm/mali400/common/mali_user_settings_db.h | 39 + + drivers/gpu/arm/mali400/include/linux/mali/mali_utgard.h | 531 + + drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_ioctl.h | 100 + + drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_events.h | 200 + + drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_gator_api.h | 315 + + drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_uk_types.h | 1100 + + drivers/gpu/arm/mali400/linux/license/gpl/mali_kernel_license.h | 30 + + drivers/gpu/arm/mali400/linux/mali_devfreq.c | 310 + + drivers/gpu/arm/mali400/linux/mali_devfreq.h | 17 + + drivers/gpu/arm/mali400/linux/mali_device_pause_resume.c | 36 + + drivers/gpu/arm/mali400/linux/mali_dma_fence.c | 352 + + drivers/gpu/arm/mali400/linux/mali_dma_fence.h | 109 + + drivers/gpu/arm/mali400/linux/mali_kernel_linux.c | 1154 + + drivers/gpu/arm/mali400/linux/mali_kernel_linux.h | 36 + + drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.c | 1410 + + drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.h | 29 + + drivers/gpu/arm/mali400/linux/mali_linux_trace.h | 158 + + drivers/gpu/arm/mali400/linux/mali_memory.c | 531 + + drivers/gpu/arm/mali400/linux/mali_memory.h | 143 + + drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.c | 362 + + drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.h | 58 + + drivers/gpu/arm/mali400/linux/mali_memory_cow.c | 776 + + drivers/gpu/arm/mali400/linux/mali_memory_cow.h | 48 + + drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.c | 262 + + drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.h | 64 + + drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.c | 369 + + drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.h | 53 + + drivers/gpu/arm/mali400/linux/mali_memory_external.c | 89 + + drivers/gpu/arm/mali400/linux/mali_memory_external.h | 29 + + drivers/gpu/arm/mali400/linux/mali_memory_manager.c | 993 + + drivers/gpu/arm/mali400/linux/mali_memory_manager.h | 51 + + drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.c | 812 + + drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.h | 54 + + drivers/gpu/arm/mali400/linux/mali_memory_secure.c | 169 + + drivers/gpu/arm/mali400/linux/mali_memory_secure.h | 30 + + drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.c | 942 + + drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.h | 121 + + drivers/gpu/arm/mali400/linux/mali_memory_types.h | 219 + + drivers/gpu/arm/mali400/linux/mali_memory_ump.c | 154 + + drivers/gpu/arm/mali400/linux/mali_memory_ump.h | 29 + + drivers/gpu/arm/mali400/linux/mali_memory_util.c | 158 + + drivers/gpu/arm/mali400/linux/mali_memory_util.h | 20 + + drivers/gpu/arm/mali400/linux/mali_memory_virtual.c | 127 + + drivers/gpu/arm/mali400/linux/mali_memory_virtual.h | 35 + + drivers/gpu/arm/mali400/linux/mali_osk_atomics.c | 59 + + drivers/gpu/arm/mali400/linux/mali_osk_bitmap.c | 152 + + drivers/gpu/arm/mali400/linux/mali_osk_irq.c | 200 + + drivers/gpu/arm/mali400/linux/mali_osk_locks.c | 287 + + drivers/gpu/arm/mali400/linux/mali_osk_locks.h | 326 + + drivers/gpu/arm/mali400/linux/mali_osk_low_level_mem.c | 146 + + drivers/gpu/arm/mali400/linux/mali_osk_mali.c | 491 + + drivers/gpu/arm/mali400/linux/mali_osk_math.c | 27 + + drivers/gpu/arm/mali400/linux/mali_osk_memory.c | 61 + + drivers/gpu/arm/mali400/linux/mali_osk_misc.c | 81 + + drivers/gpu/arm/mali400/linux/mali_osk_notification.c | 182 + + drivers/gpu/arm/mali400/linux/mali_osk_pm.c | 83 + + drivers/gpu/arm/mali400/linux/mali_osk_profiling.c | 1282 + + drivers/gpu/arm/mali400/linux/mali_osk_specific.h | 72 + + drivers/gpu/arm/mali400/linux/mali_osk_time.c | 59 + + drivers/gpu/arm/mali400/linux/mali_osk_timers.c | 76 + + drivers/gpu/arm/mali400/linux/mali_osk_wait_queue.c | 78 + + drivers/gpu/arm/mali400/linux/mali_osk_wq.c | 240 + + drivers/gpu/arm/mali400/linux/mali_pmu_power_up_down.c | 23 + + drivers/gpu/arm/mali400/linux/mali_profiling_events.h | 17 + + drivers/gpu/arm/mali400/linux/mali_profiling_gator_api.h | 17 + + drivers/gpu/arm/mali400/linux/mali_profiling_internal.c | 275 + + drivers/gpu/arm/mali400/linux/mali_profiling_internal.h | 35 + + drivers/gpu/arm/mali400/linux/mali_sync.c | 451 + + drivers/gpu/arm/mali400/linux/mali_sync.h | 111 + + drivers/gpu/arm/mali400/linux/mali_uk_types.h | 17 + + drivers/gpu/arm/mali400/linux/mali_ukk_core.c | 146 + + drivers/gpu/arm/mali400/linux/mali_ukk_gp.c | 91 + + drivers/gpu/arm/mali400/linux/mali_ukk_mem.c | 333 + + drivers/gpu/arm/mali400/linux/mali_ukk_pp.c | 105 + + drivers/gpu/arm/mali400/linux/mali_ukk_profiling.c | 183 + + drivers/gpu/arm/mali400/linux/mali_ukk_soft_job.c | 90 + + drivers/gpu/arm/mali400/linux/mali_ukk_timeline.c | 88 + + drivers/gpu/arm/mali400/linux/mali_ukk_vsync.c | 39 + + drivers/gpu/arm/mali400/linux/mali_ukk_wrappers.h | 75 + + drivers/gpu/arm/mali400/platform/arm/arm.c | 623 + + drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.c | 122 + + drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.h | 44 + + drivers/gpu/arm/mali400/platform/arm/juno_opp.c | 127 + + drivers/gpu/arm/mali400/platform/nexell/s5pxx18.c | 309 + + drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.c | 125 + + drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.h | 44 + + drivers/gpu/arm/mali400/readme.txt | 28 + + drivers/gpu/arm/mali400/regs/mali_200_regs.h | 131 + + drivers/gpu/arm/mali400/regs/mali_gp_regs.h | 172 + + drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.c | 13 + + drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.h | 48 + + drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.c | 13 + + drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.h | 26 + + drivers/gpu/drm/Kconfig | 2 + + drivers/gpu/drm/Makefile | 1 + + drivers/gpu/drm/nexell/Kconfig | 51 + + drivers/gpu/drm/nexell/Makefile | 14 + + drivers/gpu/drm/nexell/nx_drm_connector.c | 254 + + drivers/gpu/drm/nexell/nx_drm_connector.h | 41 + + drivers/gpu/drm/nexell/nx_drm_crtc.c | 674 + + drivers/gpu/drm/nexell/nx_drm_crtc.h | 44 + + drivers/gpu/drm/nexell/nx_drm_drv.c | 442 + + drivers/gpu/drm/nexell/nx_drm_drv.h | 39 + + drivers/gpu/drm/nexell/nx_drm_encoder.c | 266 + + drivers/gpu/drm/nexell/nx_drm_encoder.h | 39 + + drivers/gpu/drm/nexell/nx_drm_fb.c | 468 + + drivers/gpu/drm/nexell/nx_drm_fb.h | 62 + + drivers/gpu/drm/nexell/nx_drm_gem.c | 1710 + + drivers/gpu/drm/nexell/nx_drm_gem.h | 95 + + drivers/gpu/drm/nexell/nx_drm_hdmi.c | 731 + + drivers/gpu/drm/nexell/nx_drm_lcd.c | 680 + + drivers/gpu/drm/nexell/nx_drm_plane.c | 218 + + drivers/gpu/drm/nexell/nx_drm_plane.h | 64 + + drivers/gpu/drm/nexell/soc/Makefile | 14 + + drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.c | 891 + + drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.h | 376 + + drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.c | 1001 + + drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.h | 134 + + drivers/gpu/drm/nexell/soc/s5pxx18_dp_lvds.c | 273 + + drivers/gpu/drm/nexell/soc/s5pxx18_dp_mipi.c | 519 + + drivers/gpu/drm/nexell/soc/s5pxx18_dp_rgb.c | 48 + + drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.c | 1282 + + drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.h | 167 + + drivers/gpu/drm/nexell/soc/s5pxx18_hdmi_presets.c | 968 + + drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.c | 71 + + drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.h | 1006 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_disp.h | 35 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.c | 195 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.h | 391 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.c | 319 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.h | 69 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.c | 1580 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.h | 454 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.c | 278 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.h | 93 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.c | 675 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.h | 305 + + drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.c | 1871 ++ + drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.h | 439 + + drivers/gpu/drm/panel/Kconfig | 7 + + drivers/gpu/drm/panel/Makefile | 1 + + drivers/gpu/drm/panel/panel-nanopi.c | 602 + + drivers/hwmon/Kconfig | 7 + + drivers/hwmon/Makefile | 1 + + drivers/hwmon/nanopi-thermistor.c | 240 + + drivers/i2c/busses/i2c-s3c2410.c | 166 +- + drivers/iio/adc/Kconfig | 7 + + drivers/iio/adc/Makefile | 1 + + drivers/iio/adc/nexell_adc.c | 637 + + drivers/input/touchscreen/Kconfig | 47 + + drivers/input/touchscreen/Makefile | 4 + + drivers/input/touchscreen/himax_ts.c | 535 + + drivers/input/touchscreen/it7260_mts.c | 452 + + drivers/input/touchscreen/onewire-touch.c | 96 + + drivers/input/touchscreen/onewire.c | 488 + + drivers/media/platform/Kconfig | 24 + + drivers/media/platform/Makefile | 4 + + drivers/media/platform/nano-videodev/Makefile | 3 + + drivers/media/platform/nano-videodev/nano-videodev-v4l2.c | 1010 + + drivers/media/platform/nano-videodev/s5pxx18_dp_dev.c | 182 + + drivers/media/platform/nano-videodev/s5pxx18_dp_dev.h | 56 + + drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.c | 1818 ++ + drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.h | 431 + + drivers/media/platform/nxp-vpu/Makefile | 13 + + drivers/media/platform/nxp-vpu/blackbird_v2.3.10.h | 15880 ++++++++++ + drivers/media/platform/nxp-vpu/nx_jpu_api.c | 1787 ++ + drivers/media/platform/nxp-vpu/nx_port_func.c | 201 + + drivers/media/platform/nxp-vpu/nx_port_func.h | 106 + + drivers/media/platform/nxp-vpu/nx_vpu_api.c | 661 + + drivers/media/platform/nxp-vpu/nx_vpu_api.h | 541 + + drivers/media/platform/nxp-vpu/nx_vpu_config.h | 111 + + drivers/media/platform/nxp-vpu/nx_vpu_dec_v4l2.c | 1625 + + drivers/media/platform/nxp-vpu/nx_vpu_decoder.c | 1249 + + drivers/media/platform/nxp-vpu/nx_vpu_enc_v4l2.c | 1668 + + drivers/media/platform/nxp-vpu/nx_vpu_encoder.c | 995 + + drivers/media/platform/nxp-vpu/nx_vpu_gdi.c | 670 + + drivers/media/platform/nxp-vpu/nx_vpu_gdi.h | 30 + + drivers/media/platform/nxp-vpu/nx_vpu_v4l2.c | 1496 + + drivers/media/platform/nxp-vpu/nx_vpu_v4l2.h | 279 + + drivers/media/platform/nxp-vpu/regdefine.h | 617 + + drivers/media/platform/nxp-vpu/vpu_hw_interface.c | 97 + + drivers/media/platform/nxp-vpu/vpu_hw_interface.h | 51 + + drivers/media/platform/nxp-vpu/vpu_types.h | 452 + + drivers/media/v4l2-core/v4l2-ioctl.c | 14 + + drivers/mfd/Kconfig | 11 + + drivers/mfd/Makefile | 1 + + drivers/mfd/axp228-mfd.c | 1147 + + drivers/misc/Kconfig | 8 + + drivers/misc/Makefile | 1 + + drivers/misc/nx-scaler.c | 1405 + + drivers/misc/nx-scaler.h | 49 + + drivers/mmc/host/Kconfig | 9 + + drivers/mmc/host/Makefile | 1 + + drivers/mmc/host/dw_mmc-nexell.c | 168 + + drivers/mmc/host/dw_mmc-nexell.h | 30 + + drivers/mmc/host/dw_mmc.c | 9 + + drivers/mmc/host/dw_mmc.h | 2 + + drivers/net/ethernet/stmicro/stmmac/Kconfig | 10 + + drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + + drivers/net/ethernet/stmicro/stmmac/dwmac-nexell.c | 167 + + drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 33 + + drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 5 + + drivers/net/wireless/Kconfig | 1 + + drivers/net/wireless/Makefile | 1 + + drivers/net/wireless/bcm4336/Kconfig | 65 + + drivers/net/wireless/bcm4336/Makefile | 106 + + drivers/net/wireless/bcm4336/aiutils.c | 1097 + + drivers/net/wireless/bcm4336/ap621x.h | 79 + + drivers/net/wireless/bcm4336/bcmevent.c | 185 + + drivers/net/wireless/bcm4336/bcmsdh.c | 698 + + drivers/net/wireless/bcm4336/bcmsdh_linux.c | 463 + + drivers/net/wireless/bcm4336/bcmsdh_sdmmc.c | 1476 + + drivers/net/wireless/bcm4336/bcmsdh_sdmmc_linux.c | 412 + + drivers/net/wireless/bcm4336/bcmutils.c | 3067 ++ + drivers/net/wireless/bcm4336/bcmwifi_channels.c | 1211 + + drivers/net/wireless/bcm4336/circularbuf.c | 324 + + drivers/net/wireless/bcm4336/dhd.h | 1106 + + drivers/net/wireless/bcm4336/dhd_bta.c | 321 + + drivers/net/wireless/bcm4336/dhd_bta.h | 21 + + drivers/net/wireless/bcm4336/dhd_bus.h | 174 + + drivers/net/wireless/bcm4336/dhd_cdc.c | 810 + + drivers/net/wireless/bcm4336/dhd_cfg80211.c | 201 + + drivers/net/wireless/bcm4336/dhd_cfg80211.h | 30 + + drivers/net/wireless/bcm4336/dhd_cfg_vendor.c | 153 + + drivers/net/wireless/bcm4336/dhd_common.c | 2881 ++ + drivers/net/wireless/bcm4336/dhd_config.c | 2154 ++ + drivers/net/wireless/bcm4336/dhd_config.h | 178 + + drivers/net/wireless/bcm4336/dhd_custom_gpio.c | 422 + + drivers/net/wireless/bcm4336/dhd_dbg.h | 107 + + drivers/net/wireless/bcm4336/dhd_flowring.c | 810 + + drivers/net/wireless/bcm4336/dhd_flowring.h | 159 + + drivers/net/wireless/bcm4336/dhd_gpio.c | 148 + + drivers/net/wireless/bcm4336/dhd_ip.c | 1285 + + drivers/net/wireless/bcm4336/dhd_ip.h | 58 + + drivers/net/wireless/bcm4336/dhd_linux.c | 10363 ++++++ + drivers/net/wireless/bcm4336/dhd_linux.h | 82 + + drivers/net/wireless/bcm4336/dhd_linux_platdev.c | 864 + + drivers/net/wireless/bcm4336/dhd_linux_sched.c | 30 + + drivers/net/wireless/bcm4336/dhd_linux_wq.c | 299 + + drivers/net/wireless/bcm4336/dhd_linux_wq.h | 46 + + drivers/net/wireless/bcm4336/dhd_log.c | 58 + + drivers/net/wireless/bcm4336/dhd_msgbuf.c | 4189 +++ + drivers/net/wireless/bcm4336/dhd_pcie.c | 4733 +++ + drivers/net/wireless/bcm4336/dhd_pcie.h | 207 + + drivers/net/wireless/bcm4336/dhd_pcie_linux.c | 1315 + + drivers/net/wireless/bcm4336/dhd_pno.c | 1874 ++ + drivers/net/wireless/bcm4336/dhd_pno.h | 247 + + drivers/net/wireless/bcm4336/dhd_proto.h | 127 + + drivers/net/wireless/bcm4336/dhd_sdio.c | 8693 +++++ + drivers/net/wireless/bcm4336/dhd_static_buf.c | 171 + + drivers/net/wireless/bcm4336/dhd_wlfc.c | 4094 +++ + drivers/net/wireless/bcm4336/dhd_wlfc.h | 505 + + drivers/net/wireless/bcm4336/dngl_stats.h | 25 + + drivers/net/wireless/bcm4336/dngl_wlhdr.h | 22 + + drivers/net/wireless/bcm4336/hnd_pktpool.c | 733 + + drivers/net/wireless/bcm4336/hnd_pktq.c | 586 + + drivers/net/wireless/bcm4336/hndpmu.c | 291 + + drivers/net/wireless/bcm4336/include/Makefile | 53 + + drivers/net/wireless/bcm4336/include/aidmp.h | 368 + + drivers/net/wireless/bcm4336/include/bcm_cfg.h | 11 + + drivers/net/wireless/bcm4336/include/bcm_mpool_pub.h | 343 + + drivers/net/wireless/bcm4336/include/bcmcdc.h | 114 + + drivers/net/wireless/bcm4336/include/bcmdefs.h | 320 + + drivers/net/wireless/bcm4336/include/bcmdevs.h | 1088 + + drivers/net/wireless/bcm4336/include/bcmendian.h | 311 + + drivers/net/wireless/bcm4336/include/bcmmsgbuf.h | 731 + + drivers/net/wireless/bcm4336/include/bcmpcie.h | 203 + + drivers/net/wireless/bcm4336/include/bcmpcispi.h | 163 + + drivers/net/wireless/bcm4336/include/bcmperf.h | 18 + + drivers/net/wireless/bcm4336/include/bcmsdbus.h | 125 + + drivers/net/wireless/bcm4336/include/bcmsdh.h | 239 + + drivers/net/wireless/bcm4336/include/bcmsdh_sdmmc.h | 125 + + drivers/net/wireless/bcm4336/include/bcmsdpcm.h | 260 + + drivers/net/wireless/bcm4336/include/bcmsdspi.h | 117 + + drivers/net/wireless/bcm4336/include/bcmsdstd.h | 264 + + drivers/net/wireless/bcm4336/include/bcmspi.h | 22 + + drivers/net/wireless/bcm4336/include/bcmutils.h | 1156 + + drivers/net/wireless/bcm4336/include/bcmwifi_channels.h | 530 + + drivers/net/wireless/bcm4336/include/bcmwifi_rates.h | 452 + + drivers/net/wireless/bcm4336/include/brcm_nl80211.h | 45 + + drivers/net/wireless/bcm4336/include/circularbuf.h | 97 + + drivers/net/wireless/bcm4336/include/devctrl_if/wlioctl_defs.h | 2103 ++ + drivers/net/wireless/bcm4336/include/dhdioctl.h | 123 + + drivers/net/wireless/bcm4336/include/epivers.h | 30 + + drivers/net/wireless/bcm4336/include/epivers.h.in | 30 + + drivers/net/wireless/bcm4336/include/epivers.sh | 333 + + drivers/net/wireless/bcm4336/include/event_log.h | 293 + + drivers/net/wireless/bcm4336/include/hnd_armtrap.h | 70 + + drivers/net/wireless/bcm4336/include/hnd_cons.h | 59 + + drivers/net/wireless/bcm4336/include/hnd_pktpool.h | 186 + + drivers/net/wireless/bcm4336/include/hnd_pktq.h | 168 + + drivers/net/wireless/bcm4336/include/hndpmu.h | 23 + + drivers/net/wireless/bcm4336/include/hndsoc.h | 268 + + drivers/net/wireless/bcm4336/include/linux_osl.h | 1028 + + drivers/net/wireless/bcm4336/include/linuxver.h | 730 + + drivers/net/wireless/bcm4336/include/miniopt.h | 61 + + drivers/net/wireless/bcm4336/include/msgtrace.h | 60 + + drivers/net/wireless/bcm4336/include/osl.h | 143 + + drivers/net/wireless/bcm4336/include/osl_decl.h | 16 + + drivers/net/wireless/bcm4336/include/packed_section_end.h | 41 + + drivers/net/wireless/bcm4336/include/packed_section_start.h | 45 + + drivers/net/wireless/bcm4336/include/pcicfg.h | 600 + + drivers/net/wireless/bcm4336/include/pcie_core.h | 624 + + drivers/net/wireless/bcm4336/include/proto/802.11.h | 3865 +++ + drivers/net/wireless/bcm4336/include/proto/802.11_bta.h | 27 + + drivers/net/wireless/bcm4336/include/proto/802.11e.h | 120 + + drivers/net/wireless/bcm4336/include/proto/802.1d.h | 32 + + drivers/net/wireless/bcm4336/include/proto/802.3.h | 34 + + drivers/net/wireless/bcm4336/include/proto/bcmdhcp.h | 77 + + drivers/net/wireless/bcm4336/include/proto/bcmeth.h | 94 + + drivers/net/wireless/bcm4336/include/proto/bcmevent.h | 518 + + drivers/net/wireless/bcm4336/include/proto/bcmip.h | 227 + + drivers/net/wireless/bcm4336/include/proto/bcmipv6.h | 142 + + drivers/net/wireless/bcm4336/include/proto/bcmtcp.h | 72 + + drivers/net/wireless/bcm4336/include/proto/bcmudp.h | 46 + + drivers/net/wireless/bcm4336/include/proto/bt_amp_hci.h | 423 + + drivers/net/wireless/bcm4336/include/proto/eapol.h | 194 + + drivers/net/wireless/bcm4336/include/proto/ethernet.h | 210 + + drivers/net/wireless/bcm4336/include/proto/p2p.h | 692 + + drivers/net/wireless/bcm4336/include/proto/sdspi.h | 57 + + drivers/net/wireless/bcm4336/include/proto/vlan.h | 77 + + drivers/net/wireless/bcm4336/include/proto/wpa.h | 199 + + drivers/net/wireless/bcm4336/include/sbchipc.h | 3629 +++ + drivers/net/wireless/bcm4336/include/sbconfig.h | 264 + + drivers/net/wireless/bcm4336/include/sbhnddma.h | 399 + + drivers/net/wireless/bcm4336/include/sbpcmcia.h | 352 + + drivers/net/wireless/bcm4336/include/sbsdio.h | 168 + + drivers/net/wireless/bcm4336/include/sbsdpcmdev.h | 281 + + drivers/net/wireless/bcm4336/include/sbsocram.h | 182 + + drivers/net/wireless/bcm4336/include/sdio.h | 604 + + drivers/net/wireless/bcm4336/include/sdioh.h | 427 + + drivers/net/wireless/bcm4336/include/sdiovar.h | 40 + + drivers/net/wireless/bcm4336/include/siutils.h | 571 + + drivers/net/wireless/bcm4336/include/trxhdr.h | 74 + + drivers/net/wireless/bcm4336/include/typedefs.h | 321 + + drivers/net/wireless/bcm4336/include/wlfc_proto.h | 283 + + drivers/net/wireless/bcm4336/include/wlioctl.h | 5930 ++++ + drivers/net/wireless/bcm4336/linux_osl.c | 2488 ++ + drivers/net/wireless/bcm4336/pcie_core.c | 70 + + drivers/net/wireless/bcm4336/sbutils.c | 1087 + + drivers/net/wireless/bcm4336/siutils.c | 3022 ++ + drivers/net/wireless/bcm4336/siutils_priv.h | 265 + + drivers/net/wireless/bcm4336/uamp_api.h | 160 + + drivers/net/wireless/bcm4336/wl_android.c | 3690 +++ + drivers/net/wireless/bcm4336/wl_android.h | 180 + + drivers/net/wireless/bcm4336/wl_cfg80211.c | 15542 +++++++++ + drivers/net/wireless/bcm4336/wl_cfg80211.h | 1076 + + drivers/net/wireless/bcm4336/wl_cfg_btcoex.c | 538 + + drivers/net/wireless/bcm4336/wl_cfgp2p.c | 2931 ++ + drivers/net/wireless/bcm4336/wl_cfgp2p.h | 398 + + drivers/net/wireless/bcm4336/wl_cfgvendor.h | 33 + + drivers/net/wireless/bcm4336/wl_dbg.h | 392 + + drivers/net/wireless/bcm4336/wl_iw.c | 3909 +++ + drivers/net/wireless/bcm4336/wl_iw.h | 143 + + drivers/net/wireless/bcm4336/wl_linux_mon.c | 385 + + drivers/net/wireless/bcm4336/wldev_common.c | 370 + + drivers/net/wireless/bcm4336/wldev_common.h | 106 + + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 8 +- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 8 + + drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 6 + + drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h | 1 + + drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c | 3 + + drivers/phy/samsung/Kconfig | 6 + + drivers/phy/samsung/Makefile | 1 + + drivers/phy/samsung/phy-nexell-usb2.c | 398 + + drivers/phy/samsung/phy-samsung-usb2.c | 42 +- + drivers/phy/samsung/phy-samsung-usb2.h | 1 + + drivers/pinctrl/Kconfig | 1 + + drivers/pinctrl/Makefile | 1 + + drivers/pinctrl/nexell/Kconfig | 7 + + drivers/pinctrl/nexell/Makefile | 5 + + drivers/pinctrl/nexell/pinctrl-nexell.c | 1196 + + drivers/pinctrl/nexell/pinctrl-nexell.h | 221 + + drivers/pinctrl/nexell/pinctrl-s5pxx18.c | 2143 ++ + drivers/pinctrl/nexell/pinctrl-s5pxx18.h | 101 + + drivers/pinctrl/nexell/s5pxx18-gpio.h | 520 + + drivers/pwm/Kconfig | 2 +- + drivers/pwm/pwm-samsung.c | 325 +- + drivers/regulator/Kconfig | 9 + + drivers/regulator/Makefile | 1 + + drivers/regulator/axp228-regu.c | 814 + + drivers/reset/Makefile | 2 +- + drivers/reset/reset-nexell.c | 192 + + drivers/rtc/Kconfig | 7 + + drivers/rtc/Makefile | 1 + + drivers/rtc/rtc-nx.c | 686 + + drivers/soc/Kconfig | 1 + + drivers/soc/Makefile | 1 + + drivers/soc/nexell/Kconfig | 3 + + drivers/soc/nexell/Makefile | 2 + + drivers/soc/nexell/s5pxx18/Kconfig | 3 + + drivers/soc/nexell/s5pxx18/Makefile | 2 + + drivers/soc/nexell/s5pxx18/cpu-sys.c | 301 + + drivers/soc/nexell/s5pxx18/tieoff_init.c | 163 + + drivers/thermal/Kconfig | 2 +- + drivers/thermal/samsung/exynos_tmu.c | 40 +- + drivers/thermal/samsung/exynos_tmu.h | 1 + + drivers/tty/serial/Kconfig | 3 +- + drivers/tty/serial/samsung.c | 98 + + drivers/tty/serial/samsung.h | 2 + + drivers/usb/dwc2/core.h | 1 + + drivers/usb/dwc2/gadget.c | 22 + + drivers/usb/dwc2/hcd.c | 170 + + drivers/usb/dwc2/params.c | 15 + + drivers/usb/dwc2/platform.c | 37 + + drivers/usb/host/Kconfig | 4 +- + drivers/usb/host/ehci-exynos.c | 39 + + drivers/usb/host/ohci-exynos.c | 20 + + drivers/video/Kconfig | 2 + + include/drm/nexell_drm.h | 23 + + include/dt-bindings/interrupt-controller/s5p6818-irq.h | 137 + + include/dt-bindings/media/nexell-vip.h | 44 + + include/dt-bindings/reset/nexell,s5p6818-reset.h | 88 + + include/dt-bindings/soc/s5p6818-base.h | 395 + + include/dt-bindings/tieoff/s5p6818-tieoff.h | 409 + + include/linux/devfreq.h | 7 + + include/linux/fence.h | 377 + + include/linux/mfd/axp228-cfg.h | 179 + + include/linux/mfd/axp228-mfd.h | 307 + + include/linux/pm_qos.h | 10 + + include/linux/regulator/axp228-regu.h | 197 + + include/linux/soc/nexell/cpufreq.h | 60 + + include/linux/soc/nexell/nx-media-device.h | 28 + + include/linux/soc/nexell/sec_reg.h | 23 + + include/linux/stmmac.h | 4 + + include/soc/nexell/panel-nanopi.h | 33 + + include/soc/nexell/tieoff.h | 16 + + include/uapi/drm/nexell_drm.h | 121 + + include/uapi/linux/nx-scaler.h | 54 + + include/uapi/linux/videodev2_nxp_media.h | 80 + + kernel/power/qos.c | 70 + + mm/page_alloc.c | 18 + + sound/soc/Kconfig | 1 + + sound/soc/Makefile | 1 + + sound/soc/codecs/es8316.c | 7 +- + sound/soc/nexell/Kconfig | 56 + + sound/soc/nexell/Makefile | 22 + + sound/soc/nexell/nexell-alc5658.c | 433 + + sound/soc/nexell/nexell-es8316.c | 462 + + sound/soc/nexell/nexell-i2s.c | 914 + + sound/soc/nexell/nexell-i2s.h | 31 + + sound/soc/nexell/nexell-null.c | 238 + + sound/soc/nexell/nexell-pcm.c | 649 + + sound/soc/nexell/nexell-pcm.h | 80 + + sound/soc/nexell/nexell-spdif-transceiver.c | 137 + + sound/soc/nexell/nexell-spdif.h | 30 + + sound/soc/nexell/nexell-spdiftx.c | 631 + + 557 files changed, 260403 insertions(+), 21 deletions(-) + +diff --git a/Documentation/devicetree/bindings/pinctrl/nexell,s5p6818-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/nexell,s5p6818-pinctrl.txt +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/Documentation/devicetree/bindings/pinctrl/nexell,s5p6818-pinctrl.txt +@@ -0,0 +1,95 @@ ++Binding for Nexell s5p6818 pin cotroller ++======================================== ++ ++Nexell's ARM bases SoC's integrates a GPIO and Pin mux/config hardware ++controller. It controls the input/output settings on the available pads/pins ++and also provides ability to multiplex and configure the output of various ++on-chip controllers onto these pads. ++ ++Please refer to pinctrl-bindings.txt in this directory for details of the ++common pinctrl bindings used by client devices, including the meaning of the ++phrase "pin configuration node". ++ ++ ++Required properties: ++ - compatible: may be "nexell,s5pxx18-pinctrl", "nexell,s5p6818-pinctrl" ++ - reg: should be register base and length as documented in the datasheet ++ - interrupts: interrupt specifier for the controller over gpio and alive pins ++ ++Example: ++pinctrl_0: pinctrl@c0010000 { ++ compatible = "nexell,s5pxx18-pinctrl"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = ; ++ interrupts = <0 IRQ_GPIOA 0>, ++ <0 IRQ_GPIOB 0>, ++ <0 IRQ_GPIOC 0>, ++ <0 IRQ_GPIOD 0>, ++ <0 IRQ_GPIOE 0>, ++ <0 IRQ_ALIVE 0>; ++}; ++ ++ Note: Setting up the order must always match. ++ ++ ++Nexell's pin configuration nodes act as a container for an arbitrary number of ++subnodes. Each of these subnodes represents some desired configuration for a ++pin, a group, or a list of pins or groups. This configuration can include the ++mux function to select on those pin(s)/group(s), and various pin configuration ++parameters. ++ ++ Child nodes must be set at least one of the following settings: ++ - nexell,pins = Select pins for using this function. ++ - nexell,pin-function = Select the function for use in a selected pin. ++ - nexell,pin-pull = Pull up/down configuration. ++ - nexell,pin-strength = Drive strength configuration. ++ ++ Valid values for nexell,pins are: ++ "gpioX-N" : X in {A,B,C,D,E}, N in {0-31} ++ Valid values for nexell,pin-function are: ++ "N" : N in {0-3}. ++ This setting means that the value is different for each pin. ++ Please refer to datasheet. ++ Valid values for nexell,pin-pull are: ++ "N" : 0 - Down, 1 - Up, 2 - Off ++ Valid values for nexell,pin-strength are: ++ "N" : 0,1,2,3 ++ ++ ++Example: ++ - pin settings ++ gmac_txd: gmac-txd { ++ nexell,pins = "gpioe-7", "gpioe-8", "gpioe-9", "gpioe-10"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <3>; ++ }; ++ ++ gmac_rxd: gmac-rxd { ++ nexell,pins = "gpioe-14", "gpioe-15", "gpioe-16", "gpioe-17"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <3>; ++ }; ++ ++ gmac_txen: gmac-txen { ++ nexell,pins = "gpioe-11"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <3>; ++ }; ++ ++ - used by client devices ++ gmac0:ethernet@... { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gmac_txd &gmac_rxd &gmac_txen &gmac_mdc ++ &gmac_mdio &gmac_rxclk &gmac_txclk>; ++ ... ++ }; ++ +diff --git a/Documentation/devicetree/bindings/reset/nexell,reset.txt b/Documentation/devicetree/bindings/reset/nexell,reset.txt +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/Documentation/devicetree/bindings/reset/nexell,reset.txt +@@ -0,0 +1,32 @@ ++Nexell System Reset Controller ++====================================== ++ ++Please also refer to reset.txt in this directory for common reset ++controller binding usage. ++ ++The reset controller registers are part of the system-ctl block on s5pxx18 SoC. ++ ++Required properties: ++- compatible: may be "nexell,s5pxx18-reset" ++- reg: should be register base and length as documented in the datasheet ++- #reset-cells: 1, see below ++ ++Example: ++nexell_reset:reset@c0012000 { ++ #reset-cells = <1>; ++ compatible = "nexell,s5pxx18-reset"; ++ reg = <0xC0012000 0x3>; ++}; ++ ++Specifying reset lines connected to IP modules ++============================================== ++example: ++ ++ serial0:serial@..... { ++ ... ++ resets = <&nexell_reset RESET_ID_UART0>; ++ reset-names = "uart-reset"; ++ ... ++ }; ++ ++The index could be found in . +diff --git a/Makefile b/Makefile +index 111111111111..222222222222 100644 +--- a/Makefile ++++ b/Makefile +@@ -311,7 +311,9 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \ + # Default value for CROSS_COMPILE is not to prefix executables + # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile + ARCH ?= $(SUBARCH) ++ARCH = arm64 + CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) ++CROSS_COMPILE = aarch64-linux-gnu- + + # Architecture as present in compile.h + UTS_MACHINE := $(ARCH) +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index 111111111111..222222222222 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -30,11 +30,11 @@ config ARM64 + select ARCH_WANT_FRAME_POINTERS + select ARCH_HAS_UBSAN_SANITIZE_ALL + select ARM_AMBA +- select ARM_ARCH_TIMER ++ select ARM_ARCH_TIMER if !ARCH_S5P6818 + select ARM_GIC + select AUDIT_ARCH_COMPAT_GENERIC + select ARM_GIC_V2M if PCI +- select ARM_GIC_V3 ++ select ARM_GIC_V3 if !ARCH_S5P6818 + select ARM_GIC_V3_ITS if PCI + select ARM_PSCI_FW + select BUILDTIME_EXTABLE_SORT +@@ -627,6 +627,25 @@ config ARM64_VA_BITS + default 47 if ARM64_VA_BITS_47 + default 48 if ARM64_VA_BITS_48 + ++config ARM64_WORKAROUND_CCI400_DVMV7 ++ bool "Work around for cci400 using dvmv7 protocol" ++ depends on SMP ++ help ++ This option adds an alternative code sequence to work around ARMv8 ++ cores using CCI400 DVMv7 protocol. ++ ++ According to "AMBA AXI and ACE Protocol Specification" chapter C12.4, ++ 12.6, CCI400 optionally supports DVM(Distributed Virtual Message) ++ protocol version8(DVMv8), and version8 supports ARMv8 and ARMv7 but, ++ version7(DVMv7) supports only ARMv7. ++ ++ To work properly with DVMv7 protocol, C12.4 recommends below list. ++ - If upper 8-bits of ASID are zero the message will be received correctly ++ - TLB Invalidation by address range will work incorrectly ++ ++ So, this patch changes available bits of ASID and all tlb flush by address ++ range commands to flush by ASID. ++ + config CPU_BIG_ENDIAN + bool "Build big-endian kernel" + help +diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +index 111111111111..222222222222 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -216,6 +216,20 @@ config ARCH_SPRD + help + Support for Spreadtrum ARM based SoCs + ++config ARCH_S5P6818 ++ bool "NEXELL S5P6818" ++ select ARCH_REQUIRE_GPIOLIB ++ select ARCH_HAS_RESET_CONTROLLER ++ select CLKSRC_NXP_TIMER ++ select RESET_CONTROLLER ++ select PINCTRL ++ select ARM64_ERRATUM_845719 ++ select HAVE_S3C2410_I2C if I2C ++ select HAVE_S3C2410_WATCHDOG if WATCHDOG ++ select ARM64_WORKAROUND_CCI400_DVMV7 ++ help ++ This enables support for the NEXELL S5P6818 Architecture ++ + config ARCH_THUNDER + bool "Cavium Inc. Thunder SoC Family" + help +diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/Makefile ++++ b/arch/arm64/boot/dts/Makefile +@@ -14,6 +14,7 @@ dts-dirs += freescale dts-dirs += hisilicon dts-dirs += marvell dts-dirs += mediatek @@ -9,18 +840,22 @@ diff -ENwbur a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile dts-dirs += nvidia dts-dirs += qcom dts-dirs += realtek -diff -ENwbur a/arch/arm64/boot/dts/nexell/Makefile b/arch/arm64/boot/dts/nexell/Makefile ---- a/arch/arm64/boot/dts/nexell/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/arch/arm64/boot/dts/nexell/Makefile 2018-05-06 08:49:48.254657924 +0200 +diff --git a/arch/arm64/boot/dts/nexell/Makefile b/arch/arm64/boot/dts/nexell/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/arch/arm64/boot/dts/nexell/Makefile @@ -0,0 +1,5 @@ +dtb-$(CONFIG_ARCH_S5P6818) += s5p6818-nanopi-m3.dtb + +always := $(dtb-y) +subdir-y := $(dts-dirs) +clean-files := *.dtb -diff -ENwbur a/arch/arm64/boot/dts/nexell/s5p6818-nanopi-m3.dts b/arch/arm64/boot/dts/nexell/s5p6818-nanopi-m3.dts ---- a/arch/arm64/boot/dts/nexell/s5p6818-nanopi-m3.dts 1970-01-01 01:00:00.000000000 +0100 -+++ b/arch/arm64/boot/dts/nexell/s5p6818-nanopi-m3.dts 2018-05-06 08:49:48.254657924 +0200 +diff --git a/arch/arm64/boot/dts/nexell/s5p6818-nanopi-m3.dts b/arch/arm64/boot/dts/nexell/s5p6818-nanopi-m3.dts +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/arch/arm64/boot/dts/nexell/s5p6818-nanopi-m3.dts @@ -0,0 +1,750 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -772,1376 +1607,415 @@ diff -ENwbur a/arch/arm64/boot/dts/nexell/s5p6818-nanopi-m3.dts b/arch/arm64/boo + }; +}; + -diff -ENwbur a/arch/arm64/boot/dts/nexell/s5p6818.dtsi b/arch/arm64/boot/dts/nexell/s5p6818.dtsi ---- a/arch/arm64/boot/dts/nexell/s5p6818.dtsi 1970-01-01 01:00:00.000000000 +0100 -+++ b/arch/arm64/boot/dts/nexell/s5p6818.dtsi 2018-05-06 08:49:48.254657924 +0200 -@@ -0,0 +1,959 @@ +diff --git a/arch/arm64/boot/dts/nexell/s5p6818-pinctrl.dtsi b/arch/arm64/boot/dts/nexell/s5p6818-pinctrl.dtsi +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/arch/arm64/boot/dts/nexell/s5p6818-pinctrl.dtsi +@@ -0,0 +1,519 @@ +/* -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * Author: Youngbok, Park ++ * Nexell's s5p6818 SoC pin-mux and pin-config device tree source + * -+ * 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. ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * http://www.nexell.co.kr + * -+ * 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. ++ * Nexell's s5p6818 SoC pin-mux and pin-config options are listed as ++ * device tree nodes in this file. + * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++*/ + -+#include -+#include -+#include -+#include -+#include ++pinctrl@C0010000 { ++ gpio_a: gpioa { ++ gpio-controller; ++ #gpio-cells = <2>; + -+/ { -+ model = "nexell soc"; -+ compatible = "nexell,s5p6818"; -+ #address-cells = <0x1>; -+ #size-cells = <0x1>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; + -+ aliases { -+ serial0 = &serial0; -+ serial1 = &serial1; -+ serial2 = &serial2; -+ serial3 = &serial3; -+ serial4 = &serial4; -+ serial5 = &serial5; -+ i2s0 = &i2s_0; -+ i2s1 = &i2s_1; -+ i2s2 = &i2s_2; -+ spi0 = &spi_0; -+ spi1 = &spi_1; -+ spi2 = &spi_2; -+ i2c0 = &i2c_0; -+ i2c1 = &i2c_1; -+ i2c2 = &i2c_2; ++ gpio_b: gpiob { ++ gpio-controller; ++ #gpio-cells = <2>; + -+ pinctrl0 = &pinctrl_0; ++ interrupt-controller; ++ #interrupt-cells = <2>; + }; + -+ psci { -+ compatible = "arm,psci-0.2"; -+ method = "smc"; ++ gpio_c: gpioc { ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ interrupt-controller; ++ #interrupt-cells = <2>; + }; + -+ cpus { -+ #address-cells = <0x2>; -+ #size-cells = <0x0>; ++ gpio_d: gpiod { ++ gpio-controller; ++ #gpio-cells = <2>; + -+ cpu0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53"; -+ reg = <0x0 0x0>; -+ enable-method = "psci"; -+ cpu-release-addr = < 0x1 0xc0010230 >; -+ #cooling-cells = <2>; -+ cpu-idle-states =<&CPU_SLEEP>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ gpio_e: gpioe { ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ alive_0: alive { ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ /* Function mapping from kernel 3.x ++ * pin-function ++ * PAD_FUNC_ALT0 0 ++ * PAD_FUNC_ALT1 1 ++ * PAD_FUNC_ALT2 2 ++ * PAD_FUNC_ALT3 3 ++ * ++ * no control (PINCFG_TYPE_DIR) ++ * PAD_MODE_ALT 0 ++ * PAD_MODE_IN 0 ++ * PAD_MODE_OUT 1 ++ * ++ * no control (PINCFG_TYPE_DAT) ++ * PAD_LEVEL_LOW 0 ++ * PAD_LEVEL_HIGH 1 ++ * ++ * pin-pull ++ * PAD_PULL_DN 0 ++ * PAD_PULL_UP 1 ++ * PAD_PULL_OFF 2 ++ * ++ * pin-strength ++ * PAD_STRENGTH_0 0 ++ * PAD_STRENGTH_1 1 ++ * PAD_STRENGTH_2 2 ++ * PAD_STRENGTH_3 3 ++ */ ++ ++ /* NAND */ ++ nand_default: nand-default { ++ nand_cle: nand-cle { ++ nexell,pins = "gpiob-11"; ++ nexell,pin-function = <0>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; + }; + -+ cpu1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53"; -+ reg = <0x0 0x1>; -+ enable-method = "psci"; -+ cpu-release-addr = < 0x1 0xc0010230 >; -+ cpu-idle-states =<&CPU_SLEEP>; ++ nand_ale: nand-ale { ++ nexell,pins = "gpiob-12"; ++ nexell,pin-function = <0>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; + }; + -+ cpu2: cpu@2 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53"; -+ reg = <0x0 0x2>; -+ enable-method = "psci"; -+ cpu-release-addr = < 0x1 0xc0010230 >; -+ cpu-idle-states =<&CPU_SLEEP>; ++ nand_bus8: nand-bus-width8 { ++ nexell,pins = "gpiob-13", "gpiob-15", "gpiob-17", ++ "gpiob-19", "gpiob-20", "gpiob-21", ++ "gpiob-22", "gpiob-23"; ++ nexell,pin-function = <0>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; + }; + -+ cpu3: cpu@3 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53"; -+ reg = <0x0 0x3>; -+ enable-method = "psci"; -+ cpu-release-addr = < 0x1 0xc0010230 >; -+ cpu-idle-states =<&CPU_SLEEP>; ++ nand_rnb: nand-rnb { ++ nexell,pins = "gpiob-14"; ++ nexell,pin-function = <0>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; + }; + -+ cpu4: cpu@4 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53"; -+ reg = <0x0 0x100>; -+ enable-method = "psci"; -+ cpu-release-addr = < 0x1 0xc0010230 >; -+ cpu-idle-states =<&CPU_SLEEP>; ++ nand_noe: nand-noe { ++ nexell,pins = "gpiob-16"; ++ nexell,pin-function = <0>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; + }; + -+ cpu5: cpu@5 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53"; -+ reg = <0x0 0x101>; -+ enable-method = "psci"; -+ cpu-release-addr = < 0x1 0xc0010230 >; -+ cpu-idle-states =<&CPU_SLEEP>; ++ nand_nwe: nand-nwe { ++ nexell,pins = "gpiob-18"; ++ nexell,pin-function = <0>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; + }; ++ }; + -+ cpu6: cpu@6 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53"; -+ reg = <0x0 0x102>; -+ enable-method = "psci"; -+ cpu-release-addr = < 0x1 0xc0010230 >; -+ cpu-idle-states =<&CPU_SLEEP>; ++ ++ /* GMAC */ ++ gmac_pins: gmac_pins { ++ gmac_txd: gmac-txd { ++ nexell,pins = "gpioe-7", "gpioe-8", "gpioe-9", ++ "gpioe-10"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <3>; + }; + -+ cpu7: cpu@7 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53"; -+ reg = <0x0 0x103>; -+ enable-method = "psci"; -+ cpu-release-addr = < 0x1 0xc0010230 >; -+ cpu-idle-states =<&CPU_SLEEP>; ++ gmac_rxd: gmac-rxd { ++ nexell,pins = "gpioe-14", "gpioe-15", "gpioe-16", ++ "gpioe-17"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <3>; + }; + -+ cpu-map { -+ cluster0 { -+ core0 { -+ cpu = <&cpu0>; -+ }; -+ core1 { -+ cpu = <&cpu1>; -+ }; -+ core2 { -+ cpu = <&cpu2>; -+ }; -+ core3 { -+ cpu = <&cpu3>; -+ }; -+ }; -+ cluster1 { -+ core0 { -+ cpu = <&cpu4>; -+ }; -+ core1 { -+ cpu = <&cpu5>; -+ }; -+ core2 { -+ cpu = <&cpu6>; -+ }; -+ core3 { -+ cpu = <&cpu7>; -+ }; -+ }; ++ gmac_txen: gmac-txen { ++ nexell,pins = "gpioe-11"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <3>; + }; + -+ idle-states { -+ CPU_SLEEP: sleep { -+ compatible = "nexell,idle-state"; -+ arm,psci-suspend-param = <0x0000000>; -+ entry-latency-us = <150>; -+ exit-latency-us = <200>; -+ min-residency-us = <2000>; -+ }; ++ gmac_mdc: gmac-mdc { ++ nexell,pins = "gpioe-20"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <3>; + }; -+ }; + -+ pmu { -+ compatible = "arm,armv8-pmuv3"; -+ interrupt-parent = <&gic>; -+ interrupts = <0 IRQ_P0_PMUIRQ0 0>, -+ <0 IRQ_P0_PMUIRQ1 0>, -+ <0 IRQ_P0_PMUIRQ2 0>, -+ <0 IRQ_P0_PMUIRQ3 0>, -+ <0 IRQ_P1_PMUIRQ0 0>, -+ <0 IRQ_P1_PMUIRQ1 0>, -+ <0 IRQ_P1_PMUIRQ2 0>, -+ <0 IRQ_P1_PMUIRQ3 0>; -+ interrupt-affinity = <&cpu0>, -+ <&cpu1>, -+ <&cpu2>, -+ <&cpu3>, -+ <&cpu4>, -+ <&cpu5>, -+ <&cpu6>, -+ <&cpu7>; ++ gmac_mdio: gmac-mdio { ++ nexell,pins = "gpioe-21"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <3>; ++ }; ++ ++ gmac_rxclk: gmac-rxclk { ++ nexell,pins = "gpioe-18"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <3>; ++ }; ++ ++ gmac_txclk: gmac-txclk { ++ nexell,pins = "gpioe-24"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <2>; ++ }; + }; + -+ refclk:oscillator { -+ compatible = "nexell,s5pxx18,pll"; -+ reg = <0xc0010000 0x1000>; -+ ref-freuecny = <24000000>; ++ /* MMC0 */ ++ sdmmc0_cclk: sdmmc0-cclk { ++ nexell,pins = "gpioa-29"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <2>; + }; + -+ nx-v4l2 { -+ compatible = "nexell,nx-v4l2"; -+ status = "disabled"; ++ sdmmc0_cmd: sdmmc0-cmd { ++ nexell,pins = "gpioa-31"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <1>; + }; + -+ nx-devfreq { -+ compatible = "nexell,s5pxx18-devfreq"; -+ pll = <0>; -+ supply_name = "vdd_arm_regulator"; -+ vdd_arm_regulator-supply = <&VCC_DCDC1>; -+ status = "disabled"; ++ sdmmc0_bus4: sdmmc0-bus-width4 { ++ nexell,pins = "gpiob-1", "gpiob-3", "gpiob-5", "gpiob-7"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <1>; ++ }; ++ /* MMC1 */ ++ sdmmc1_cclk: sdmmc1-cclk { ++ nexell,pins = "gpiod-22"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <2>; + }; + -+ soc { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0xc0000000 0x300000>; -+ interrupt-parent = <&gic>; -+ ranges; ++ sdmmc1_cmd: sdmmc1-cmd { ++ nexell,pins = "gpiod-23"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <1>; ++ }; + -+ #include "s5p6818-soc.dtsi" ++ sdmmc1_bus4: sdmmc1-bus-width4 { ++ nexell,pins = "gpiod-24", "gpiod-25", "gpiod-26", "gpiod-27"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <1>; ++ }; + -+ gic:interrupt-controller@c0009000 { -+ compatible = "arm,gic-400"; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ reg = <0xC0009000 0x1000>, <0xC000a000 0x100>; -+ }; ++ /* MMC2 */ ++ sdmmc2_cclk: sdmmc2-cclk { ++ nexell,pins = "gpioc-18"; ++ nexell,pin-function = <2>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <2>; ++ }; + -+ timer@c0017000 { -+ compatible = "nexell,s5p6818-timer"; -+ reg = ; -+ interrupts = <0 IRQ_TIMER1 0>; -+ clksource = <0>; -+ clkevent = <1>; -+ clocks = <&timer0>, <&timer1>, <&pclk>; -+ clock-names = "timer0", "timer1", "pclk"; -+ }; ++ sdmmc2_cmd: sdmmc2-cmd { ++ nexell,pins = "gpioc-19"; ++ nexell,pin-function = <2>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <1>; ++ }; + -+ tieoff@c0011000 { -+ compatible = "nexell,tieoff"; -+ reg = ; -+ }; ++ sdmmc2_bus4: sdmmc2-bus-width4 { ++ nexell,pins = "gpioc-20", "gpioc-21", "gpioc-22", "gpioc-23"; ++ nexell,pin-function = <2>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <1>; ++ }; + -+ dynamic-freq@bb000 { -+ compatible = "nexell,s5pxx18-cpufreq"; -+ reg = <0xc00bb000 0x30000>; -+ }; ++ sdmmc2_bus8: sdmmc2-bus-width8 { ++ nexell,pins = "gpioe-21", "gpioe-22", "gpioe-23", "gpioe-24"; ++ nexell,pin-function = <2>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <1>; ++ }; + -+ serial0:serial@c00a1000 { -+ compatible = "nexell,s5p6818-uart"; -+ reg = ; -+ interrupts = <0 IRQ_UART0 0>; -+ clock-names = "uart", "clk_uart_baud0"; -+ clocks = <&uart0>, <&uart0>; -+ resets = <&nexell_reset RESET_ID_UART0>; -+ reset-names = "uart-reset"; -+ soc,tieoff = , -+ , -+ ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial0_pin>; -+ status = "disabled"; -+ }; ++ /* serial */ ++ serial0_pin:serial0 { ++ nexell,pins = "gpiod-14", "gpiod-18"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; ++ }; + -+ serial1:serial@c00a0000 { -+ compatible = "nexell,s5p6818-uart"; -+ reg = ; -+ interrupts = <0 IRQ_UART1 0>; -+ clock-names = "uart", "clk_uart_baud0"; -+ clocks = <&uart1>, <&uart1>; -+ resets = <&nexell_reset RESET_ID_UART1>; -+ reset-names = "uart-reset"; -+ soc,tieoff = , -+ , -+ ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial1_pin>; -+ status = "disabled"; -+ }; ++ serial1_pin:serial1 { ++ nexell,pins = "gpiod-15", "gpiod-19"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; ++ }; + -+ serial2:serial@c00a2000 { -+ compatible = "nexell,s5p6818-uart"; -+ reg = ; -+ interrupts = <0 IRQ_UART2 0>; -+ clock-names = "uart", "clk_uart_baud0"; -+ clocks = <&uart2>, <&uart2>; -+ resets = <&nexell_reset RESET_ID_UART2>; -+ reset-names = "uart-reset"; -+ soc,tieoff = , -+ , -+ ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial2_pin>; -+ status = "disabled"; -+ }; ++ serial1_flow:serial1_flow { ++ nexell,pins = "gpioc-5", "gpioc-6"; ++ nexell,pin-function = <2>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; ++ }; + -+ serial3:serial@c00a3000 { -+ compatible = "nexell,s5p6818-uart"; -+ reg = ; -+ interrupts = <0 IRQ_UART3 0>; -+ clock-names = "uart", "clk_uart_baud0"; -+ clocks = <&uart3>, <&uart3>; -+ resets = <&nexell_reset RESET_ID_UART3>; -+ reset-names = "uart-reset"; -+ soc,tieoff = , -+ , -+ ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial3_pin>; -+ status = "disabled"; -+ }; ++ serial2_pin:serial2 { ++ nexell,pins = "gpiod-16", "gpiod-20"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; ++ }; + -+ serial4:serial@c006d000 { -+ compatible = "nexell,s5p6818-uart"; -+ reg = ; -+ interrupts = <0 IRQ_UART4 0>; -+ clock-names = "uart", "clk_uart_baud0"; -+ clocks = <&uart4>, <&uart4>; -+ resets = <&nexell_reset RESET_ID_UART4>; -+ reset-names = "uart-reset"; -+ soc,tieoff = , -+ , -+ ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial4_pin>; -+ status = "disabled"; -+ }; ++ serial3_pin:serial3 { ++ nexell,pins = "gpiod-17", "gpiod-21"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; ++ }; + -+ serial5:serial@c006f000 { -+ compatible = "nexell,s5p6818-uart"; -+ reg = ; -+ interrupts = <0 IRQ_UART5 0>; -+ clock-names = "uart", "clk_uart_baud0"; -+ clocks = <&uart5>, <&uart5>; -+ resets = <&nexell_reset RESET_ID_UART5>; -+ reset-names = "uart-reset"; -+ soc,tieoff = , -+ , -+ ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&serial5_pin>; -+ status = "disabled"; -+ }; ++ serial4_pin:serial4 { ++ nexell,pins = "gpiob-28", "gpiob-29"; ++ nexell,pin-function = <3>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; ++ }; + -+ nexell_reset:reset@c0012000 { -+ #reset-cells = <1>; -+ compatible = "nexell,s5pxx18-reset"; -+ reg = <0xC0012000 0x3>; -+ status = "okay"; -+ }; ++ serial5_pin:serial5 { ++ nexell,pins = "gpiob-30", "gpiob-31"; ++ nexell,pin-function = <3>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; ++ }; + -+ pwm:pwm@c0018000 { -+ compatible = "nexell,s5p6818-pwm"; -+ reg = ; -+ reset-names = "pwm-reset"; -+ resets = <&nexell_reset RESET_ID_PWM>; -+ clock-names = "timers", "pwm-tclk0", "pwm-tclk1"; -+ clocks = <&pclk>, <&pwm0>, <&pwm2>; -+ #pwm-cells = <3>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pwm0_pin &pwm1_pin &pwm2_pin &pwm3_pin>; -+ samsung,pwm-outputs = <0>, <1>, <2>, <3>; -+ status = "disabled"; -+ }; ++ i2c0_pin:i2c0 { ++ nexell,pins = "gpiod-2", "gpiod-3"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; ++ }; + -+ i2c_0:i2c@c00a4000 { -+ compatible = "nexell,s5p6818-i2c"; -+ reg = ; -+ interrupts = <0 IRQ_I2C0 0>; -+ clock-names = "i2c"; -+ clocks = <&i2c0>; -+ samsung,i2c-sda-delay = <100>; -+ samsung,i2c-max-bus-freq = <100000>; -+ samsung,i2c-slave-addr = <0x66>; -+ resets = <&nexell_reset RESET_ID_I2C0>; -+ reset-names = "i2c-reset"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c0_pin>; -+ status = "disabled"; -+ }; ++ i2c1_pin:i2c1 { ++ nexell,pins = "gpiod-4", "gpiod-5"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; ++ }; + -+ i2c_1:i2c@c00a5000 { -+ compatible = "nexell,s5p6818-i2c"; -+ reg = ; -+ interrupts = <0 IRQ_I2C1 0>; -+ clock-names = "i2c"; -+ clocks = <&i2c1>; -+ samsung,i2c-sda-delay = <100>; -+ samsung,i2c-max-bus-freq = <100000>; -+ samsung,i2c-slave-addr = <0x66>; -+ resets = <&nexell_reset RESET_ID_I2C1>; -+ reset-names = "i2c-reset"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c1_pin>; -+ status = "disabled"; -+ }; ++ i2c2_pin:i2c2 { ++ nexell,pins = "gpiod-6", "gpiod-7"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; ++ }; + -+ i2c_2:i2c@c00a6000 { -+ compatible = "nexell,s5p6818-i2c"; -+ reg = ; -+ interrupts = <0 IRQ_I2C2 0>; -+ clock-names = "i2c"; -+ clocks = <&i2c2>; -+ samsung,i2c-sda-delay = <100>; -+ samsung,i2c-max-bus-freq = <100000>; -+ samsung,i2c-slave-addr = <0x66>; -+ resets = <&nexell_reset RESET_ID_I2C2>; -+ reset-names = "i2c-reset"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c2_pin>; -+ status = "disabled"; -+ }; ++ pwm0_pin:pwm0 { ++ nexell,pins = "gpiod-1"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <0>; ++ nexell,pin-strength = <0>; ++ }; + -+ dw_mmc_2:dw_mmc@c0069000 { -+ compatible = "nexell,s5p6818-dw-mshc"; -+ interrupts = <0 IRQ_SDMMC2 0>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = ; -+ resets = <&nexell_reset RESET_ID_SDMMC2>; -+ reset-names = "dw_mmc-reset"; -+ clock-names = "biu","ciu"; -+ clocks = <&sdhc2>, <&sdhc2>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc2_cclk &sdmmc2_cmd &sdmmc2_bus4>; -+ fifo-depth = <0x20>; -+ status = "disabled"; -+ }; ++ pwm1_pin:pwm1 { ++ nexell,pins = "gpioc-13"; ++ nexell,pin-function = <2>; ++ nexell,pin-pull = <0>; ++ nexell,pin-strength = <0>; ++ }; + -+ dw_mmc_1:dw_mmc@c0068000 { -+ compatible = "nexell,s5p6818-dw-mshc"; -+ interrupts = <0 IRQ_SDMMC1 0>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = ; -+ resets = <&nexell_reset RESET_ID_SDMMC1>; -+ reset-names = "dw_mmc-reset"; -+ clock-names = "biu","ciu"; -+ clocks = <&sdhc1>, <&sdhc1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc1_cclk &sdmmc1_cmd &sdmmc1_bus4>; -+ fifo-depth = <0x20>; -+ status = "disabled"; -+ }; ++ pwm2_pin:pwm2 { ++ nexell,pins = "gpioc-14"; ++ nexell,pin-function = <2>; ++ nexell,pin-pull = <0>; ++ nexell,pin-strength = <0>; ++ }; + -+ dw_mmc_0:dw_mmc@c0062000 { -+ compatible = "nexell,s5p6818-dw-mshc"; -+ interrupts = <0 IRQ_SDMMC0 0>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = ; -+ resets = <&nexell_reset RESET_ID_SDMMC0>; -+ reset-names = "dw_mmc-reset"; -+ clock-names = "biu", "ciu"; -+ clocks = <&sdhc0>, <&sdhc0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdmmc0_cclk &sdmmc0_cmd &sdmmc0_bus4>; -+ fifo-depth = <0x20>; -+ status = "disabled"; -+ }; ++ pwm3_pin:pwm3 { ++ nexell,pins = "gpiod-0"; ++ nexell,pin-function = <2>; ++ nexell,pin-pull = <0>; ++ nexell,pin-strength = <0>; ++ }; + -+ i2s_0:i2s@c0055000 { -+ compatible = "nexell,nexell-i2s"; -+ reg = ; -+ dmas = <&pl08xdma0 12 0>, <&pl08xdma0 13 0>; -+ dma-names = "tx", "rx"; -+ clocks = <&i2s0>; -+ clock-names = "i2s0"; -+ resets = <&nexell_reset RESET_ID_I2S0>; -+ reset-names = "i2s-reset"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s0_bus>; -+ master-mode = <1>; -+ mclk-in = <0>; -+ trans-mode = <0>; -+ frame-bit = <32>; -+ sample-rate = <48000>; -+ pre-supply-mclk = <1>; -+ status = "disabled"; -+ }; ++ i2s0_bus:i2s0 { ++ nexell,pins = "gpiod-9", "gpiod-10", "gpiod-11", ++ "gpiod-12", "gpiod-13"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <0>; ++ nexell,pin-strength = <0>; ++ }; + -+ i2s_1:i2s@c0056000 { -+ compatible = "nexell,nexell-i2s"; -+ reg = ; -+ dmas = <&pl08xdma0 14 0>, <&pl08xdma0 15 0>; -+ dma-names = "tx", "rx"; -+ clocks = <&i2s1>; -+ clock-names = "i2s1"; -+ resets = <&nexell_reset RESET_ID_I2S1>; -+ reset-names = "i2s-reset"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s1_bus>; -+ master-mode = <1>; -+ mclk-in = <0>; -+ trans-mode = <0>; -+ frame-bit = <32>; -+ sample-rate = <48000>; -+ pre-supply-mclk = <1>; -+ status = "disabled"; -+ }; ++ i2s1_bus:i2s1 { ++ nexell,pins = "gpioa-28", "gpioa-30", "gpiob-0", ++ "gpiob-6", "gpiob-9"; ++ nexell,pin-function = <3>; ++ nexell,pin-pull = <0>; ++ nexell,pin-strength = <0>; ++ }; + -+ i2s_2:i2s@c0057000 { -+ compatible = "nexell,nexell-i2s"; -+ reg = ; -+ dmas = <&pl08xdma1 0 0>, <&pl08xdma1 1 0>; -+ dma-names = "tx", "rx"; -+ clocks = <&i2s2>; -+ clock-names = "i2s2"; -+ resets = <&nexell_reset RESET_ID_I2S2>; -+ reset-names = "i2s-reset"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s2_bus>; -+ master-mode = <1>; -+ mclk-in = <0>; -+ trans-mode = <0>; -+ frame-bit = <32>; -+ sample-rate = <48000>; -+ pre-supply-mclk = <1>; -+ status = "disabled"; ++ i2s2_bus:i2s2 { ++ i2s2_mclk: i2s2-mclk { ++ nexell,pins = "gpioa-28"; ++ nexell,pin-function = <2>; ++ nexell,pin-pull = <0>; ++ nexell,pin-strength = <0>; + }; + -+ nexell_usbphy: nexell-usbphy@c0012000 { -+ compatible = "nexell,nexell-usb2-phy"; -+ reg = ; -+ clocks = <&usbhost>; -+ clock-names = "phy"; -+ #phy-cells = <1>; -+ status = "disabled"; ++ i2s2_other: i2s2-other { ++ nexell,pins = "gpiob-2", "gpiob-4", ++ "gpiob-8", "gpiob-10"; ++ nexell,pin-function = <3>; ++ nexell,pin-pull = <0>; ++ nexell,pin-strength = <0>; + }; ++ }; + -+ ehci@c0030000 { -+ compatible = "nexell,nexell-ehci"; -+ reg = ; -+ interrupts = <0 IRQ_USB20HOST 0>; -+ clocks = <&usbhost>; -+ clock-names = "usbhost"; -+ resets = <&nexell_reset RESET_ID_USB20HOST>; -+ reset-names = "usbhost-reset"; -+ status = "disabled"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ port@0 { -+ reg = <0>; -+ phys = <&nexell_usbphy 1>; -+ status = "disabled"; -+ }; -+ port@1 { -+ reg = <1>; -+ phys = <&nexell_usbphy 2>; -+ status = "disabled"; -+ }; -+ }; -+ -+ ohci@c0020000 { -+ compatible = "nexell,nexell-ohci"; -+ reg = ; -+ interrupts = <0 IRQ_USB20HOST 0>; -+ clocks = <&usbhost>; -+ clock-names = "usbhost"; -+ resets = <&nexell_reset RESET_ID_USB20HOST>; -+ reset-names = "usbhost-reset"; -+ status = "disabled"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ port@0 { -+ reg = <0>; -+ phys = <&nexell_usbphy 1>; -+ status = "disabled"; -+ }; -+ }; -+ -+ dwc2otg@c0040000 { -+ compatible = "nexell,nexell-dwc2otg"; -+ reg = ; -+ interrupts = <0 IRQ_USB20OTG 0>; -+ clocks = <&otg>; -+ clock-names = "otg"; -+ resets = <&nexell_reset RESET_ID_USB20OTG>; -+ reset-names = "usbotg-reset"; -+ phys = <&nexell_usbphy 0>; -+ phy-names = "usb2-phy"; -+ dr_mode = "otg"; -+ g-use-dma = <1>; -+ g-rx-fifo-size = <1064>; -+ g-np-tx-fifo-size = <512>; -+ g-tx-fifo-size = <512 512 512 512 512 256 256 256 256 -+ 256 64 64 64 64 64>; -+ status = "disabled"; -+ }; -+ -+ gmac0:ethernet@c0060000 { -+ compatible = "nexell,s5p6818-gmac"; -+ clocks = <&pclk>, <&gmac>; -+ clock-names = "stmmaceth", "nexell_gmac_tx"; -+ resets = <&nexell_reset RESET_ID_DWC_GMAC>; -+ reset-names = "stmmaceth"; -+ reg = ; -+ interrupt-parent = <&gic>; -+ interrupts = <0 IRQ_GMAC 0>; -+ interrupt-names = "macirq"; -+ mac-address = [000000000000]; /* Filled in by U-Boot */ -+ phy-mode = "rgmii"; -+ snps,multicast-filter-bins = <256>; -+ status = "disable"; -+ }; -+ -+ adc:adc@c0053000 { -+ compatible = "nexell,s5p6818-adc"; -+ reg = ; -+ interrupts = <0 IRQ_ADC 0>; -+ resets = <&nexell_reset RESET_ID_ADC>; -+ reset-names = "adc-reset"; -+ clocks = <&pclk>; -+ clock-names = "adc"; -+ sample_rate = <200000>; -+ #io-channel-cells = <1>; -+ status = "disabled"; -+ }; -+ -+ spi_0:spi@c005b000 { -+ compatible = "nexell,s5p6818-spi"; -+ reg = ; -+ interrupts = <0 IRQ_SSP0 0>; -+ dmas = <&pl08xdma0 6 0>, <&pl08xdma0 7 0>; -+ dma-names = "tx", "rx"; -+ resets = <&nexell_reset RESET_ID_SSP0_P>, -+ <&nexell_reset RESET_ID_SSP0>; -+ reset-names = "pre-reset","spi-reset"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ samsung,spi-src-clk = <0>; -+ num-cs = <1>; -+ clocks = <&spi0>, <&spi0>; -+ clock-names = "spi", "spi_busclk0"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_bus>; -+ status ="disable"; -+ }; -+ -+ spi_1:spi@c005c000 { -+ compatible = "nexell,s5p6818-spi"; -+ reg = ; -+ interrupts = <0 IRQ_SSP1 0>; -+ dmas = <&pl08xdma0 8 0>, <&pl08xdma0 9 0>; -+ dma-names = "tx", "rx"; -+ resets = <&nexell_reset RESET_ID_SSP1_P>, -+ <&nexell_reset RESET_ID_SSP1>; -+ reset-names = "pre-reset","spi-reset"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ samsung,spi-src-clk = <0>; -+ num-cs = <1>; -+ clocks = <&spi1>, <&spi1>; -+ clock-names = "spi", "spi_busclk0"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi1_bus>; -+ status ="disable"; -+ }; -+ -+ spi_2:spi@c005f000 { -+ compatible = "nexell,s5p6818-spi"; -+ reg = ; -+ interrupts = <0 IRQ_SSP2 0>; -+ dmas = <&pl08xdma0 10 0>, <&pl08xdma0 11 0>; -+ dma-names = "tx", "rx"; -+ resets = <&nexell_reset RESET_ID_SSP2_P>, -+ <&nexell_reset RESET_ID_SSP2>; -+ reset-names = "pre-reset","spi-reset"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ samsung,spi-src-clk = <0>; -+ num-cs = <1>; -+ clocks = <&spi2>, <&spi2>; -+ clock-names = "spi", "spi_busclk0"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi2_bus>; -+ status ="disable"; -+ }; -+ -+ watchdog@c0019000 { -+ compatible = "nexell,nexell-wdt"; -+ reg = ; -+ interrupts = <0 IRQ_WDT 0>; -+ resets = <&nexell_reset RESET_ID_WDT>, -+ <&nexell_reset RESET_ID_WDT_POR>; -+ reset-names = "wdt-reset","wdt-por-reset"; -+ clocks = <&pclk>; -+ clock-names = "watchdog"; -+ status = "disabled"; -+ }; -+ -+ spdif_tx: spdiftx@c0059000 { -+ compatible = "nexell,nexell-spdif-tx"; -+ reg = ; -+ interrupts = <0 IRQ_SPDIFTX 0>; -+ dmas = <&pl08xdma1 6 0>; -+ dma-names = "tx"; -+ resets = <&nexell_reset RESET_ID_SPDIFTX>; -+ reset-names = "spdiftx-reset"; -+ clocks = <&spdiftx>; -+ clock-names = "spdif-tx"; -+ pcm-bit = <16>; -+ sample_rate = <48000>; -+ status = "disabled"; -+ }; -+ -+ tmuctrl_0: tmuctrl@c0096000 { -+ compatible = "nexell,s5p6818-tmu"; -+ reg = ; -+ interrupts = <0 IRQ_TMU0 0>; -+ clocks = <&pclk>; -+ clock-names = "tmu_apbif"; -+ #include "s5p6818-tmu-sensor-conf.dtsi" -+ soc,tieoff = ; -+ status = "disabled"; -+ }; -+ -+ tmuctrl_1: tmuctrl@c0097000 { -+ compatible = "nexell,s5p6818-tmu"; -+ reg = ; -+ interrupts = <0 IRQ_TMU1 0>; -+ clocks = <&pclk>; -+ clock-names = "tmu_apbif"; -+ #include "s5p6818-tmu-sensor-conf.dtsi" -+ soc,tieoff = ; -+ status = "disabled"; -+ }; -+ -+ mipi_csi:mipi_csi@c00d0000 { -+ compatible = "nexell,mipi_csi"; -+ reg = ; -+ clock-names = "mipi"; -+ clocks = <&mipi>; -+ reset-names = "mipi-reset", "mipi_csi-reset", "mipi_phy_s-reset"; -+ resets = <&nexell_reset RESET_ID_MIPI>, -+ <&nexell_reset RESET_ID_MIPI_CSI>, -+ <&nexell_reset RESET_ID_MIPI_PHY_S>; -+ soc,tieoff = ; -+ data_lane = <2>; -+ swap_clocklane = <0>; -+ swap_datalane = <0>; -+ pllval = <750>; -+ status = "disabled"; -+ }; -+ -+ vip_0:vip@c0063000 { -+ compatible = "nexell,vip"; -+ reg = ; -+ interrupts = <0 IRQ_VIP0 0>; -+ clock-names = "vip0"; -+ clocks = <&vip0>; -+ reset-names = "vip0-reset"; -+ resets = <&nexell_reset RESET_ID_VIP0>; -+ module = <0>; -+ status = "disabled"; -+ }; -+ -+ vip_1:vip@c0064000 { -+ compatible = "nexell,vip"; -+ reg = ; -+ interrupts = <0 IRQ_VIP1 0>; -+ clock-names = "vip1"; -+ clocks = <&vip1>; -+ reset-names = "vip1-reset"; -+ resets = <&nexell_reset RESET_ID_VIP1>; -+ module = <1>; -+ status = "disabled"; -+ }; -+ -+ vip_2:vip@c0099000 { -+ compatible = "nexell,vip"; -+ reg = ; -+ interrupts = <0 IRQ_VIP2 0>; -+ clock-names = "vip2"; -+ clocks = <&vip2>; -+ reset-names = "vip2-reset"; -+ resets = <&nexell_reset RESET_ID_VIP2>; -+ module = <2>; -+ status = "disabled"; -+ }; -+ -+ clipper_0:clipper0@c0063000 { -+ compatible = "nexell,nx-clipper"; -+ module = <0>; -+ status = "disabled"; -+ }; -+ -+ clipper_1:clipper1@c0064000 { -+ compatible = "nexell,nx-clipper"; -+ module = <1>; -+ status = "disabled"; -+ }; -+ -+ clipper_2:clipper2@c0064000 { -+ compatible = "nexell,nx-clipper"; -+ module = <2>; -+ status = "disabled"; -+ }; -+ -+ decimator_0:decimator0@c0063000 { -+ compatible = "nexell,nx-decimator"; -+ module = <0>; -+ status = "disabled"; -+ }; -+ -+ dp_drm: display_drm { -+ compatible = "nexell,s5pxx18-drm"; -+ reg = <0xc0102800 0x100>, <0xc0102c00 0x100>, -+ <0xc0102000 0x100>, <0xc0102400 0x100>; -+ reg-names = "dpc.0", "dpc.1", "mlc.0", "mlc.1"; -+ -+ interrupts = < 0 IRQ_DPC_P 0 >, <0 IRQ_DPC_S 0>; -+ interrupts-names = "dpc.0", "dpc.1"; -+ -+ resets = <&nexell_reset RESET_ID_DISPLAY>, -+ <&nexell_reset RESET_ID_DISP_TOP>; -+ reset-names = "rsc-display", "rsc-display-top"; -+ -+ status = "disabled"; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ port@0 { }; -+ port@1 { }; -+ }; -+ }; -+ -+ dp_drm_rgb: display_drm_rgb { -+ compatible = "nexell,s5pxx18-drm-rgb"; -+ reg = <0xc0101000 0x100>; -+ resets = <&nexell_reset RESET_ID_DISP_TOP>; -+ reset-names = "rsc-display-top"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ }; -+ -+ dp_drm_lvds: display_drm_lvds { -+ compatible = "nexell,s5pxx18-drm-lvds"; -+ reg = <0xc0101000 0x100>; -+ resets = <&nexell_reset RESET_ID_DISP_TOP>; -+ reset-names = "rsc-display-top"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ -+ dp-resource { -+ reg_base = <0xc010a000 0x100>; -+ clk_base = <0xc0108000 3>; -+ resets = <&nexell_reset RESET_ID_LVDS>; -+ reset-names = "rsc-lvds-phy"; -+ }; -+ }; -+ -+ dp_drm_mipi: display_drm_mipi { -+ compatible = "nexell,s5pxx18-drm-mipi"; -+ reg = <0xc0101000 0x100>; -+ resets = <&nexell_reset RESET_ID_DISP_TOP>; -+ reset-names = "rsc-display-top"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ -+ dp-resource { -+ reg_base = <0xc00d0000 0x100>; -+ clk_base = <0xc0105000 2>; -+ -+ resets = <&nexell_reset RESET_ID_MIPI>, -+ <&nexell_reset RESET_ID_MIPI_DSI>, -+ <&nexell_reset RESET_ID_MIPI_PHY_S>, -+ <&nexell_reset RESET_ID_MIPI_PHY_M>; -+ reset-names = "rsc-mipi", "rsc-mipi-dsi", -+ "rsc-mipi-phy-s", "rsc-mipi-phy-m"; -+ soc,tieoff = , -+ ; -+ }; -+ }; -+ -+ dp_drm_hdmi: display_drm_hdmi{ -+ compatible = "nexell,s5pxx18-drm-hdmi"; -+ reg = <0xc0101000 0x100>; -+ interrupts = < 0 IRQ_HDMI 0 >; -+ resets = <&nexell_reset RESET_ID_DISP_TOP>; -+ reset-names = "rsc-display-top"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ -+ dp-resource { -+ reg_base = <0xc0000000 0x300000>; -+ clk_base = <0xc0109000 4>, <0xc0105000 2>; -+ resets = <&nexell_reset RESET_ID_HDMI_VIDEO>, -+ <&nexell_reset RESET_ID_HDMI_SPDIF>, -+ <&nexell_reset RESET_ID_HDMI_TMDS>, -+ <&nexell_reset RESET_ID_HDMI>, -+ <&nexell_reset RESET_ID_HDMI_PHY>; -+ reset-names = "rsc-hdmi-video", "rsc-hdmi-spdif", -+ "rsc-hdmi-tmds", "rsc-hdmi", "rsc-hdmi-phy"; -+ soc,tieoff = ; -+ }; -+ }; -+ -+ video-codec@c0080000 { -+ compatible = "nexell, nx-vpu"; -+ reg = <0xc0080000 0x4000>; -+ interrupts = <0 IRQ_CODA960_HOST 0>, -+ <0 IRQ_CODA960_JPG 0>; -+ resets = <&nexell_reset RESET_ID_CODA_A>, -+ <&nexell_reset RESET_ID_CODA_P>, -+ <&nexell_reset RESET_ID_CODA_C>; -+ reset-names = "vpu-a-reset", "vpu-p-reset", -+ "vpu-c-reset"; -+ clocks = <&pclk>, <&bclk>; -+ status = "disabled"; -+ }; -+ -+ rtc@c0010c00 { -+ compatible = "nexell,nx-rtc"; -+ reg = , <0xc0010200 0x100>; -+ interrupts = <0 IRQ_RTC 0>; -+ status = "disabled"; -+ }; -+ -+ scaler@c0066000 { -+ compatible = "nexell,scaler"; -+ reg = ; -+ interrupts = <0 IRQ_SCALER 0>; -+ clock-names = "scaler"; -+ clocks = <&scaler>; -+ reset-names = "scaler-reset"; -+ resets = <&nexell_reset RESET_ID_SCALER>; -+ status = "disabled"; -+ }; -+ -+ gpu@c0070000 { -+ compatible = "arm,mali-400", "arm,mali-utgard"; -+ reg = ; -+ interrupts = <0 IRQ_VR 0>, <0 IRQ_VR 0>, <0 IRQ_VR 0>, -+ <0 IRQ_VR 0>, <0 IRQ_VR 0>, <0 IRQ_VR 0>, -+ <0 IRQ_VR 0>, <0 IRQ_VR 0>, <0 IRQ_VR 0>, -+ <0 IRQ_VR 0>, <0 IRQ_VR 0>; -+ interrupt-names = "IRQGP", "IRQGPMMU", "IRQPP0", -+ "IRQPPMMU0", "IRQPP1", "IRQPPMMU1", -+ "IRQPP2", "IRQPPMMU2", "IRQPP3", -+ "IRQPPMMU3", "IRQPMU"; -+ pmu_domain_config = <0x1 0x4 0x8 0x10 0x20 0x0 0x0 0x0 -+ 0x0 0x2 0x0 0x0>; -+ pmu_switch_delay = <0xff>; -+ clocks = <&vr>; -+ clock-names = "clk_mali"; -+ resets = <&nexell_reset RESET_ID_VR>; -+ reset-names = "vr-reset"; -+ }; -+ }; /*** soc ***/ -+}; -diff -ENwbur a/arch/arm64/boot/dts/nexell/s5p6818-pinctrl.dtsi b/arch/arm64/boot/dts/nexell/s5p6818-pinctrl.dtsi ---- a/arch/arm64/boot/dts/nexell/s5p6818-pinctrl.dtsi 1970-01-01 01:00:00.000000000 +0100 -+++ b/arch/arm64/boot/dts/nexell/s5p6818-pinctrl.dtsi 2018-05-06 08:49:48.254657924 +0200 -@@ -0,0 +1,519 @@ -+/* -+ * Nexell's s5p6818 SoC pin-mux and pin-config device tree source -+ * -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * http://www.nexell.co.kr -+ * -+ * Nexell's s5p6818 SoC pin-mux and pin-config options are listed as -+ * device tree nodes in this file. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+*/ -+ -+pinctrl@C0010000 { -+ gpio_a: gpioa { -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ gpio_b: gpiob { -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ gpio_c: gpioc { -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ gpio_d: gpiod { -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ gpio_e: gpioe { -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ alive_0: alive { -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ }; -+ -+ /* Function mapping from kernel 3.x -+ * pin-function -+ * PAD_FUNC_ALT0 0 -+ * PAD_FUNC_ALT1 1 -+ * PAD_FUNC_ALT2 2 -+ * PAD_FUNC_ALT3 3 -+ * -+ * no control (PINCFG_TYPE_DIR) -+ * PAD_MODE_ALT 0 -+ * PAD_MODE_IN 0 -+ * PAD_MODE_OUT 1 -+ * -+ * no control (PINCFG_TYPE_DAT) -+ * PAD_LEVEL_LOW 0 -+ * PAD_LEVEL_HIGH 1 -+ * -+ * pin-pull -+ * PAD_PULL_DN 0 -+ * PAD_PULL_UP 1 -+ * PAD_PULL_OFF 2 -+ * -+ * pin-strength -+ * PAD_STRENGTH_0 0 -+ * PAD_STRENGTH_1 1 -+ * PAD_STRENGTH_2 2 -+ * PAD_STRENGTH_3 3 -+ */ -+ -+ /* NAND */ -+ nand_default: nand-default { -+ nand_cle: nand-cle { -+ nexell,pins = "gpiob-11"; -+ nexell,pin-function = <0>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ nand_ale: nand-ale { -+ nexell,pins = "gpiob-12"; -+ nexell,pin-function = <0>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ nand_bus8: nand-bus-width8 { -+ nexell,pins = "gpiob-13", "gpiob-15", "gpiob-17", -+ "gpiob-19", "gpiob-20", "gpiob-21", -+ "gpiob-22", "gpiob-23"; -+ nexell,pin-function = <0>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ nand_rnb: nand-rnb { -+ nexell,pins = "gpiob-14"; -+ nexell,pin-function = <0>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ nand_noe: nand-noe { -+ nexell,pins = "gpiob-16"; -+ nexell,pin-function = <0>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ nand_nwe: nand-nwe { -+ nexell,pins = "gpiob-18"; -+ nexell,pin-function = <0>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ }; -+ -+ -+ /* GMAC */ -+ gmac_pins: gmac_pins { -+ gmac_txd: gmac-txd { -+ nexell,pins = "gpioe-7", "gpioe-8", "gpioe-9", -+ "gpioe-10"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <3>; -+ }; -+ -+ gmac_rxd: gmac-rxd { -+ nexell,pins = "gpioe-14", "gpioe-15", "gpioe-16", -+ "gpioe-17"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <3>; -+ }; -+ -+ gmac_txen: gmac-txen { -+ nexell,pins = "gpioe-11"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <3>; -+ }; -+ -+ gmac_mdc: gmac-mdc { -+ nexell,pins = "gpioe-20"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <3>; -+ }; -+ -+ gmac_mdio: gmac-mdio { -+ nexell,pins = "gpioe-21"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <3>; -+ }; -+ -+ gmac_rxclk: gmac-rxclk { -+ nexell,pins = "gpioe-18"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <3>; -+ }; -+ -+ gmac_txclk: gmac-txclk { -+ nexell,pins = "gpioe-24"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <2>; -+ }; -+ }; -+ -+ /* MMC0 */ -+ sdmmc0_cclk: sdmmc0-cclk { -+ nexell,pins = "gpioa-29"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <2>; -+ }; -+ -+ sdmmc0_cmd: sdmmc0-cmd { -+ nexell,pins = "gpioa-31"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <1>; -+ }; -+ -+ sdmmc0_bus4: sdmmc0-bus-width4 { -+ nexell,pins = "gpiob-1", "gpiob-3", "gpiob-5", "gpiob-7"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <1>; -+ }; -+ /* MMC1 */ -+ sdmmc1_cclk: sdmmc1-cclk { -+ nexell,pins = "gpiod-22"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <2>; -+ }; -+ -+ sdmmc1_cmd: sdmmc1-cmd { -+ nexell,pins = "gpiod-23"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <1>; -+ }; -+ -+ sdmmc1_bus4: sdmmc1-bus-width4 { -+ nexell,pins = "gpiod-24", "gpiod-25", "gpiod-26", "gpiod-27"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <1>; -+ }; -+ -+ /* MMC2 */ -+ sdmmc2_cclk: sdmmc2-cclk { -+ nexell,pins = "gpioc-18"; -+ nexell,pin-function = <2>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <2>; -+ }; -+ -+ sdmmc2_cmd: sdmmc2-cmd { -+ nexell,pins = "gpioc-19"; -+ nexell,pin-function = <2>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <1>; -+ }; -+ -+ sdmmc2_bus4: sdmmc2-bus-width4 { -+ nexell,pins = "gpioc-20", "gpioc-21", "gpioc-22", "gpioc-23"; -+ nexell,pin-function = <2>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <1>; -+ }; -+ -+ sdmmc2_bus8: sdmmc2-bus-width8 { -+ nexell,pins = "gpioe-21", "gpioe-22", "gpioe-23", "gpioe-24"; -+ nexell,pin-function = <2>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <1>; -+ }; -+ -+ /* serial */ -+ serial0_pin:serial0 { -+ nexell,pins = "gpiod-14", "gpiod-18"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ serial1_pin:serial1 { -+ nexell,pins = "gpiod-15", "gpiod-19"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ serial1_flow:serial1_flow { -+ nexell,pins = "gpioc-5", "gpioc-6"; -+ nexell,pin-function = <2>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ serial2_pin:serial2 { -+ nexell,pins = "gpiod-16", "gpiod-20"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ serial3_pin:serial3 { -+ nexell,pins = "gpiod-17", "gpiod-21"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ serial4_pin:serial4 { -+ nexell,pins = "gpiob-28", "gpiob-29"; -+ nexell,pin-function = <3>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ serial5_pin:serial5 { -+ nexell,pins = "gpiob-30", "gpiob-31"; -+ nexell,pin-function = <3>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ i2c0_pin:i2c0 { -+ nexell,pins = "gpiod-2", "gpiod-3"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ i2c1_pin:i2c1 { -+ nexell,pins = "gpiod-4", "gpiod-5"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ i2c2_pin:i2c2 { -+ nexell,pins = "gpiod-6", "gpiod-7"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ pwm0_pin:pwm0 { -+ nexell,pins = "gpiod-1"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <0>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ pwm1_pin:pwm1 { -+ nexell,pins = "gpioc-13"; -+ nexell,pin-function = <2>; -+ nexell,pin-pull = <0>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ pwm2_pin:pwm2 { -+ nexell,pins = "gpioc-14"; -+ nexell,pin-function = <2>; -+ nexell,pin-pull = <0>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ pwm3_pin:pwm3 { -+ nexell,pins = "gpiod-0"; -+ nexell,pin-function = <2>; -+ nexell,pin-pull = <0>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ i2s0_bus:i2s0 { -+ nexell,pins = "gpiod-9", "gpiod-10", "gpiod-11", -+ "gpiod-12", "gpiod-13"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <0>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ i2s1_bus:i2s1 { -+ nexell,pins = "gpioa-28", "gpioa-30", "gpiob-0", -+ "gpiob-6", "gpiob-9"; -+ nexell,pin-function = <3>; -+ nexell,pin-pull = <0>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ i2s2_bus:i2s2 { -+ i2s2_mclk: i2s2-mclk { -+ nexell,pins = "gpioa-28"; -+ nexell,pin-function = <2>; -+ nexell,pin-pull = <0>; -+ nexell,pin-strength = <0>; -+ }; -+ -+ i2s2_other: i2s2-other { -+ nexell,pins = "gpiob-2", "gpiob-4", -+ "gpiob-8", "gpiob-10"; -+ nexell,pin-function = <3>; -+ nexell,pin-pull = <0>; -+ nexell,pin-strength = <0>; -+ }; -+ }; -+ -+ spi0_bus:spi0 { -+ nexell,pins = "gpioc-29", "gpioc-30", "gpioc-31", "gpiod-0"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <0>; -+ }; ++ spi0_bus:spi0 { ++ nexell,pins = "gpioc-29", "gpioc-30", "gpioc-31", "gpiod-0"; ++ nexell,pin-function = <1>; ++ nexell,pin-pull = <2>; ++ nexell,pin-strength = <0>; ++ }; + + spi1_bus:spi1 { + nexell,pins = "gpioe-14", "gpioe-15", "gpioe-18", "gpioe-19"; @@ -2258,9 +2132,11 @@ diff -ENwbur a/arch/arm64/boot/dts/nexell/s5p6818-pinctrl.dtsi b/arch/arm64/boot + nexell,pin-strength = <0>; + }; +}; -diff -ENwbur a/arch/arm64/boot/dts/nexell/s5p6818-soc.dtsi b/arch/arm64/boot/dts/nexell/s5p6818-soc.dtsi ---- a/arch/arm64/boot/dts/nexell/s5p6818-soc.dtsi 1970-01-01 01:00:00.000000000 +0100 -+++ b/arch/arm64/boot/dts/nexell/s5p6818-soc.dtsi 2018-05-06 08:49:48.254657924 +0200 +diff --git a/arch/arm64/boot/dts/nexell/s5p6818-soc.dtsi b/arch/arm64/boot/dts/nexell/s5p6818-soc.dtsi +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/arch/arm64/boot/dts/nexell/s5p6818-soc.dtsi @@ -0,0 +1,667 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -2929,9 +2805,11 @@ diff -ENwbur a/arch/arm64/boot/dts/nexell/s5p6818-soc.dtsi b/arch/arm64/boot/dts +}; + + -diff -ENwbur a/arch/arm64/boot/dts/nexell/s5p6818-tmu-sensor-conf.dtsi b/arch/arm64/boot/dts/nexell/s5p6818-tmu-sensor-conf.dtsi ---- a/arch/arm64/boot/dts/nexell/s5p6818-tmu-sensor-conf.dtsi 1970-01-01 01:00:00.000000000 +0100 -+++ b/arch/arm64/boot/dts/nexell/s5p6818-tmu-sensor-conf.dtsi 2018-05-06 08:49:48.254657924 +0200 +diff --git a/arch/arm64/boot/dts/nexell/s5p6818-tmu-sensor-conf.dtsi b/arch/arm64/boot/dts/nexell/s5p6818-tmu-sensor-conf.dtsi +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/arch/arm64/boot/dts/nexell/s5p6818-tmu-sensor-conf.dtsi @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -2964,184 +2842,1151 @@ diff -ENwbur a/arch/arm64/boot/dts/nexell/s5p6818-tmu-sensor-conf.dtsi b/arch/ar +samsung,tmu_second_point_trim = <85>; +samsung,tmu_default_temp_offset = <25>; +samsung,tmu_cal_type = ; -diff -ENwbur a/arch/arm64/configs/nanopim3_defconfig b/arch/arm64/configs/nanopim3_defconfig ---- a/arch/arm64/configs/nanopim3_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ b/arch/arm64/configs/nanopim3_defconfig 2018-05-06 08:49:48.262658250 +0200 -@@ -0,0 +1,4592 @@ -+# -+# Automatically generated file; DO NOT EDIT. -+# Linux/arm64 4.14.39 Kernel Configuration -+# -+CONFIG_ARM64=y -+CONFIG_64BIT=y -+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y -+CONFIG_MMU=y -+CONFIG_ARM64_PAGE_SHIFT=12 -+CONFIG_ARM64_CONT_SHIFT=4 -+CONFIG_ARCH_MMAP_RND_BITS_MIN=18 -+CONFIG_ARCH_MMAP_RND_BITS_MAX=24 -+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 -+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 -+CONFIG_NO_IOPORT_MAP=y -+CONFIG_STACKTRACE_SUPPORT=y -+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -+CONFIG_LOCKDEP_SUPPORT=y -+CONFIG_TRACE_IRQFLAGS_SUPPORT=y -+CONFIG_RWSEM_XCHGADD_ALGORITHM=y -+CONFIG_GENERIC_BUG=y -+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -+CONFIG_GENERIC_HWEIGHT=y -+CONFIG_GENERIC_CSUM=y -+CONFIG_GENERIC_CALIBRATE_DELAY=y -+CONFIG_ZONE_DMA=y -+CONFIG_HAVE_GENERIC_GUP=y -+CONFIG_ARCH_DMA_ADDR_T_64BIT=y -+CONFIG_NEED_DMA_MAP_STATE=y -+CONFIG_NEED_SG_DMA_LENGTH=y -+CONFIG_SMP=y -+CONFIG_SWIOTLB=y -+CONFIG_IOMMU_HELPER=y -+CONFIG_KERNEL_MODE_NEON=y -+CONFIG_FIX_EARLYCON_MEM=y -+CONFIG_PGTABLE_LEVELS=3 -+CONFIG_ARCH_SUPPORTS_UPROBES=y -+CONFIG_ARCH_PROC_KCORE_TEXT=y -+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -+CONFIG_IRQ_WORK=y -+CONFIG_BUILDTIME_EXTABLE_SORT=y -+CONFIG_THREAD_INFO_IN_TASK=y +diff --git a/arch/arm64/boot/dts/nexell/s5p6818.dtsi b/arch/arm64/boot/dts/nexell/s5p6818.dtsi +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/arch/arm64/boot/dts/nexell/s5p6818.dtsi +@@ -0,0 +1,959 @@ ++/* ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * Author: Youngbok, Park ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ + -+# -+# General setup -+# -+CONFIG_INIT_ENV_ARG_LIMIT=32 -+CONFIG_CROSS_COMPILE="aarch64-linux-gnu-" -+# CONFIG_COMPILE_TEST is not set -+CONFIG_LOCALVERSION="" -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_DEFAULT_HOSTNAME="S5P6818" -+CONFIG_SWAP=y -+CONFIG_SYSVIPC=y -+CONFIG_SYSVIPC_SYSCTL=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_POSIX_MQUEUE_SYSCTL=y -+CONFIG_CROSS_MEMORY_ATTACH=y -+CONFIG_FHANDLE=y -+CONFIG_USELIB=y -+CONFIG_AUDIT=y -+CONFIG_HAVE_ARCH_AUDITSYSCALL=y -+CONFIG_AUDITSYSCALL=y -+CONFIG_AUDIT_WATCH=y -+CONFIG_AUDIT_TREE=y ++#include ++#include ++#include ++#include ++#include + -+# -+# IRQ subsystem -+# -+CONFIG_GENERIC_IRQ_PROBE=y -+CONFIG_GENERIC_IRQ_SHOW=y -+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y -+CONFIG_GENERIC_IRQ_MIGRATION=y -+CONFIG_HARDIRQS_SW_RESEND=y -+CONFIG_IRQ_DOMAIN=y -+CONFIG_IRQ_DOMAIN_HIERARCHY=y -+CONFIG_HANDLE_DOMAIN_IRQ=y -+# CONFIG_IRQ_DOMAIN_DEBUG is not set -+CONFIG_IRQ_FORCED_THREADING=y -+CONFIG_SPARSE_IRQ=y -+# CONFIG_GENERIC_IRQ_DEBUGFS is not set -+CONFIG_ARCH_CLOCKSOURCE_DATA=y -+CONFIG_GENERIC_TIME_VSYSCALL=y -+CONFIG_GENERIC_CLOCKEVENTS=y -+CONFIG_ARCH_HAS_TICK_BROADCAST=y -+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++/ { ++ model = "nexell soc"; ++ compatible = "nexell,s5p6818"; ++ #address-cells = <0x1>; ++ #size-cells = <0x1>; + -+# -+# Timers subsystem -+# -+CONFIG_TICK_ONESHOT=y -+CONFIG_NO_HZ_COMMON=y -+# CONFIG_HZ_PERIODIC is not set -+CONFIG_NO_HZ_IDLE=y -+# CONFIG_NO_HZ_FULL is not set -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y ++ aliases { ++ serial0 = &serial0; ++ serial1 = &serial1; ++ serial2 = &serial2; ++ serial3 = &serial3; ++ serial4 = &serial4; ++ serial5 = &serial5; ++ i2s0 = &i2s_0; ++ i2s1 = &i2s_1; ++ i2s2 = &i2s_2; ++ spi0 = &spi_0; ++ spi1 = &spi_1; ++ spi2 = &spi_2; ++ i2c0 = &i2c_0; ++ i2c1 = &i2c_1; ++ i2c2 = &i2c_2; + -+# -+# CPU/Task time and stats accounting -+# -+CONFIG_TICK_CPU_ACCOUNTING=y -+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set -+# CONFIG_IRQ_TIME_ACCOUNTING is not set -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+# CONFIG_TASKSTATS is not set ++ pinctrl0 = &pinctrl_0; ++ }; + -+# -+# RCU Subsystem -+# -+CONFIG_PREEMPT_RCU=y -+# CONFIG_RCU_EXPERT is not set -+CONFIG_SRCU=y -+CONFIG_TREE_SRCU=y -+CONFIG_TASKS_RCU=y -+CONFIG_RCU_STALL_COMMON=y -+CONFIG_RCU_NEED_SEGCBLIST=y -+CONFIG_BUILD_BIN2C=y -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y -+CONFIG_LOG_BUF_SHIFT=16 -+CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -+CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 -+CONFIG_GENERIC_SCHED_CLOCK=y -+CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y -+CONFIG_CGROUPS=y -+CONFIG_PAGE_COUNTER=y -+CONFIG_MEMCG=y -+CONFIG_MEMCG_SWAP=y -+CONFIG_MEMCG_SWAP_ENABLED=y -+# CONFIG_BLK_CGROUP is not set -+CONFIG_CGROUP_SCHED=y -+CONFIG_FAIR_GROUP_SCHED=y -+# CONFIG_CFS_BANDWIDTH is not set -+CONFIG_RT_GROUP_SCHED=y -+# CONFIG_CGROUP_PIDS is not set -+# CONFIG_CGROUP_RDMA is not set -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CGROUP_HUGETLB=y -+# CONFIG_CPUSETS is not set -+# CONFIG_CGROUP_DEVICE is not set -+CONFIG_CGROUP_CPUACCT=y -+# CONFIG_CGROUP_PERF is not set -+CONFIG_CGROUP_BPF=y -+CONFIG_CGROUP_DEBUG=y -+CONFIG_SOCK_CGROUP_DATA=y -+# CONFIG_CHECKPOINT_RESTORE is not set -+CONFIG_NAMESPACES=y -+CONFIG_UTS_NS=y -+CONFIG_IPC_NS=y -+# CONFIG_USER_NS is not set -+CONFIG_PID_NS=y -+CONFIG_NET_NS=y -+CONFIG_SCHED_AUTOGROUP=y -+# CONFIG_SYSFS_DEPRECATED is not set -+# CONFIG_RELAY is not set -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_INITRAMFS_SOURCE="" -+CONFIG_RD_GZIP=y -+# CONFIG_RD_BZIP2 is not set -+# CONFIG_RD_LZMA is not set -+# CONFIG_RD_XZ is not set -+# CONFIG_RD_LZO is not set -+# CONFIG_RD_LZ4 is not set -+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set -+CONFIG_CC_OPTIMIZE_FOR_SIZE=y -+CONFIG_SYSCTL=y -+CONFIG_ANON_INODES=y -+CONFIG_HAVE_UID16=y -+CONFIG_SYSCTL_EXCEPTION_TRACE=y -+CONFIG_BPF=y -+CONFIG_EXPERT=y ++ psci { ++ compatible = "arm,psci-0.2"; ++ method = "smc"; ++ }; ++ ++ cpus { ++ #address-cells = <0x2>; ++ #size-cells = <0x0>; ++ ++ cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x0>; ++ enable-method = "psci"; ++ cpu-release-addr = < 0x1 0xc0010230 >; ++ #cooling-cells = <2>; ++ cpu-idle-states =<&CPU_SLEEP>; ++ }; ++ ++ cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x1>; ++ enable-method = "psci"; ++ cpu-release-addr = < 0x1 0xc0010230 >; ++ cpu-idle-states =<&CPU_SLEEP>; ++ }; ++ ++ cpu2: cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x2>; ++ enable-method = "psci"; ++ cpu-release-addr = < 0x1 0xc0010230 >; ++ cpu-idle-states =<&CPU_SLEEP>; ++ }; ++ ++ cpu3: cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x3>; ++ enable-method = "psci"; ++ cpu-release-addr = < 0x1 0xc0010230 >; ++ cpu-idle-states =<&CPU_SLEEP>; ++ }; ++ ++ cpu4: cpu@4 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x100>; ++ enable-method = "psci"; ++ cpu-release-addr = < 0x1 0xc0010230 >; ++ cpu-idle-states =<&CPU_SLEEP>; ++ }; ++ ++ cpu5: cpu@5 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x101>; ++ enable-method = "psci"; ++ cpu-release-addr = < 0x1 0xc0010230 >; ++ cpu-idle-states =<&CPU_SLEEP>; ++ }; ++ ++ cpu6: cpu@6 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x102>; ++ enable-method = "psci"; ++ cpu-release-addr = < 0x1 0xc0010230 >; ++ cpu-idle-states =<&CPU_SLEEP>; ++ }; ++ ++ cpu7: cpu@7 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x103>; ++ enable-method = "psci"; ++ cpu-release-addr = < 0x1 0xc0010230 >; ++ cpu-idle-states =<&CPU_SLEEP>; ++ }; ++ ++ cpu-map { ++ cluster0 { ++ core0 { ++ cpu = <&cpu0>; ++ }; ++ core1 { ++ cpu = <&cpu1>; ++ }; ++ core2 { ++ cpu = <&cpu2>; ++ }; ++ core3 { ++ cpu = <&cpu3>; ++ }; ++ }; ++ cluster1 { ++ core0 { ++ cpu = <&cpu4>; ++ }; ++ core1 { ++ cpu = <&cpu5>; ++ }; ++ core2 { ++ cpu = <&cpu6>; ++ }; ++ core3 { ++ cpu = <&cpu7>; ++ }; ++ }; ++ }; ++ ++ idle-states { ++ CPU_SLEEP: sleep { ++ compatible = "nexell,idle-state"; ++ arm,psci-suspend-param = <0x0000000>; ++ entry-latency-us = <150>; ++ exit-latency-us = <200>; ++ min-residency-us = <2000>; ++ }; ++ }; ++ }; ++ ++ pmu { ++ compatible = "arm,armv8-pmuv3"; ++ interrupt-parent = <&gic>; ++ interrupts = <0 IRQ_P0_PMUIRQ0 0>, ++ <0 IRQ_P0_PMUIRQ1 0>, ++ <0 IRQ_P0_PMUIRQ2 0>, ++ <0 IRQ_P0_PMUIRQ3 0>, ++ <0 IRQ_P1_PMUIRQ0 0>, ++ <0 IRQ_P1_PMUIRQ1 0>, ++ <0 IRQ_P1_PMUIRQ2 0>, ++ <0 IRQ_P1_PMUIRQ3 0>; ++ interrupt-affinity = <&cpu0>, ++ <&cpu1>, ++ <&cpu2>, ++ <&cpu3>, ++ <&cpu4>, ++ <&cpu5>, ++ <&cpu6>, ++ <&cpu7>; ++ }; ++ ++ refclk:oscillator { ++ compatible = "nexell,s5pxx18,pll"; ++ reg = <0xc0010000 0x1000>; ++ ref-freuecny = <24000000>; ++ }; ++ ++ nx-v4l2 { ++ compatible = "nexell,nx-v4l2"; ++ status = "disabled"; ++ }; ++ ++ nx-devfreq { ++ compatible = "nexell,s5pxx18-devfreq"; ++ pll = <0>; ++ supply_name = "vdd_arm_regulator"; ++ vdd_arm_regulator-supply = <&VCC_DCDC1>; ++ status = "disabled"; ++ }; ++ ++ soc { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0xc0000000 0x300000>; ++ interrupt-parent = <&gic>; ++ ranges; ++ ++ #include "s5p6818-soc.dtsi" ++ ++ gic:interrupt-controller@c0009000 { ++ compatible = "arm,gic-400"; ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ reg = <0xC0009000 0x1000>, <0xC000a000 0x100>; ++ }; ++ ++ timer@c0017000 { ++ compatible = "nexell,s5p6818-timer"; ++ reg = ; ++ interrupts = <0 IRQ_TIMER1 0>; ++ clksource = <0>; ++ clkevent = <1>; ++ clocks = <&timer0>, <&timer1>, <&pclk>; ++ clock-names = "timer0", "timer1", "pclk"; ++ }; ++ ++ tieoff@c0011000 { ++ compatible = "nexell,tieoff"; ++ reg = ; ++ }; ++ ++ dynamic-freq@bb000 { ++ compatible = "nexell,s5pxx18-cpufreq"; ++ reg = <0xc00bb000 0x30000>; ++ }; ++ ++ serial0:serial@c00a1000 { ++ compatible = "nexell,s5p6818-uart"; ++ reg = ; ++ interrupts = <0 IRQ_UART0 0>; ++ clock-names = "uart", "clk_uart_baud0"; ++ clocks = <&uart0>, <&uart0>; ++ resets = <&nexell_reset RESET_ID_UART0>; ++ reset-names = "uart-reset"; ++ soc,tieoff = , ++ , ++ ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&serial0_pin>; ++ status = "disabled"; ++ }; ++ ++ serial1:serial@c00a0000 { ++ compatible = "nexell,s5p6818-uart"; ++ reg = ; ++ interrupts = <0 IRQ_UART1 0>; ++ clock-names = "uart", "clk_uart_baud0"; ++ clocks = <&uart1>, <&uart1>; ++ resets = <&nexell_reset RESET_ID_UART1>; ++ reset-names = "uart-reset"; ++ soc,tieoff = , ++ , ++ ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&serial1_pin>; ++ status = "disabled"; ++ }; ++ ++ serial2:serial@c00a2000 { ++ compatible = "nexell,s5p6818-uart"; ++ reg = ; ++ interrupts = <0 IRQ_UART2 0>; ++ clock-names = "uart", "clk_uart_baud0"; ++ clocks = <&uart2>, <&uart2>; ++ resets = <&nexell_reset RESET_ID_UART2>; ++ reset-names = "uart-reset"; ++ soc,tieoff = , ++ , ++ ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&serial2_pin>; ++ status = "disabled"; ++ }; ++ ++ serial3:serial@c00a3000 { ++ compatible = "nexell,s5p6818-uart"; ++ reg = ; ++ interrupts = <0 IRQ_UART3 0>; ++ clock-names = "uart", "clk_uart_baud0"; ++ clocks = <&uart3>, <&uart3>; ++ resets = <&nexell_reset RESET_ID_UART3>; ++ reset-names = "uart-reset"; ++ soc,tieoff = , ++ , ++ ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&serial3_pin>; ++ status = "disabled"; ++ }; ++ ++ serial4:serial@c006d000 { ++ compatible = "nexell,s5p6818-uart"; ++ reg = ; ++ interrupts = <0 IRQ_UART4 0>; ++ clock-names = "uart", "clk_uart_baud0"; ++ clocks = <&uart4>, <&uart4>; ++ resets = <&nexell_reset RESET_ID_UART4>; ++ reset-names = "uart-reset"; ++ soc,tieoff = , ++ , ++ ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&serial4_pin>; ++ status = "disabled"; ++ }; ++ ++ serial5:serial@c006f000 { ++ compatible = "nexell,s5p6818-uart"; ++ reg = ; ++ interrupts = <0 IRQ_UART5 0>; ++ clock-names = "uart", "clk_uart_baud0"; ++ clocks = <&uart5>, <&uart5>; ++ resets = <&nexell_reset RESET_ID_UART5>; ++ reset-names = "uart-reset"; ++ soc,tieoff = , ++ , ++ ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&serial5_pin>; ++ status = "disabled"; ++ }; ++ ++ nexell_reset:reset@c0012000 { ++ #reset-cells = <1>; ++ compatible = "nexell,s5pxx18-reset"; ++ reg = <0xC0012000 0x3>; ++ status = "okay"; ++ }; ++ ++ pwm:pwm@c0018000 { ++ compatible = "nexell,s5p6818-pwm"; ++ reg = ; ++ reset-names = "pwm-reset"; ++ resets = <&nexell_reset RESET_ID_PWM>; ++ clock-names = "timers", "pwm-tclk0", "pwm-tclk1"; ++ clocks = <&pclk>, <&pwm0>, <&pwm2>; ++ #pwm-cells = <3>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm0_pin &pwm1_pin &pwm2_pin &pwm3_pin>; ++ samsung,pwm-outputs = <0>, <1>, <2>, <3>; ++ status = "disabled"; ++ }; ++ ++ i2c_0:i2c@c00a4000 { ++ compatible = "nexell,s5p6818-i2c"; ++ reg = ; ++ interrupts = <0 IRQ_I2C0 0>; ++ clock-names = "i2c"; ++ clocks = <&i2c0>; ++ samsung,i2c-sda-delay = <100>; ++ samsung,i2c-max-bus-freq = <100000>; ++ samsung,i2c-slave-addr = <0x66>; ++ resets = <&nexell_reset RESET_ID_I2C0>; ++ reset-names = "i2c-reset"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pin>; ++ status = "disabled"; ++ }; ++ ++ i2c_1:i2c@c00a5000 { ++ compatible = "nexell,s5p6818-i2c"; ++ reg = ; ++ interrupts = <0 IRQ_I2C1 0>; ++ clock-names = "i2c"; ++ clocks = <&i2c1>; ++ samsung,i2c-sda-delay = <100>; ++ samsung,i2c-max-bus-freq = <100000>; ++ samsung,i2c-slave-addr = <0x66>; ++ resets = <&nexell_reset RESET_ID_I2C1>; ++ reset-names = "i2c-reset"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pin>; ++ status = "disabled"; ++ }; ++ ++ i2c_2:i2c@c00a6000 { ++ compatible = "nexell,s5p6818-i2c"; ++ reg = ; ++ interrupts = <0 IRQ_I2C2 0>; ++ clock-names = "i2c"; ++ clocks = <&i2c2>; ++ samsung,i2c-sda-delay = <100>; ++ samsung,i2c-max-bus-freq = <100000>; ++ samsung,i2c-slave-addr = <0x66>; ++ resets = <&nexell_reset RESET_ID_I2C2>; ++ reset-names = "i2c-reset"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pin>; ++ status = "disabled"; ++ }; ++ ++ dw_mmc_2:dw_mmc@c0069000 { ++ compatible = "nexell,s5p6818-dw-mshc"; ++ interrupts = <0 IRQ_SDMMC2 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = ; ++ resets = <&nexell_reset RESET_ID_SDMMC2>; ++ reset-names = "dw_mmc-reset"; ++ clock-names = "biu","ciu"; ++ clocks = <&sdhc2>, <&sdhc2>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc2_cclk &sdmmc2_cmd &sdmmc2_bus4>; ++ fifo-depth = <0x20>; ++ status = "disabled"; ++ }; ++ ++ dw_mmc_1:dw_mmc@c0068000 { ++ compatible = "nexell,s5p6818-dw-mshc"; ++ interrupts = <0 IRQ_SDMMC1 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = ; ++ resets = <&nexell_reset RESET_ID_SDMMC1>; ++ reset-names = "dw_mmc-reset"; ++ clock-names = "biu","ciu"; ++ clocks = <&sdhc1>, <&sdhc1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc1_cclk &sdmmc1_cmd &sdmmc1_bus4>; ++ fifo-depth = <0x20>; ++ status = "disabled"; ++ }; ++ ++ dw_mmc_0:dw_mmc@c0062000 { ++ compatible = "nexell,s5p6818-dw-mshc"; ++ interrupts = <0 IRQ_SDMMC0 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = ; ++ resets = <&nexell_reset RESET_ID_SDMMC0>; ++ reset-names = "dw_mmc-reset"; ++ clock-names = "biu", "ciu"; ++ clocks = <&sdhc0>, <&sdhc0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_cclk &sdmmc0_cmd &sdmmc0_bus4>; ++ fifo-depth = <0x20>; ++ status = "disabled"; ++ }; ++ ++ i2s_0:i2s@c0055000 { ++ compatible = "nexell,nexell-i2s"; ++ reg = ; ++ dmas = <&pl08xdma0 12 0>, <&pl08xdma0 13 0>; ++ dma-names = "tx", "rx"; ++ clocks = <&i2s0>; ++ clock-names = "i2s0"; ++ resets = <&nexell_reset RESET_ID_I2S0>; ++ reset-names = "i2s-reset"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s0_bus>; ++ master-mode = <1>; ++ mclk-in = <0>; ++ trans-mode = <0>; ++ frame-bit = <32>; ++ sample-rate = <48000>; ++ pre-supply-mclk = <1>; ++ status = "disabled"; ++ }; ++ ++ i2s_1:i2s@c0056000 { ++ compatible = "nexell,nexell-i2s"; ++ reg = ; ++ dmas = <&pl08xdma0 14 0>, <&pl08xdma0 15 0>; ++ dma-names = "tx", "rx"; ++ clocks = <&i2s1>; ++ clock-names = "i2s1"; ++ resets = <&nexell_reset RESET_ID_I2S1>; ++ reset-names = "i2s-reset"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s1_bus>; ++ master-mode = <1>; ++ mclk-in = <0>; ++ trans-mode = <0>; ++ frame-bit = <32>; ++ sample-rate = <48000>; ++ pre-supply-mclk = <1>; ++ status = "disabled"; ++ }; ++ ++ i2s_2:i2s@c0057000 { ++ compatible = "nexell,nexell-i2s"; ++ reg = ; ++ dmas = <&pl08xdma1 0 0>, <&pl08xdma1 1 0>; ++ dma-names = "tx", "rx"; ++ clocks = <&i2s2>; ++ clock-names = "i2s2"; ++ resets = <&nexell_reset RESET_ID_I2S2>; ++ reset-names = "i2s-reset"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s2_bus>; ++ master-mode = <1>; ++ mclk-in = <0>; ++ trans-mode = <0>; ++ frame-bit = <32>; ++ sample-rate = <48000>; ++ pre-supply-mclk = <1>; ++ status = "disabled"; ++ }; ++ ++ nexell_usbphy: nexell-usbphy@c0012000 { ++ compatible = "nexell,nexell-usb2-phy"; ++ reg = ; ++ clocks = <&usbhost>; ++ clock-names = "phy"; ++ #phy-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ehci@c0030000 { ++ compatible = "nexell,nexell-ehci"; ++ reg = ; ++ interrupts = <0 IRQ_USB20HOST 0>; ++ clocks = <&usbhost>; ++ clock-names = "usbhost"; ++ resets = <&nexell_reset RESET_ID_USB20HOST>; ++ reset-names = "usbhost-reset"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port@0 { ++ reg = <0>; ++ phys = <&nexell_usbphy 1>; ++ status = "disabled"; ++ }; ++ port@1 { ++ reg = <1>; ++ phys = <&nexell_usbphy 2>; ++ status = "disabled"; ++ }; ++ }; ++ ++ ohci@c0020000 { ++ compatible = "nexell,nexell-ohci"; ++ reg = ; ++ interrupts = <0 IRQ_USB20HOST 0>; ++ clocks = <&usbhost>; ++ clock-names = "usbhost"; ++ resets = <&nexell_reset RESET_ID_USB20HOST>; ++ reset-names = "usbhost-reset"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port@0 { ++ reg = <0>; ++ phys = <&nexell_usbphy 1>; ++ status = "disabled"; ++ }; ++ }; ++ ++ dwc2otg@c0040000 { ++ compatible = "nexell,nexell-dwc2otg"; ++ reg = ; ++ interrupts = <0 IRQ_USB20OTG 0>; ++ clocks = <&otg>; ++ clock-names = "otg"; ++ resets = <&nexell_reset RESET_ID_USB20OTG>; ++ reset-names = "usbotg-reset"; ++ phys = <&nexell_usbphy 0>; ++ phy-names = "usb2-phy"; ++ dr_mode = "otg"; ++ g-use-dma = <1>; ++ g-rx-fifo-size = <1064>; ++ g-np-tx-fifo-size = <512>; ++ g-tx-fifo-size = <512 512 512 512 512 256 256 256 256 ++ 256 64 64 64 64 64>; ++ status = "disabled"; ++ }; ++ ++ gmac0:ethernet@c0060000 { ++ compatible = "nexell,s5p6818-gmac"; ++ clocks = <&pclk>, <&gmac>; ++ clock-names = "stmmaceth", "nexell_gmac_tx"; ++ resets = <&nexell_reset RESET_ID_DWC_GMAC>; ++ reset-names = "stmmaceth"; ++ reg = ; ++ interrupt-parent = <&gic>; ++ interrupts = <0 IRQ_GMAC 0>; ++ interrupt-names = "macirq"; ++ mac-address = [000000000000]; /* Filled in by U-Boot */ ++ phy-mode = "rgmii"; ++ snps,multicast-filter-bins = <256>; ++ status = "disable"; ++ }; ++ ++ adc:adc@c0053000 { ++ compatible = "nexell,s5p6818-adc"; ++ reg = ; ++ interrupts = <0 IRQ_ADC 0>; ++ resets = <&nexell_reset RESET_ID_ADC>; ++ reset-names = "adc-reset"; ++ clocks = <&pclk>; ++ clock-names = "adc"; ++ sample_rate = <200000>; ++ #io-channel-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ spi_0:spi@c005b000 { ++ compatible = "nexell,s5p6818-spi"; ++ reg = ; ++ interrupts = <0 IRQ_SSP0 0>; ++ dmas = <&pl08xdma0 6 0>, <&pl08xdma0 7 0>; ++ dma-names = "tx", "rx"; ++ resets = <&nexell_reset RESET_ID_SSP0_P>, ++ <&nexell_reset RESET_ID_SSP0>; ++ reset-names = "pre-reset","spi-reset"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ samsung,spi-src-clk = <0>; ++ num-cs = <1>; ++ clocks = <&spi0>, <&spi0>; ++ clock-names = "spi", "spi_busclk0"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_bus>; ++ status ="disable"; ++ }; ++ ++ spi_1:spi@c005c000 { ++ compatible = "nexell,s5p6818-spi"; ++ reg = ; ++ interrupts = <0 IRQ_SSP1 0>; ++ dmas = <&pl08xdma0 8 0>, <&pl08xdma0 9 0>; ++ dma-names = "tx", "rx"; ++ resets = <&nexell_reset RESET_ID_SSP1_P>, ++ <&nexell_reset RESET_ID_SSP1>; ++ reset-names = "pre-reset","spi-reset"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ samsung,spi-src-clk = <0>; ++ num-cs = <1>; ++ clocks = <&spi1>, <&spi1>; ++ clock-names = "spi", "spi_busclk0"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi1_bus>; ++ status ="disable"; ++ }; ++ ++ spi_2:spi@c005f000 { ++ compatible = "nexell,s5p6818-spi"; ++ reg = ; ++ interrupts = <0 IRQ_SSP2 0>; ++ dmas = <&pl08xdma0 10 0>, <&pl08xdma0 11 0>; ++ dma-names = "tx", "rx"; ++ resets = <&nexell_reset RESET_ID_SSP2_P>, ++ <&nexell_reset RESET_ID_SSP2>; ++ reset-names = "pre-reset","spi-reset"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ samsung,spi-src-clk = <0>; ++ num-cs = <1>; ++ clocks = <&spi2>, <&spi2>; ++ clock-names = "spi", "spi_busclk0"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi2_bus>; ++ status ="disable"; ++ }; ++ ++ watchdog@c0019000 { ++ compatible = "nexell,nexell-wdt"; ++ reg = ; ++ interrupts = <0 IRQ_WDT 0>; ++ resets = <&nexell_reset RESET_ID_WDT>, ++ <&nexell_reset RESET_ID_WDT_POR>; ++ reset-names = "wdt-reset","wdt-por-reset"; ++ clocks = <&pclk>; ++ clock-names = "watchdog"; ++ status = "disabled"; ++ }; ++ ++ spdif_tx: spdiftx@c0059000 { ++ compatible = "nexell,nexell-spdif-tx"; ++ reg = ; ++ interrupts = <0 IRQ_SPDIFTX 0>; ++ dmas = <&pl08xdma1 6 0>; ++ dma-names = "tx"; ++ resets = <&nexell_reset RESET_ID_SPDIFTX>; ++ reset-names = "spdiftx-reset"; ++ clocks = <&spdiftx>; ++ clock-names = "spdif-tx"; ++ pcm-bit = <16>; ++ sample_rate = <48000>; ++ status = "disabled"; ++ }; ++ ++ tmuctrl_0: tmuctrl@c0096000 { ++ compatible = "nexell,s5p6818-tmu"; ++ reg = ; ++ interrupts = <0 IRQ_TMU0 0>; ++ clocks = <&pclk>; ++ clock-names = "tmu_apbif"; ++ #include "s5p6818-tmu-sensor-conf.dtsi" ++ soc,tieoff = ; ++ status = "disabled"; ++ }; ++ ++ tmuctrl_1: tmuctrl@c0097000 { ++ compatible = "nexell,s5p6818-tmu"; ++ reg = ; ++ interrupts = <0 IRQ_TMU1 0>; ++ clocks = <&pclk>; ++ clock-names = "tmu_apbif"; ++ #include "s5p6818-tmu-sensor-conf.dtsi" ++ soc,tieoff = ; ++ status = "disabled"; ++ }; ++ ++ mipi_csi:mipi_csi@c00d0000 { ++ compatible = "nexell,mipi_csi"; ++ reg = ; ++ clock-names = "mipi"; ++ clocks = <&mipi>; ++ reset-names = "mipi-reset", "mipi_csi-reset", "mipi_phy_s-reset"; ++ resets = <&nexell_reset RESET_ID_MIPI>, ++ <&nexell_reset RESET_ID_MIPI_CSI>, ++ <&nexell_reset RESET_ID_MIPI_PHY_S>; ++ soc,tieoff = ; ++ data_lane = <2>; ++ swap_clocklane = <0>; ++ swap_datalane = <0>; ++ pllval = <750>; ++ status = "disabled"; ++ }; ++ ++ vip_0:vip@c0063000 { ++ compatible = "nexell,vip"; ++ reg = ; ++ interrupts = <0 IRQ_VIP0 0>; ++ clock-names = "vip0"; ++ clocks = <&vip0>; ++ reset-names = "vip0-reset"; ++ resets = <&nexell_reset RESET_ID_VIP0>; ++ module = <0>; ++ status = "disabled"; ++ }; ++ ++ vip_1:vip@c0064000 { ++ compatible = "nexell,vip"; ++ reg = ; ++ interrupts = <0 IRQ_VIP1 0>; ++ clock-names = "vip1"; ++ clocks = <&vip1>; ++ reset-names = "vip1-reset"; ++ resets = <&nexell_reset RESET_ID_VIP1>; ++ module = <1>; ++ status = "disabled"; ++ }; ++ ++ vip_2:vip@c0099000 { ++ compatible = "nexell,vip"; ++ reg = ; ++ interrupts = <0 IRQ_VIP2 0>; ++ clock-names = "vip2"; ++ clocks = <&vip2>; ++ reset-names = "vip2-reset"; ++ resets = <&nexell_reset RESET_ID_VIP2>; ++ module = <2>; ++ status = "disabled"; ++ }; ++ ++ clipper_0:clipper0@c0063000 { ++ compatible = "nexell,nx-clipper"; ++ module = <0>; ++ status = "disabled"; ++ }; ++ ++ clipper_1:clipper1@c0064000 { ++ compatible = "nexell,nx-clipper"; ++ module = <1>; ++ status = "disabled"; ++ }; ++ ++ clipper_2:clipper2@c0064000 { ++ compatible = "nexell,nx-clipper"; ++ module = <2>; ++ status = "disabled"; ++ }; ++ ++ decimator_0:decimator0@c0063000 { ++ compatible = "nexell,nx-decimator"; ++ module = <0>; ++ status = "disabled"; ++ }; ++ ++ dp_drm: display_drm { ++ compatible = "nexell,s5pxx18-drm"; ++ reg = <0xc0102800 0x100>, <0xc0102c00 0x100>, ++ <0xc0102000 0x100>, <0xc0102400 0x100>; ++ reg-names = "dpc.0", "dpc.1", "mlc.0", "mlc.1"; ++ ++ interrupts = < 0 IRQ_DPC_P 0 >, <0 IRQ_DPC_S 0>; ++ interrupts-names = "dpc.0", "dpc.1"; ++ ++ resets = <&nexell_reset RESET_ID_DISPLAY>, ++ <&nexell_reset RESET_ID_DISP_TOP>; ++ reset-names = "rsc-display", "rsc-display-top"; ++ ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port@0 { }; ++ port@1 { }; ++ }; ++ }; ++ ++ dp_drm_rgb: display_drm_rgb { ++ compatible = "nexell,s5pxx18-drm-rgb"; ++ reg = <0xc0101000 0x100>; ++ resets = <&nexell_reset RESET_ID_DISP_TOP>; ++ reset-names = "rsc-display-top"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ dp_drm_lvds: display_drm_lvds { ++ compatible = "nexell,s5pxx18-drm-lvds"; ++ reg = <0xc0101000 0x100>; ++ resets = <&nexell_reset RESET_ID_DISP_TOP>; ++ reset-names = "rsc-display-top"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ dp-resource { ++ reg_base = <0xc010a000 0x100>; ++ clk_base = <0xc0108000 3>; ++ resets = <&nexell_reset RESET_ID_LVDS>; ++ reset-names = "rsc-lvds-phy"; ++ }; ++ }; ++ ++ dp_drm_mipi: display_drm_mipi { ++ compatible = "nexell,s5pxx18-drm-mipi"; ++ reg = <0xc0101000 0x100>; ++ resets = <&nexell_reset RESET_ID_DISP_TOP>; ++ reset-names = "rsc-display-top"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ dp-resource { ++ reg_base = <0xc00d0000 0x100>; ++ clk_base = <0xc0105000 2>; ++ ++ resets = <&nexell_reset RESET_ID_MIPI>, ++ <&nexell_reset RESET_ID_MIPI_DSI>, ++ <&nexell_reset RESET_ID_MIPI_PHY_S>, ++ <&nexell_reset RESET_ID_MIPI_PHY_M>; ++ reset-names = "rsc-mipi", "rsc-mipi-dsi", ++ "rsc-mipi-phy-s", "rsc-mipi-phy-m"; ++ soc,tieoff = , ++ ; ++ }; ++ }; ++ ++ dp_drm_hdmi: display_drm_hdmi{ ++ compatible = "nexell,s5pxx18-drm-hdmi"; ++ reg = <0xc0101000 0x100>; ++ interrupts = < 0 IRQ_HDMI 0 >; ++ resets = <&nexell_reset RESET_ID_DISP_TOP>; ++ reset-names = "rsc-display-top"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ dp-resource { ++ reg_base = <0xc0000000 0x300000>; ++ clk_base = <0xc0109000 4>, <0xc0105000 2>; ++ resets = <&nexell_reset RESET_ID_HDMI_VIDEO>, ++ <&nexell_reset RESET_ID_HDMI_SPDIF>, ++ <&nexell_reset RESET_ID_HDMI_TMDS>, ++ <&nexell_reset RESET_ID_HDMI>, ++ <&nexell_reset RESET_ID_HDMI_PHY>; ++ reset-names = "rsc-hdmi-video", "rsc-hdmi-spdif", ++ "rsc-hdmi-tmds", "rsc-hdmi", "rsc-hdmi-phy"; ++ soc,tieoff = ; ++ }; ++ }; ++ ++ video-codec@c0080000 { ++ compatible = "nexell, nx-vpu"; ++ reg = <0xc0080000 0x4000>; ++ interrupts = <0 IRQ_CODA960_HOST 0>, ++ <0 IRQ_CODA960_JPG 0>; ++ resets = <&nexell_reset RESET_ID_CODA_A>, ++ <&nexell_reset RESET_ID_CODA_P>, ++ <&nexell_reset RESET_ID_CODA_C>; ++ reset-names = "vpu-a-reset", "vpu-p-reset", ++ "vpu-c-reset"; ++ clocks = <&pclk>, <&bclk>; ++ status = "disabled"; ++ }; ++ ++ rtc@c0010c00 { ++ compatible = "nexell,nx-rtc"; ++ reg = , <0xc0010200 0x100>; ++ interrupts = <0 IRQ_RTC 0>; ++ status = "disabled"; ++ }; ++ ++ scaler@c0066000 { ++ compatible = "nexell,scaler"; ++ reg = ; ++ interrupts = <0 IRQ_SCALER 0>; ++ clock-names = "scaler"; ++ clocks = <&scaler>; ++ reset-names = "scaler-reset"; ++ resets = <&nexell_reset RESET_ID_SCALER>; ++ status = "disabled"; ++ }; ++ ++ gpu@c0070000 { ++ compatible = "arm,mali-400", "arm,mali-utgard"; ++ reg = ; ++ interrupts = <0 IRQ_VR 0>, <0 IRQ_VR 0>, <0 IRQ_VR 0>, ++ <0 IRQ_VR 0>, <0 IRQ_VR 0>, <0 IRQ_VR 0>, ++ <0 IRQ_VR 0>, <0 IRQ_VR 0>, <0 IRQ_VR 0>, ++ <0 IRQ_VR 0>, <0 IRQ_VR 0>; ++ interrupt-names = "IRQGP", "IRQGPMMU", "IRQPP0", ++ "IRQPPMMU0", "IRQPP1", "IRQPPMMU1", ++ "IRQPP2", "IRQPPMMU2", "IRQPP3", ++ "IRQPPMMU3", "IRQPMU"; ++ pmu_domain_config = <0x1 0x4 0x8 0x10 0x20 0x0 0x0 0x0 ++ 0x0 0x2 0x0 0x0>; ++ pmu_switch_delay = <0xff>; ++ clocks = <&vr>; ++ clock-names = "clk_mali"; ++ resets = <&nexell_reset RESET_ID_VR>; ++ reset-names = "vr-reset"; ++ }; ++ }; /*** soc ***/ ++}; +diff --git a/arch/arm64/configs/nanopim3_defconfig b/arch/arm64/configs/nanopim3_defconfig +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/arch/arm64/configs/nanopim3_defconfig +@@ -0,0 +1,4592 @@ ++# ++# Automatically generated file; DO NOT EDIT. ++# Linux/arm64 4.14.39 Kernel Configuration ++# ++CONFIG_ARM64=y ++CONFIG_64BIT=y ++CONFIG_ARCH_PHYS_ADDR_T_64BIT=y ++CONFIG_MMU=y ++CONFIG_ARM64_PAGE_SHIFT=12 ++CONFIG_ARM64_CONT_SHIFT=4 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=18 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=24 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_NO_IOPORT_MAP=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_RWSEM_XCHGADD_ALGORITHM=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CSUM=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_ZONE_DMA=y ++CONFIG_HAVE_GENERIC_GUP=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_SMP=y ++CONFIG_SWIOTLB=y ++CONFIG_IOMMU_HELPER=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_PGTABLE_LEVELS=3 ++CONFIG_ARCH_SUPPORTS_UPROBES=y ++CONFIG_ARCH_PROC_KCORE_TEXT=y ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_IRQ_WORK=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++CONFIG_THREAD_INFO_IN_TASK=y ++ ++# ++# General setup ++# ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_CROSS_COMPILE="aarch64-linux-gnu-" ++# CONFIG_COMPILE_TEST is not set ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_DEFAULT_HOSTNAME="S5P6818" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_POSIX_MQUEUE_SYSCTL=y ++CONFIG_CROSS_MEMORY_ATTACH=y ++CONFIG_FHANDLE=y ++CONFIG_USELIB=y ++CONFIG_AUDIT=y ++CONFIG_HAVE_ARCH_AUDITSYSCALL=y ++CONFIG_AUDITSYSCALL=y ++CONFIG_AUDIT_WATCH=y ++CONFIG_AUDIT_TREE=y ++ ++# ++# IRQ subsystem ++# ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_GENERIC_IRQ_SHOW_LEVEL=y ++CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y ++CONFIG_GENERIC_IRQ_MIGRATION=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++# CONFIG_IRQ_DOMAIN_DEBUG is not set ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_SPARSE_IRQ=y ++# CONFIG_GENERIC_IRQ_DEBUGFS is not set ++CONFIG_ARCH_CLOCKSOURCE_DATA=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_ARCH_HAS_TICK_BROADCAST=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++ ++# ++# Timers subsystem ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ_COMMON=y ++# CONFIG_HZ_PERIODIC is not set ++CONFIG_NO_HZ_IDLE=y ++# CONFIG_NO_HZ_FULL is not set ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++ ++# ++# CPU/Task time and stats accounting ++# ++CONFIG_TICK_CPU_ACCOUNTING=y ++# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set ++# CONFIG_IRQ_TIME_ACCOUNTING is not set ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++# CONFIG_TASKSTATS is not set ++ ++# ++# RCU Subsystem ++# ++CONFIG_PREEMPT_RCU=y ++# CONFIG_RCU_EXPERT is not set ++CONFIG_SRCU=y ++CONFIG_TREE_SRCU=y ++CONFIG_TASKS_RCU=y ++CONFIG_RCU_STALL_COMMON=y ++CONFIG_RCU_NEED_SEGCBLIST=y ++CONFIG_BUILD_BIN2C=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y ++CONFIG_CGROUPS=y ++CONFIG_PAGE_COUNTER=y ++CONFIG_MEMCG=y ++CONFIG_MEMCG_SWAP=y ++CONFIG_MEMCG_SWAP_ENABLED=y ++# CONFIG_BLK_CGROUP is not set ++CONFIG_CGROUP_SCHED=y ++CONFIG_FAIR_GROUP_SCHED=y ++# CONFIG_CFS_BANDWIDTH is not set ++CONFIG_RT_GROUP_SCHED=y ++# CONFIG_CGROUP_PIDS is not set ++# CONFIG_CGROUP_RDMA is not set ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CGROUP_HUGETLB=y ++# CONFIG_CPUSETS is not set ++# CONFIG_CGROUP_DEVICE is not set ++CONFIG_CGROUP_CPUACCT=y ++# CONFIG_CGROUP_PERF is not set ++CONFIG_CGROUP_BPF=y ++CONFIG_CGROUP_DEBUG=y ++CONFIG_SOCK_CGROUP_DATA=y ++# CONFIG_CHECKPOINT_RESTORE is not set ++CONFIG_NAMESPACES=y ++CONFIG_UTS_NS=y ++CONFIG_IPC_NS=y ++# CONFIG_USER_NS is not set ++CONFIG_PID_NS=y ++CONFIG_NET_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++# CONFIG_SYSFS_DEPRECATED is not set ++# CONFIG_RELAY is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_RD_GZIP=y ++# CONFIG_RD_BZIP2 is not set ++# CONFIG_RD_LZMA is not set ++# CONFIG_RD_XZ is not set ++# CONFIG_RD_LZO is not set ++# CONFIG_RD_LZ4 is not set ++# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++CONFIG_HAVE_UID16=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=y ++CONFIG_BPF=y ++CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set @@ -7560,18 +8405,19 @@ diff -ENwbur a/arch/arm64/configs/nanopim3_defconfig b/arch/arm64/configs/nanopi +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_SBITMAP=y +# CONFIG_STRING_SELFTEST is not set -diff -ENwbur a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h ---- a/arch/arm64/include/asm/arch_timer.h 2018-05-06 08:47:35.377264876 +0200 -+++ b/arch/arm64/include/asm/arch_timer.h 2018-05-06 08:49:48.266658411 +0200 -@@ -131,6 +131,7 @@ +diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h +index 111111111111..222222222222 100644 +--- a/arch/arm64/include/asm/arch_timer.h ++++ b/arch/arm64/include/asm/arch_timer.h +@@ -131,6 +131,7 @@ u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg) BUG(); } - + +#ifdef CONFIG_ARM_ARCH_TIMER static inline u32 arch_timer_get_cntfrq(void) { return read_sysreg(cntfrq_el0); -@@ -165,5 +166,33 @@ +@@ -165,5 +166,33 @@ static inline int arch_timer_arch_init(void) { return 0; } @@ -7603,13 +8449,14 @@ diff -ENwbur a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch +extern u64 arch_counter_get_cntvct(void); +extern int arch_timer_arch_init(void); +#endif - + #endif -diff -ENwbur a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h ---- a/arch/arm64/include/asm/tlbflush.h 2018-05-06 08:47:35.385265201 +0200 -+++ b/arch/arm64/include/asm/tlbflush.h 2018-05-06 08:49:48.270658574 +0200 -@@ -117,23 +117,36 @@ - +diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h +index 111111111111..222222222222 100644 +--- a/arch/arm64/include/asm/tlbflush.h ++++ b/arch/arm64/include/asm/tlbflush.h +@@ -117,23 +117,36 @@ static inline void flush_tlb_all(void) + static inline void flush_tlb_mm(struct mm_struct *mm) { + /* FIXME: temporary turnaround code to resolve tlb flush by ASID BUG. @@ -7621,14 +8468,14 @@ diff -ENwbur a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflu + flush_tlb_all(); +#else unsigned long asid = ASID(mm) << 48; - + dsb(ishst); __tlbi(aside1is, asid); __tlbi_user(aside1is, asid); dsb(ish); +#endif } - + static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) { @@ -7636,16 +8483,16 @@ diff -ENwbur a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflu + flush_tlb_mm(vma->vm_mm); +#else unsigned long addr = uaddr >> 12 | (ASID(vma->vm_mm) << 48); - + dsb(ishst); __tlbi(vale1is, addr); __tlbi_user(vale1is, addr); dsb(ish); +#endif } - + /* -@@ -146,6 +159,9 @@ +@@ -146,6 +159,9 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end, bool last_level) { @@ -7654,34 +8501,34 @@ diff -ENwbur a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflu +#else unsigned long asid = ASID(vma->vm_mm) << 48; unsigned long addr; - -@@ -168,6 +184,7 @@ + +@@ -168,6 +184,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, } } dsb(ish); +#endif } - + static inline void flush_tlb_range(struct vm_area_struct *vma, -@@ -178,6 +195,9 @@ - +@@ -178,6 +195,9 @@ static inline void flush_tlb_range(struct vm_area_struct *vma, + static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end) { +#ifdef CONFIG_ARM64_WORKAROUND_CCI400_DVMV7 + flush_tlb_all(); +#else unsigned long addr; - + if ((end - start) > MAX_TLB_RANGE) { -@@ -193,6 +213,7 @@ +@@ -193,6 +213,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end __tlbi(vaae1is, addr); dsb(ish); isb(); +#endif } - + /* -@@ -202,11 +223,15 @@ +@@ -202,11 +223,15 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end static inline void __flush_tlb_pgtable(struct mm_struct *mm, unsigned long uaddr) { @@ -7689,112 +8536,47 @@ diff -ENwbur a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflu + flush_tlb_mm(mm); +#else unsigned long addr = uaddr >> 12 | (ASID(mm) << 48); - + __tlbi(vae1is, addr); __tlbi_user(vae1is, addr); dsb(ish); +#endif } - + #endif -diff -ENwbur a/arch/arm64/Kconfig b/arch/arm64/Kconfig ---- a/arch/arm64/Kconfig 2018-05-06 08:47:35.345263577 +0200 -+++ b/arch/arm64/Kconfig 2018-05-06 08:49:48.242657438 +0200 -@@ -30,11 +30,11 @@ - select ARCH_WANT_FRAME_POINTERS - select ARCH_HAS_UBSAN_SANITIZE_ALL - select ARM_AMBA -- select ARM_ARCH_TIMER -+ select ARM_ARCH_TIMER if !ARCH_S5P6818 - select ARM_GIC - select AUDIT_ARCH_COMPAT_GENERIC - select ARM_GIC_V2M if PCI -- select ARM_GIC_V3 -+ select ARM_GIC_V3 if !ARCH_S5P6818 - select ARM_GIC_V3_ITS if PCI - select ARM_PSCI_FW - select BUILDTIME_EXTABLE_SORT -@@ -612,6 +612,25 @@ - default 47 if ARM64_VA_BITS_47 - default 48 if ARM64_VA_BITS_48 - -+config ARM64_WORKAROUND_CCI400_DVMV7 -+ bool "Work around for cci400 using dvmv7 protocol" -+ depends on SMP -+ help -+ This option adds an alternative code sequence to work around ARMv8 -+ cores using CCI400 DVMv7 protocol. -+ -+ According to "AMBA AXI and ACE Protocol Specification" chapter C12.4, -+ 12.6, CCI400 optionally supports DVM(Distributed Virtual Message) -+ protocol version8(DVMv8), and version8 supports ARMv8 and ARMv7 but, -+ version7(DVMv7) supports only ARMv7. -+ -+ To work properly with DVMv7 protocol, C12.4 recommends below list. -+ - If upper 8-bits of ASID are zero the message will be received correctly -+ - TLB Invalidation by address range will work incorrectly -+ -+ So, this patch changes available bits of ASID and all tlb flush by address -+ range commands to flush by ASID. -+ - config CPU_BIG_ENDIAN - bool "Build big-endian kernel" - help -diff -ENwbur a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms ---- a/arch/arm64/Kconfig.platforms 2018-05-06 08:47:35.345263577 +0200 -+++ b/arch/arm64/Kconfig.platforms 2018-05-06 08:49:48.242657438 +0200 -@@ -215,6 +215,20 @@ - help - Support for Spreadtrum ARM based SoCs - -+config ARCH_S5P6818 -+ bool "NEXELL S5P6818" -+ select ARCH_REQUIRE_GPIOLIB -+ select ARCH_HAS_RESET_CONTROLLER -+ select CLKSRC_NXP_TIMER -+ select RESET_CONTROLLER -+ select PINCTRL -+ select ARM64_ERRATUM_845719 -+ select HAVE_S3C2410_I2C if I2C -+ select HAVE_S3C2410_WATCHDOG if WATCHDOG -+ select ARM64_WORKAROUND_CCI400_DVMV7 -+ help -+ This enables support for the NEXELL S5P6818 Architecture -+ - config ARCH_THUNDER - bool "Cavium Inc. Thunder SoC Family" - help -diff -ENwbur a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c ---- a/arch/arm64/kernel/time.c 2018-05-06 08:47:35.393265526 +0200 -+++ b/arch/arm64/kernel/time.c 2018-05-06 08:49:48.278658899 +0200 -@@ -66,11 +66,14 @@ - +diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c +index 111111111111..222222222222 100644 +--- a/arch/arm64/kernel/time.c ++++ b/arch/arm64/kernel/time.c +@@ -66,11 +66,14 @@ EXPORT_SYMBOL(profile_pc); + void __init time_init(void) { +#ifdef CONFIG_ARM_ARCH_TIMER u32 arch_timer_rate; +#endif - + of_clk_init(NULL); timer_probe(); - + +#ifdef CONFIG_ARM_ARCH_TIMER tick_setup_hrtimer_broadcast(); - + arch_timer_rate = arch_timer_get_rate(); -@@ -79,4 +82,5 @@ - +@@ -79,4 +82,5 @@ void __init time_init(void) + /* Calibrate the delay loop directly */ lpj_fine = arch_timer_rate / HZ; +#endif } -diff -ENwbur a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c ---- a/arch/arm64/mm/context.c 2018-05-06 08:47:35.397265688 +0200 -+++ b/arch/arm64/mm/context.c 2018-05-06 08:49:48.282659061 +0200 -@@ -69,6 +69,11 @@ +diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c +index 111111111111..222222222222 100644 +--- a/arch/arm64/mm/context.c ++++ b/arch/arm64/mm/context.c +@@ -69,6 +69,11 @@ static u32 get_cpu_asid_bits(void) asid = 16; } - + +#ifdef CONFIG_ARM64_WORKAROUND_CCI400_DVMV7 +/* In DVMv7 protocol, ASID bits must be 8 regardless of cpu core feature */ + asid = 8; @@ -7802,18 +8584,18 @@ diff -ENwbur a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c + return asid; } - -@@ -119,6 +124,9 @@ - + +@@ -119,6 +124,9 @@ static void flush_context(unsigned int cpu) + /* Queue a TLB invalidate and flush the I-cache if necessary. */ cpumask_setall(&tlb_flush_pending); +#ifdef CONFIG_ARM64_WORKAROUND_CCI400_DVMV7 + flush_tlb_all(); +#endif } - + static bool check_update_reserved_asid(u64 asid, u64 newasid) -@@ -236,6 +244,9 @@ +@@ -236,6 +244,9 @@ switch_mm_fastpath: */ if (!system_uses_ttbr0_pan()) cpu_switch_mm(mm->pgd, mm); @@ -7821,910 +8603,29 @@ diff -ENwbur a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c + flush_tlb_all(); +#endif } - + /* Errata workaround post TTBRx_EL1 update. */ -diff -ENwbur a/Documentation/devicetree/bindings/pinctrl/nexell,s5p6818-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/nexell,s5p6818-pinctrl.txt ---- a/Documentation/devicetree/bindings/pinctrl/nexell,s5p6818-pinctrl.txt 1970-01-01 01:00:00.000000000 +0100 -+++ b/Documentation/devicetree/bindings/pinctrl/nexell,s5p6818-pinctrl.txt 2018-05-06 08:49:47.754637636 +0200 -@@ -0,0 +1,95 @@ -+Binding for Nexell s5p6818 pin cotroller -+======================================== -+ -+Nexell's ARM bases SoC's integrates a GPIO and Pin mux/config hardware -+controller. It controls the input/output settings on the available pads/pins -+and also provides ability to multiplex and configure the output of various -+on-chip controllers onto these pads. -+ -+Please refer to pinctrl-bindings.txt in this directory for details of the -+common pinctrl bindings used by client devices, including the meaning of the -+phrase "pin configuration node". -+ -+ -+Required properties: -+ - compatible: may be "nexell,s5pxx18-pinctrl", "nexell,s5p6818-pinctrl" -+ - reg: should be register base and length as documented in the datasheet -+ - interrupts: interrupt specifier for the controller over gpio and alive pins -+ -+Example: -+pinctrl_0: pinctrl@c0010000 { -+ compatible = "nexell,s5pxx18-pinctrl"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = ; -+ interrupts = <0 IRQ_GPIOA 0>, -+ <0 IRQ_GPIOB 0>, -+ <0 IRQ_GPIOC 0>, -+ <0 IRQ_GPIOD 0>, -+ <0 IRQ_GPIOE 0>, -+ <0 IRQ_ALIVE 0>; -+}; -+ -+ Note: Setting up the order must always match. -+ -+ -+Nexell's pin configuration nodes act as a container for an arbitrary number of -+subnodes. Each of these subnodes represents some desired configuration for a -+pin, a group, or a list of pins or groups. This configuration can include the -+mux function to select on those pin(s)/group(s), and various pin configuration -+parameters. -+ -+ Child nodes must be set at least one of the following settings: -+ - nexell,pins = Select pins for using this function. -+ - nexell,pin-function = Select the function for use in a selected pin. -+ - nexell,pin-pull = Pull up/down configuration. -+ - nexell,pin-strength = Drive strength configuration. -+ -+ Valid values for nexell,pins are: -+ "gpioX-N" : X in {A,B,C,D,E}, N in {0-31} -+ Valid values for nexell,pin-function are: -+ "N" : N in {0-3}. -+ This setting means that the value is different for each pin. -+ Please refer to datasheet. -+ Valid values for nexell,pin-pull are: -+ "N" : 0 - Down, 1 - Up, 2 - Off -+ Valid values for nexell,pin-strength are: -+ "N" : 0,1,2,3 -+ -+ -+Example: -+ - pin settings -+ gmac_txd: gmac-txd { -+ nexell,pins = "gpioe-7", "gpioe-8", "gpioe-9", "gpioe-10"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <3>; -+ }; -+ -+ gmac_rxd: gmac-rxd { -+ nexell,pins = "gpioe-14", "gpioe-15", "gpioe-16", "gpioe-17"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <3>; -+ }; -+ -+ gmac_txen: gmac-txen { -+ nexell,pins = "gpioe-11"; -+ nexell,pin-function = <1>; -+ nexell,pin-pull = <2>; -+ nexell,pin-strength = <3>; -+ }; -+ -+ - used by client devices -+ gmac0:ethernet@... { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&gmac_txd &gmac_rxd &gmac_txen &gmac_mdc -+ &gmac_mdio &gmac_rxclk &gmac_txclk>; -+ ... -+ }; -+ -diff -ENwbur a/Documentation/devicetree/bindings/reset/nexell,reset.txt b/Documentation/devicetree/bindings/reset/nexell,reset.txt ---- a/Documentation/devicetree/bindings/reset/nexell,reset.txt 1970-01-01 01:00:00.000000000 +0100 -+++ b/Documentation/devicetree/bindings/reset/nexell,reset.txt 2018-05-06 08:49:47.766638123 +0200 -@@ -0,0 +1,32 @@ -+Nexell System Reset Controller -+====================================== -+ -+Please also refer to reset.txt in this directory for common reset -+controller binding usage. -+ -+The reset controller registers are part of the system-ctl block on s5pxx18 SoC. -+ -+Required properties: -+- compatible: may be "nexell,s5pxx18-reset" -+- reg: should be register base and length as documented in the datasheet -+- #reset-cells: 1, see below -+ -+Example: -+nexell_reset:reset@c0012000 { -+ #reset-cells = <1>; -+ compatible = "nexell,s5pxx18-reset"; -+ reg = <0xC0012000 0x3>; -+}; -+ -+Specifying reset lines connected to IP modules -+============================================== -+example: -+ -+ serial0:serial@..... { -+ ... -+ resets = <&nexell_reset RESET_ID_UART0>; -+ reset-names = "uart-reset"; -+ ... -+ }; -+ -+The index could be found in . -diff -ENwbur a/drivers/clk/Makefile b/drivers/clk/Makefile ---- a/drivers/clk/Makefile 2018-05-06 08:47:36.225299305 +0200 -+++ b/drivers/clk/Makefile 2018-05-06 08:49:49.034689576 +0200 -@@ -98,3 +98,4 @@ +diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -99,3 +99,4 @@ obj-$(CONFIG_X86) += x86/ endif obj-$(CONFIG_ARCH_ZX) += zte/ obj-$(CONFIG_ARCH_ZYNQ) += zynq/ +obj-$(CONFIG_ARCH_S5P6818) += nexell/ -diff -ENwbur a/drivers/clk/nexell/clk-s5pxx18.c b/drivers/clk/nexell/clk-s5pxx18.c ---- a/drivers/clk/nexell/clk-s5pxx18.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/clk/nexell/clk-s5pxx18.c 2018-05-06 08:49:49.054690387 +0200 -@@ -0,0 +1,589 @@ -+/* -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * Author: Youngbok, Park -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "clk-s5pxx18.h" -+ -+#define to_clk_dev(_hw) container_of(_hw, struct clk_dev, hw) -+ -+struct clk_dev_peri { -+ const char *parent_name; -+ const char *name; -+ void __iomem *base; -+ int id; -+ int clk_step; /* 1S or 2S */ -+ bool enable; -+ long rate; -+ u32 in_mask; -+ u32 in_mask1; -+ /* clock register */ -+ int div_src_0; -+ int div_val_0; -+ int invert_0; -+ int div_src_1; -+ int div_val_1; -+ int invert_1; -+ int in_extclk_1; -+ int in_extclk_2; -+ int fix_src; -+}; -+ -+struct clk_dev { -+ struct device_node *node; -+ struct clk *clk; -+ struct clk_hw hw; -+ struct clk_dev_peri *peri; -+ unsigned int rate; -+ spinlock_t lock; -+}; -+ -+struct clk_dev_map { -+ unsigned int con_enb; -+ unsigned int con_gen[4]; -+}; -+ -+#define MAX_DIVIDER ((1 << 8) - 1) /* 256, align 2 */ -+ -+static inline void clk_dev_bclk(void *base, int on) -+{ -+ struct clk_dev_map *reg = base; -+ unsigned int val = readl(®->con_enb) & ~(0x3); -+ -+ val |= (on ? 3 : 0) & 0x3; /* always BCLK */ -+ writel(val, ®->con_enb); -+} -+ -+static inline void clk_dev_pclk(void *base, int on) -+{ -+ struct clk_dev_map *reg = base; -+ unsigned int val = 0; -+ -+ if (!on) -+ return; -+ -+ val = readl(®->con_enb) & ~(1 << 3); -+ val |= (1 << 3); -+ writel(val, ®->con_enb); -+} -+ -+static inline void clk_dev_rate(void *base, int step, int src, int div) -+{ -+ struct clk_dev_map *reg = base; -+ unsigned int val = 0; -+ -+ val = readl(®->con_gen[step << 1]); -+ val &= ~(0x07 << 2); -+ val |= (src << 2); /* source */ -+ val &= ~(0xFF << 5); -+ val |= (div - 1) << 5; /* divider */ -+ writel(val, ®->con_gen[step << 1]); -+} -+ -+static inline void clk_dev_inv(void *base, int step, int inv) -+{ -+ struct clk_dev_map *reg = base; -+ unsigned int val = readl(®->con_gen[step << 1]) & ~(1 << 1); -+ -+ val |= (inv << 1); -+ writel(val, ®->con_gen[step << 1]); -+} -+ -+static inline void clk_dev_enb(void *base, int on) -+{ -+ struct clk_dev_map *reg = base; -+ unsigned int val = readl(®->con_enb) & ~(1 << 2); -+ -+ val |= ((on ? 1 : 0) << 2); -+ writel(val, ®->con_enb); -+} -+ -+static inline long clk_dev_divide(long rate, long request, int align, -+ int *divide) -+{ -+ int div = (rate / request); -+ int max = MAX_DIVIDER & ~(align - 1); -+ int adv = (div & ~(align - 1)) + align; -+ -+ if (!div) { -+ if (divide) -+ *divide = 1; -+ return rate; -+ } -+ -+ if (1 != div) -+ div &= ~(align - 1); -+ -+ if (div != adv && abs(request - rate / div) > abs(request - rate / adv)) -+ div = adv; -+ -+ div = (div > max ? max : div); -+ if (divide) -+ *divide = div; -+ -+ return (rate / div); -+} -+ -+static long clk_dev_bus_rate(struct clk_dev_peri *peri) -+{ -+ struct clk *clk; -+ const char *name = NULL; -+ long rate = 0; -+ -+ if (I_PCLK_MASK & peri->in_mask) -+ name = CLK_BUS_PCLK; -+ else if (I_BCLK_MASK & peri->in_mask) -+ name = CLK_BUS_PCLK; -+ -+ if (name) { -+ clk = clk_get(NULL, name); -+ rate = clk_get_rate(clk); -+ clk_put(clk); -+ } -+ -+ return rate ?: -EINVAL; -+} -+ -+static long clk_dev_pll_rate(int no) -+{ -+ struct clk *clk; -+ char name[16]; -+ long rate = 0; -+ -+ sprintf(name, "pll%d", no); -+ clk = clk_get(NULL, name); -+ rate = clk_get_rate(clk); -+ clk_put(clk); -+ -+ return rate; -+} -+ -+static long dev_round_rate(struct clk_hw *hw, unsigned long rate) -+{ -+ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; -+ unsigned long request = rate, new_rate = 0; -+ unsigned long clock_hz, freq_hz = 0; -+ unsigned int mask; -+ int step, div[2] = { -+ 0, -+ }; -+ int i, n, start_src = 0, max_src = 0, clk2 = 0; -+ short s1 = 0, s2 = 0, d1 = 0, d2 = 0; -+ -+ step = peri->clk_step; -+ mask = peri->in_mask; -+ pr_debug("clk: %s request = %ld [input=0x%x]\n", peri->name, rate, -+ mask); -+ -+ if (!(mask & I_CLOCK_MASK)) -+ return clk_dev_bus_rate(peri); -+ -+next: -+ if (peri->fix_src >= 0) { -+ start_src = peri->fix_src; -+ max_src = start_src + 1; -+ } else { -+ start_src = 0; -+ max_src = I_CLOCK_NUM; -+ } -+ -+ for (n = start_src ; n < max_src ; n++) { -+ if (!(((mask & I_CLOCK_MASK) >> n) & 0x1)) -+ continue; -+ -+ if (I_EXT1_BIT == n) -+ rate = peri->in_extclk_1; -+ else if (I_EXT2_BIT == n) -+ rate = peri->in_extclk_2; -+ else -+ rate = clk_dev_pll_rate(n); -+ -+ if (!rate) -+ continue; -+ -+ clock_hz = rate; -+ for (i = 0; step > i; i++) -+ rate = clk_dev_divide(rate, request, 2, &div[i]); -+ -+ if (new_rate && (abs(rate - request) > abs(new_rate - request))) -+ continue; -+ -+ pr_debug("clk: %s, pll.%d request[%ld] calc[%ld]\n", peri->name, -+ n, request, rate); -+ -+ if (clk2) { -+ s1 = -1, d1 = -1; /* not use */ -+ s2 = n, d2 = div[0]; -+ } else { -+ s1 = n, d1 = div[0]; -+ s2 = I_CLKn_BIT, d2 = div[1]; -+ } -+ -+ new_rate = rate; -+ freq_hz = clock_hz; -+ -+ if (request == rate) -+ break; -+ } -+ -+ /* search 2th clock from input */ -+ if (!clk2 && abs(new_rate - request) && -+ peri->in_mask1 & ((1 << I_CLOCK_NUM) - 1)) { -+ clk2 = 1; -+ mask = peri->in_mask1; -+ step = 1; -+ goto next; -+ } -+ -+ peri->div_src_0 = s1, peri->div_val_0 = d1; -+ peri->div_src_1 = s2, peri->div_val_1 = d2; -+ -+ pr_debug("clk: %s, step[%d] src[%d,%d] %ld /(div0: %d * div1: %d) ", -+ peri->name, peri->clk_step, peri->div_src_0, peri->div_src_1, -+ freq_hz, peri->div_val_0, peri->div_val_1); -+ pr_debug("= %ld, %ld diff (%ld)\n", new_rate, request, -+ (long)abs(new_rate - request)); -+ -+ return new_rate; -+} -+ -+static int dev_set_rate(struct clk_hw *hw, unsigned long rate) -+{ -+ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; -+ int i; -+ -+ rate = dev_round_rate(hw, rate); -+ -+ for (i = 0; peri->clk_step > i; i++) { -+ int s = (0 == i ? peri->div_src_0 : peri->div_src_1); -+ int d = (0 == i ? peri->div_val_0 : peri->div_val_1); -+ -+ if (-1 == s) -+ continue; -+ -+ /* change rate */ -+#ifdef CONFIG_EARLY_PRINTK -+ if (!strcmp(peri->name, "uart0")) -+ break; -+#endif -+ clk_dev_rate((void *)peri->base, i, s, d); -+ -+ pr_debug("clk: %s (%p) set_rate [%d] src[%d] div[%d]\n", -+ peri->name, peri->base, i, s, d); -+ } -+ peri->rate = rate; -+ return rate; -+} -+ -+/* -+ * clock devices interface -+ */ -+static int clk_dev_enable(struct clk_hw *hw) -+{ -+ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; -+ int i = 0, inv = 0; -+ -+ pr_debug("clk: %s enable (BCLK=%s, PCLK=%s)\n", peri->name, -+ I_GATE_BCLK & peri->in_mask ? "ON" : "PASS", -+ I_GATE_PCLK & peri->in_mask ? "ON" : "PASS"); -+ -+ if (peri->in_mask & I_GATE_BCLK) -+ clk_dev_bclk((void *)peri->base, 1); -+ -+ if (peri->in_mask & I_GATE_PCLK) -+ clk_dev_pclk((void *)peri->base, 1); -+ -+ if (!(peri->in_mask & I_CLOCK_MASK)) -+ return 0; -+ -+ for (i = 0, inv = peri->invert_0; peri->clk_step > i; -+ i++, inv = peri->invert_1) -+ clk_dev_inv((void *)peri->base, i, inv); -+ -+ /* restore clock rate */ -+ for (i = 0; peri->clk_step > i; i++) { -+ if (peri->fix_src < 0) { -+ int s = (0 == i ? peri->div_src_0 : peri->div_src_1); -+ int d = (0 == i ? peri->div_val_0 : peri->div_val_1); -+ -+ if (s == -1) -+ continue; -+ -+ clk_dev_rate((void *)peri->base, i, s, d); -+ } else { -+ int s = peri->fix_src; -+ int d = (0 == i ? peri->div_val_0 : peri->div_val_1); -+ if(d == 0) -+ d = 1; -+ clk_dev_rate((void *)peri->base, i, s, d); -+ } -+ } -+ -+ clk_dev_enb((void *)peri->base, 1); -+ peri->enable = true; -+ -+ return 0; -+} -+ -+static void clk_dev_disable(struct clk_hw *hw) -+{ -+ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; -+ -+ pr_debug("clk: %s disable\n", peri->name); -+ -+ if (peri->in_mask & I_GATE_BCLK) -+ clk_dev_bclk((void *)peri->base, 0); -+ -+ if (peri->in_mask & I_GATE_PCLK) -+ clk_dev_pclk((void *)peri->base, 0); -+ -+ if (!(peri->in_mask & I_CLOCK_MASK)) -+ return; -+ -+ clk_dev_rate((void *)peri->base, 0, 7, 256); /* for power save */ -+ clk_dev_enb((void *)peri->base, 0); -+ -+ peri->enable = false; -+ -+} -+ -+static unsigned long clk_dev_recalc_rate(struct clk_hw *hw, unsigned long rate) -+{ -+ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; -+ -+ pr_debug("%s: name %s, (%lu)\n", __func__, peri->name, peri->rate); -+ return peri->rate; -+} -+ -+static long clk_dev_round_rate(struct clk_hw *hw, unsigned long drate, -+ unsigned long *prate) -+{ -+ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; -+ long rate = dev_round_rate(hw, drate); -+ -+ pr_debug("%s: name %s, (%lu, %lu)\n", __func__, peri->name, drate, -+ rate); -+ return rate; -+} -+ -+static int clk_dev_set_rate(struct clk_hw *hw, unsigned long drate, -+ unsigned long prate) -+{ -+ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; -+ int rate = dev_set_rate(hw, drate); -+ -+ pr_debug("%s: name %s, rate %lu:%d\n", __func__, peri->name, drate, -+ rate); -+ return rate; -+} -+ -+static const struct clk_ops clk_dev_ops = { -+ .recalc_rate = clk_dev_recalc_rate, -+ .round_rate = clk_dev_round_rate, -+ .set_rate = clk_dev_set_rate, -+ .enable = clk_dev_enable, -+ .disable = clk_dev_disable, -+}; -+ -+static const struct clk_ops clk_empty_ops = {}; -+ -+struct clk *clk_dev_get_provider(struct of_phandle_args *clkspec, void *data) -+{ -+ struct clk_dev *clk_data = data; -+ -+ pr_debug("%s: name %s\n", __func__, clk_data->peri->name); -+ return clk_data->clk; -+} -+ -+static void __init clk_dev_parse_device_data(struct device_node *np, -+ struct clk_dev *clk_data, -+ struct device *dev) -+{ -+ struct clk_dev_peri *peri = clk_data->peri; -+ unsigned int frequency = 0; -+ u32 value; -+ -+ if (of_property_read_string(np, "clock-output-names", &peri->name)) { -+ pr_err("clock node is missing 'clock-output-names'\n"); -+ return; -+ } -+ -+ if (!of_property_read_string(np, "clock-names", &peri->parent_name)) -+ return; -+ -+ if (of_property_read_u32(np, "cell-id", &peri->id)) { -+ pr_err("clock node is missing 'cell-id'\n"); -+ return; -+ } -+ -+ if (of_property_read_u32(np, "clk-step", &peri->clk_step)) { -+ pr_err("clock node is missing 'clk-step'\n"); -+ return; -+ } -+ -+ if (of_property_read_u32(np, "clk-input", &peri->in_mask)) { -+ pr_err("clock node is missing 'clk-input'\n"); -+ return; -+ } -+ -+ if (2 == peri->clk_step && -+ of_property_read_u32(np, "clk-input1", &peri->in_mask1)) { -+ pr_err("clock node is missing 'clk-input1'\n"); -+ return; -+ } -+ -+ if (!of_property_read_u32(np, "src-force", &value)) -+ peri->fix_src = value; -+ else -+ peri->fix_src = -1; -+ -+ if (!of_property_read_u32(np, "clk-input-ext1", &value)) -+ peri->in_extclk_1 = value; -+ -+ if (!of_property_read_u32(np, "clk-input-ext2", &value)) -+ peri->in_extclk_2 = value; -+ -+ if (!of_property_read_u32(np, "clock-frequency", &frequency)) -+ clk_data->rate = frequency; -+ -+ peri->base = of_iomap(np, 0); -+ if (!peri->base) { -+ pr_err("Can't map registers for clock %s!\n", peri->name); -+ return; -+ } -+ -+ pr_debug("%8s: id=%2d, base=%p, step=%d, m=0x%04x, m1=0x%04x\n", -+ peri->name, peri->id, peri->base, peri->clk_step, -+ peri->in_mask, peri->in_mask1); -+} -+ -+struct clk *clk_dev_clock_register(const char *name, const char *parent_name, -+ struct clk_hw *hw, const struct clk_ops *ops, -+ unsigned long flags) -+{ -+ struct clk *clk; -+ struct clk_init_data init; -+ -+ init.name = name; -+ init.ops = ops; -+ init.flags = flags; -+ init.parent_names = (parent_name ? &parent_name : NULL); -+ init.num_parents = parent_name ? 1 : 0; -+ hw->init = &init; -+ pr_debug("Register clk %8s: parent %s\n", name, parent_name); -+ -+ clk = clk_register(NULL, hw); -+ if (IS_ERR(clk)) { -+ pr_err("%s: failed to register pll clock %s\n", __func__, -+ init.name); -+ return NULL; -+ } -+ -+ if (clk_register_clkdev(clk, init.name, NULL)) -+ pr_err("%s: failed to register lookup for %s", __func__, -+ init.name); -+ -+ return clk; -+} -+ -+#ifdef CONFIG_PM_SLEEP -+static int clk_syscore_suspend(void) { return 0; } -+ -+static void clk_syscore_resume(void) {} -+ -+static struct syscore_ops clk_syscore_ops = { -+ .suspend = clk_syscore_suspend, .resume = clk_syscore_resume, -+}; -+#endif /* CONFIG_PM_SLEEP */ -+ -+static void __init clk_dev_of_setup(struct device_node *node) -+{ -+ struct device_node *np; -+ struct clk_dev *clk_data = NULL; -+ struct clk_dev_peri *peri = NULL; -+ struct clk *clk; -+ int i = 0, size = (sizeof(*clk_data) + sizeof(*peri)); -+ int num_clks; -+ -+#ifdef CONFIG_ARM_NEXELL_CPUFREQ -+ char pll[16]; -+ -+ sprintf(pll, "sys-pll%d", CONFIG_NEXELL_CPUFREQ_PLLDEV); -+#endif -+ -+ num_clks = of_get_child_count(node); -+ if (!num_clks) { -+ pr_err("Failed to clocks count for clock generator!\n"); -+ return; -+ } -+ -+ clk_data = kzalloc(size * num_clks, GFP_KERNEL); -+ if (!clk_data) { -+ WARN_ON(1); -+ return; -+ } -+ peri = (struct clk_dev_peri *)(clk_data + num_clks); -+ -+ for_each_child_of_node(node, np) { -+ clk_data[i].peri = &peri[i]; -+ clk_data[i].node = np; -+ clk_dev_parse_device_data(np, &clk_data[i], NULL); -+ of_clk_add_provider(np, clk_dev_get_provider, &clk_data[i++]); -+ } -+ -+ for (i = 0; num_clks > i; i++, clk_data++) { -+ unsigned long flags = 0; -+ const struct clk_ops *ops = &clk_dev_ops; -+ -+ if (peri[i].parent_name) { -+ ops = &clk_empty_ops; -+ flags = CLK_IS_BASIC; -+#ifdef CONFIG_ARM_NEXELL_CPUFREQ -+ if (!strcmp(pll, peri[i].parent_name)) -+ flags |= CLK_SET_RATE_PARENT; -+#endif -+ } -+ -+ clk = clk_dev_clock_register(peri[i].name, peri[i].parent_name, -+ &clk_data->hw, ops, flags); -+ if (NULL == clk) -+ continue; -+ -+ clk_data->clk = clk; -+ if (clk_data->rate) { -+ pr_debug("[%s set boot rate %u]\n", node->name, -+ clk_data->rate); -+ clk_set_rate(clk, clk_data->rate); -+ } -+ } -+ -+#ifdef CONFIG_PM_SLEEP -+ register_syscore_ops(&clk_syscore_ops); -+#endif -+ -+ pr_debug("[%s:%d] %s (%d)\n", __func__, __LINE__, node->name, num_clks); -+} -+CLK_OF_DECLARE(s5pxx18, "nexell,s5pxx18,clocks", clk_dev_of_setup); -diff -ENwbur a/drivers/clk/nexell/clk-s5pxx18.h b/drivers/clk/nexell/clk-s5pxx18.h ---- a/drivers/clk/nexell/clk-s5pxx18.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/clk/nexell/clk-s5pxx18.h 2018-05-06 08:49:49.054690387 +0200 -@@ -0,0 +1,159 @@ -+/* -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * Author: Youngbok, Park -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef _CLK_S5PXX18_H -+#define _CLK_S5PXX18_H -+ -+#define I_PLL0_BIT (0) -+#define I_PLL1_BIT (1) -+#define I_PLL2_BIT (2) -+#define I_PLL3_BIT (3) -+#define I_EXT1_BIT (4) -+#define I_EXT2_BIT (5) -+#define I_CLKn_BIT (7) -+ -+#define I_CLOCK_NUM 6 /* PLL0, PLL1, PLL2, PLL3, EXT1, EXT2 */ -+ -+#ifdef CONFIG_ARM_NEXELL_CPUFREQ -+#define I_EXECEPT_CLK (1 << CONFIG_NEXELL_CPUFREQ_PLLDEV) -+#else -+#define I_EXECEPT_CLK (0) -+#endif -+ -+#define I_CLOCK_MASK (((1 << I_CLOCK_NUM) - 1) & ~I_EXECEPT_CLK) -+/* -+ * clock -+ */ -+#define CLK_CPU_PLL0 "sys-pll0" -+#define CLK_CPU_PLL1 "sys-pll1" -+#define CLK_CPU_PLL2 "sys-pll2" -+#define CLK_CPU_PLL3 "sys-pll3" -+#define CLK_CPU_FCLK "sys-cfclk" -+#define CLK_CPU_HCLK "sys-chclk" -+#define CLK_MEM_FCLK "sys-mfclk" -+#define CLK_MEM_DCLK "sys-mdclk" -+#define CLK_MEM_BCLK "sys-mbclk" -+#define CLK_MEM_PCLK "sys-mpclk" -+#define CLK_BUS_BCLK "sys-bbclk" -+#define CLK_BUS_PCLK "sys-bpclk" -+#define CLK_VPU_BCLK "sys-vpubclk" -+#define CLK_VPU_PCLK "sys-vpupclk" -+#define CLK_DIS_BCLK "sys-disbclk" -+#define CLK_DIS_PCLK "sys-disspclk" -+#define CLK_CCI_BCLK "sys-ccibclk" -+#define CLK_CCI_PCLK "sys-ccipclk" -+#define CLK_G3D_BCLK "sys-g3dbclk" -+ -+#define CLK_ID_TIMER_1 0 -+#define CLK_ID_TIMER_2 1 -+#define CLK_ID_TIMER_3 2 -+#define CLK_ID_PWM_1 3 -+#define CLK_ID_PWM_2 4 -+#define CLK_ID_PWM_3 5 -+#define CLK_ID_I2C_0 6 -+#define CLK_ID_I2C_1 7 -+#define CLK_ID_I2C_2 8 -+#define CLK_ID_MIPI 9 -+#define CLK_ID_GMAC 10 /* External Clock 1 */ -+#define CLK_ID_SPDIF_TX 11 -+#define CLK_ID_MPEGTSI 12 -+#define CLK_ID_PWM_0 13 -+#define CLK_ID_TIMER_0 14 -+#define CLK_ID_I2S_0 15 /* External Clock 1 */ -+#define CLK_ID_I2S_1 16 /* External Clock 1 */ -+#define CLK_ID_I2S_2 17 /* External Clock 1 */ -+#define CLK_ID_SDHC_0 18 -+#define CLK_ID_SDHC_1 19 -+#define CLK_ID_SDHC_2 20 -+#define CLK_ID_VR 21 -+#define CLK_ID_UART_0 22 /* UART0_MODULE */ -+#define CLK_ID_UART_2 23 /* UART1_MODULE */ -+#define CLK_ID_UART_1 24 /* pl01115_Uart_modem_MODULE */ -+#define CLK_ID_UART_3 25 /* pl01115_Uart_nodma0_MODULE */ -+#define CLK_ID_UART_4 26 /* pl01115_Uart_nodma1_MODULE */ -+#define CLK_ID_UART_5 27 /* pl01115_Uart_nodma2_MODULE */ -+#define CLK_ID_DIT 28 -+#define CLK_ID_PPM 29 -+#define CLK_ID_VIP_0 30 /* External Clock 1 */ -+#define CLK_ID_VIP_1 31 /* External Clock 1, 2 */ -+#define CLK_ID_USB2HOST 32 /* External Clock 2 */ -+#define CLK_ID_CODA 33 -+#define CLK_ID_CRYPTO 34 -+#define CLK_ID_SCALER 35 -+#define CLK_ID_PDM 36 -+#define CLK_ID_SPI_0 37 -+#define CLK_ID_SPI_1 38 -+#define CLK_ID_SPI_2 39 -+#define CLK_ID_MAX 39 -+#define CLK_ID_USBOTG 40 /* Shared with USB2HOST */ -+ -+#define I_PLL0_BIT (0) -+#define I_PLL1_BIT (1) -+#define I_PLL2_BIT (2) -+#define I_PLL3_BIT (3) -+#define I_EXT1_BIT (4) -+#define I_EXT2_BIT (5) -+#define I_CLKn_BIT (7) -+ -+#define I_PLL0 (1 << I_PLL0_BIT) -+#define I_PLL1 (1 << I_PLL1_BIT) -+#define I_PLL2 (1 << I_PLL2_BIT) -+#define I_PLL3 (1 << I_PLL3_BIT) -+#define I_EXTCLK1 (1 << I_EXT1_BIT) -+#define I_EXTCLK2 (1 << I_EXT2_BIT) -+ -+#define I_PLL_0_1 (I_PLL0 | I_PLL1) -+#define I_PLL_0_2 (I_PLL_0_1 | I_PLL2) -+#define I_PLL_0_3 (I_PLL_0_2 | I_PLL3) -+#define I_CLKnOUT (0) -+ -+#define I_PCLK (1 << 8) -+#define I_BCLK (1 << 9) -+#define I_GATE_PCLK (1 << 12) -+#define I_GATE_BCLK (1 << 13) -+#define I_PCLK_MASK (I_GATE_PCLK | I_PCLK) -+#define I_BCLK_MASK (I_GATE_BCLK | I_BCLK) -+ -+#define CLK_INPUT_TIMER (I_PLL_0_2) -+#define CLK_INPUT_UART (I_PLL_0_2) -+#define CLK_INPUT_PWM (I_PLL_0_2) -+#define CLK_INPUT_I2C (I_GATE_PCLK) -+#define CLK_INPUT_SDHC (I_PLL_0_2 | I_GATE_PCLK) -+#define CLK_INPUT_I2S (I_PLL_0_3 | I_EXTCLK1) -+#define CLK_INPUT_I2S_IN1 (I_CLKnOUT) -+#define CLK_INPUT_SPI (I_PLL_0_2) -+#define CLK_INPUT_VIP0 (I_PLL_0_3 | I_EXTCLK1 | I_GATE_BCLK) -+#define CLK_INPUT_VIP1 (I_PLL_0_3 | I_EXTCLK1 | I_EXTCLK2 | I_GATE_BCLK) -+#define CLK_INPUT_MIPI (I_PLL_0_2) -+#define CLK_INPUT_GMAC (I_PLL_0_3 | I_EXTCLK1) -+#define CLK_INPUT_GMAC_IN1 (I_CLKnOUT) -+#define CLK_INPUT_SPDIFTX (I_PLL_0_2) -+#define CLK_INPUT_MPEGTS (I_GATE_BCLK) -+#define CLK_INPUT_VR (I_GATE_BCLK) -+#define CLK_INPUT_DIT (I_GATE_BCLK) -+#define CLK_INPUT_PPM (I_PLL_0_2) -+#define CLK_INPUT_EHCI (I_PLL_0_3) -+#define CLK_INPUT_EHCI_IN1 (I_PLL_0_3 | I_EXTCLK1) -+#define CLK_INPUT_VPU (I_GATE_PCLK | I_GATE_BCLK) -+#define CLK_INPUT_CRYPTO (I_GATE_PCLK) -+#define CLK_INPUT_SCALER (I_GATE_BCLK) -+#define CLK_INPUT_OTG (I_PLL_0_3) -+#define CLK_INPUT_OTG_IN1 (I_PLL_0_3 | I_EXTCLK1) -+#define CLK_INPUT_PDM (I_GATE_PCLK) -+ -+#endif -diff -ENwbur a/drivers/clk/nexell/clk-s5pxx18-pll.c b/drivers/clk/nexell/clk-s5pxx18-pll.c ---- a/drivers/clk/nexell/clk-s5pxx18-pll.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/clk/nexell/clk-s5pxx18-pll.c 2018-05-06 08:49:49.054690387 +0200 +diff --git a/drivers/clk/nexell/Makefile b/drivers/clk/nexell/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/clk/nexell/Makefile +@@ -0,0 +1 @@ ++obj-y += clk-s5pxx18.o clk-s5pxx18-pll.o +diff --git a/drivers/clk/nexell/clk-s5pxx18-pll.c b/drivers/clk/nexell/clk-s5pxx18-pll.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/clk/nexell/clk-s5pxx18-pll.c @@ -0,0 +1,838 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -9564,9 +9465,11 @@ diff -ENwbur a/drivers/clk/nexell/clk-s5pxx18-pll.c b/drivers/clk/nexell/clk-s5p +} + +CLK_OF_DECLARE(s5pxx18, "nexell,s5pxx18,pll", clk_pll_of_setup); -diff -ENwbur a/drivers/clk/nexell/clk-s5pxx18-pll.h b/drivers/clk/nexell/clk-s5pxx18-pll.h ---- a/drivers/clk/nexell/clk-s5pxx18-pll.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/clk/nexell/clk-s5pxx18-pll.h 2018-05-06 08:49:49.054690387 +0200 +diff --git a/drivers/clk/nexell/clk-s5pxx18-pll.h b/drivers/clk/nexell/clk-s5pxx18-pll.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/clk/nexell/clk-s5pxx18-pll.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -9644,18 +9547,774 @@ diff -ENwbur a/drivers/clk/nexell/clk-s5pxx18-pll.h b/drivers/clk/nexell/clk-s5p +#define to_clk_core(_hw) container_of(_hw, struct clk_core, hw) + +#endif -diff -ENwbur a/drivers/clk/nexell/Makefile b/drivers/clk/nexell/Makefile ---- a/drivers/clk/nexell/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/clk/nexell/Makefile 2018-05-06 08:49:49.054690387 +0200 -@@ -0,0 +1 @@ -+obj-y += clk-s5pxx18.o clk-s5pxx18-pll.o -diff -ENwbur a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig ---- a/drivers/clocksource/Kconfig 2018-05-06 08:47:36.269301092 +0200 -+++ b/drivers/clocksource/Kconfig 2018-05-06 08:49:49.082691523 +0200 -@@ -615,4 +615,11 @@ +diff --git a/drivers/clk/nexell/clk-s5pxx18.c b/drivers/clk/nexell/clk-s5pxx18.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/clk/nexell/clk-s5pxx18.c +@@ -0,0 +1,589 @@ ++/* ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * Author: Youngbok, Park ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "clk-s5pxx18.h" ++ ++#define to_clk_dev(_hw) container_of(_hw, struct clk_dev, hw) ++ ++struct clk_dev_peri { ++ const char *parent_name; ++ const char *name; ++ void __iomem *base; ++ int id; ++ int clk_step; /* 1S or 2S */ ++ bool enable; ++ long rate; ++ u32 in_mask; ++ u32 in_mask1; ++ /* clock register */ ++ int div_src_0; ++ int div_val_0; ++ int invert_0; ++ int div_src_1; ++ int div_val_1; ++ int invert_1; ++ int in_extclk_1; ++ int in_extclk_2; ++ int fix_src; ++}; ++ ++struct clk_dev { ++ struct device_node *node; ++ struct clk *clk; ++ struct clk_hw hw; ++ struct clk_dev_peri *peri; ++ unsigned int rate; ++ spinlock_t lock; ++}; ++ ++struct clk_dev_map { ++ unsigned int con_enb; ++ unsigned int con_gen[4]; ++}; ++ ++#define MAX_DIVIDER ((1 << 8) - 1) /* 256, align 2 */ ++ ++static inline void clk_dev_bclk(void *base, int on) ++{ ++ struct clk_dev_map *reg = base; ++ unsigned int val = readl(®->con_enb) & ~(0x3); ++ ++ val |= (on ? 3 : 0) & 0x3; /* always BCLK */ ++ writel(val, ®->con_enb); ++} ++ ++static inline void clk_dev_pclk(void *base, int on) ++{ ++ struct clk_dev_map *reg = base; ++ unsigned int val = 0; ++ ++ if (!on) ++ return; ++ ++ val = readl(®->con_enb) & ~(1 << 3); ++ val |= (1 << 3); ++ writel(val, ®->con_enb); ++} ++ ++static inline void clk_dev_rate(void *base, int step, int src, int div) ++{ ++ struct clk_dev_map *reg = base; ++ unsigned int val = 0; ++ ++ val = readl(®->con_gen[step << 1]); ++ val &= ~(0x07 << 2); ++ val |= (src << 2); /* source */ ++ val &= ~(0xFF << 5); ++ val |= (div - 1) << 5; /* divider */ ++ writel(val, ®->con_gen[step << 1]); ++} ++ ++static inline void clk_dev_inv(void *base, int step, int inv) ++{ ++ struct clk_dev_map *reg = base; ++ unsigned int val = readl(®->con_gen[step << 1]) & ~(1 << 1); ++ ++ val |= (inv << 1); ++ writel(val, ®->con_gen[step << 1]); ++} ++ ++static inline void clk_dev_enb(void *base, int on) ++{ ++ struct clk_dev_map *reg = base; ++ unsigned int val = readl(®->con_enb) & ~(1 << 2); ++ ++ val |= ((on ? 1 : 0) << 2); ++ writel(val, ®->con_enb); ++} ++ ++static inline long clk_dev_divide(long rate, long request, int align, ++ int *divide) ++{ ++ int div = (rate / request); ++ int max = MAX_DIVIDER & ~(align - 1); ++ int adv = (div & ~(align - 1)) + align; ++ ++ if (!div) { ++ if (divide) ++ *divide = 1; ++ return rate; ++ } ++ ++ if (1 != div) ++ div &= ~(align - 1); ++ ++ if (div != adv && abs(request - rate / div) > abs(request - rate / adv)) ++ div = adv; ++ ++ div = (div > max ? max : div); ++ if (divide) ++ *divide = div; ++ ++ return (rate / div); ++} ++ ++static long clk_dev_bus_rate(struct clk_dev_peri *peri) ++{ ++ struct clk *clk; ++ const char *name = NULL; ++ long rate = 0; ++ ++ if (I_PCLK_MASK & peri->in_mask) ++ name = CLK_BUS_PCLK; ++ else if (I_BCLK_MASK & peri->in_mask) ++ name = CLK_BUS_PCLK; ++ ++ if (name) { ++ clk = clk_get(NULL, name); ++ rate = clk_get_rate(clk); ++ clk_put(clk); ++ } ++ ++ return rate ?: -EINVAL; ++} ++ ++static long clk_dev_pll_rate(int no) ++{ ++ struct clk *clk; ++ char name[16]; ++ long rate = 0; ++ ++ sprintf(name, "pll%d", no); ++ clk = clk_get(NULL, name); ++ rate = clk_get_rate(clk); ++ clk_put(clk); ++ ++ return rate; ++} ++ ++static long dev_round_rate(struct clk_hw *hw, unsigned long rate) ++{ ++ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; ++ unsigned long request = rate, new_rate = 0; ++ unsigned long clock_hz, freq_hz = 0; ++ unsigned int mask; ++ int step, div[2] = { ++ 0, ++ }; ++ int i, n, start_src = 0, max_src = 0, clk2 = 0; ++ short s1 = 0, s2 = 0, d1 = 0, d2 = 0; ++ ++ step = peri->clk_step; ++ mask = peri->in_mask; ++ pr_debug("clk: %s request = %ld [input=0x%x]\n", peri->name, rate, ++ mask); ++ ++ if (!(mask & I_CLOCK_MASK)) ++ return clk_dev_bus_rate(peri); ++ ++next: ++ if (peri->fix_src >= 0) { ++ start_src = peri->fix_src; ++ max_src = start_src + 1; ++ } else { ++ start_src = 0; ++ max_src = I_CLOCK_NUM; ++ } ++ ++ for (n = start_src ; n < max_src ; n++) { ++ if (!(((mask & I_CLOCK_MASK) >> n) & 0x1)) ++ continue; ++ ++ if (I_EXT1_BIT == n) ++ rate = peri->in_extclk_1; ++ else if (I_EXT2_BIT == n) ++ rate = peri->in_extclk_2; ++ else ++ rate = clk_dev_pll_rate(n); ++ ++ if (!rate) ++ continue; ++ ++ clock_hz = rate; ++ for (i = 0; step > i; i++) ++ rate = clk_dev_divide(rate, request, 2, &div[i]); ++ ++ if (new_rate && (abs(rate - request) > abs(new_rate - request))) ++ continue; ++ ++ pr_debug("clk: %s, pll.%d request[%ld] calc[%ld]\n", peri->name, ++ n, request, rate); ++ ++ if (clk2) { ++ s1 = -1, d1 = -1; /* not use */ ++ s2 = n, d2 = div[0]; ++ } else { ++ s1 = n, d1 = div[0]; ++ s2 = I_CLKn_BIT, d2 = div[1]; ++ } ++ ++ new_rate = rate; ++ freq_hz = clock_hz; ++ ++ if (request == rate) ++ break; ++ } ++ ++ /* search 2th clock from input */ ++ if (!clk2 && abs(new_rate - request) && ++ peri->in_mask1 & ((1 << I_CLOCK_NUM) - 1)) { ++ clk2 = 1; ++ mask = peri->in_mask1; ++ step = 1; ++ goto next; ++ } ++ ++ peri->div_src_0 = s1, peri->div_val_0 = d1; ++ peri->div_src_1 = s2, peri->div_val_1 = d2; ++ ++ pr_debug("clk: %s, step[%d] src[%d,%d] %ld /(div0: %d * div1: %d) ", ++ peri->name, peri->clk_step, peri->div_src_0, peri->div_src_1, ++ freq_hz, peri->div_val_0, peri->div_val_1); ++ pr_debug("= %ld, %ld diff (%ld)\n", new_rate, request, ++ (long)abs(new_rate - request)); ++ ++ return new_rate; ++} ++ ++static int dev_set_rate(struct clk_hw *hw, unsigned long rate) ++{ ++ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; ++ int i; ++ ++ rate = dev_round_rate(hw, rate); ++ ++ for (i = 0; peri->clk_step > i; i++) { ++ int s = (0 == i ? peri->div_src_0 : peri->div_src_1); ++ int d = (0 == i ? peri->div_val_0 : peri->div_val_1); ++ ++ if (-1 == s) ++ continue; ++ ++ /* change rate */ ++#ifdef CONFIG_EARLY_PRINTK ++ if (!strcmp(peri->name, "uart0")) ++ break; ++#endif ++ clk_dev_rate((void *)peri->base, i, s, d); ++ ++ pr_debug("clk: %s (%p) set_rate [%d] src[%d] div[%d]\n", ++ peri->name, peri->base, i, s, d); ++ } ++ peri->rate = rate; ++ return rate; ++} ++ ++/* ++ * clock devices interface ++ */ ++static int clk_dev_enable(struct clk_hw *hw) ++{ ++ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; ++ int i = 0, inv = 0; ++ ++ pr_debug("clk: %s enable (BCLK=%s, PCLK=%s)\n", peri->name, ++ I_GATE_BCLK & peri->in_mask ? "ON" : "PASS", ++ I_GATE_PCLK & peri->in_mask ? "ON" : "PASS"); ++ ++ if (peri->in_mask & I_GATE_BCLK) ++ clk_dev_bclk((void *)peri->base, 1); ++ ++ if (peri->in_mask & I_GATE_PCLK) ++ clk_dev_pclk((void *)peri->base, 1); ++ ++ if (!(peri->in_mask & I_CLOCK_MASK)) ++ return 0; ++ ++ for (i = 0, inv = peri->invert_0; peri->clk_step > i; ++ i++, inv = peri->invert_1) ++ clk_dev_inv((void *)peri->base, i, inv); ++ ++ /* restore clock rate */ ++ for (i = 0; peri->clk_step > i; i++) { ++ if (peri->fix_src < 0) { ++ int s = (0 == i ? peri->div_src_0 : peri->div_src_1); ++ int d = (0 == i ? peri->div_val_0 : peri->div_val_1); ++ ++ if (s == -1) ++ continue; ++ ++ clk_dev_rate((void *)peri->base, i, s, d); ++ } else { ++ int s = peri->fix_src; ++ int d = (0 == i ? peri->div_val_0 : peri->div_val_1); ++ if(d == 0) ++ d = 1; ++ clk_dev_rate((void *)peri->base, i, s, d); ++ } ++ } ++ ++ clk_dev_enb((void *)peri->base, 1); ++ peri->enable = true; ++ ++ return 0; ++} ++ ++static void clk_dev_disable(struct clk_hw *hw) ++{ ++ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; ++ ++ pr_debug("clk: %s disable\n", peri->name); ++ ++ if (peri->in_mask & I_GATE_BCLK) ++ clk_dev_bclk((void *)peri->base, 0); ++ ++ if (peri->in_mask & I_GATE_PCLK) ++ clk_dev_pclk((void *)peri->base, 0); ++ ++ if (!(peri->in_mask & I_CLOCK_MASK)) ++ return; ++ ++ clk_dev_rate((void *)peri->base, 0, 7, 256); /* for power save */ ++ clk_dev_enb((void *)peri->base, 0); ++ ++ peri->enable = false; ++ ++} ++ ++static unsigned long clk_dev_recalc_rate(struct clk_hw *hw, unsigned long rate) ++{ ++ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; ++ ++ pr_debug("%s: name %s, (%lu)\n", __func__, peri->name, peri->rate); ++ return peri->rate; ++} ++ ++static long clk_dev_round_rate(struct clk_hw *hw, unsigned long drate, ++ unsigned long *prate) ++{ ++ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; ++ long rate = dev_round_rate(hw, drate); ++ ++ pr_debug("%s: name %s, (%lu, %lu)\n", __func__, peri->name, drate, ++ rate); ++ return rate; ++} ++ ++static int clk_dev_set_rate(struct clk_hw *hw, unsigned long drate, ++ unsigned long prate) ++{ ++ struct clk_dev_peri *peri = to_clk_dev(hw)->peri; ++ int rate = dev_set_rate(hw, drate); ++ ++ pr_debug("%s: name %s, rate %lu:%d\n", __func__, peri->name, drate, ++ rate); ++ return rate; ++} ++ ++static const struct clk_ops clk_dev_ops = { ++ .recalc_rate = clk_dev_recalc_rate, ++ .round_rate = clk_dev_round_rate, ++ .set_rate = clk_dev_set_rate, ++ .enable = clk_dev_enable, ++ .disable = clk_dev_disable, ++}; ++ ++static const struct clk_ops clk_empty_ops = {}; ++ ++struct clk *clk_dev_get_provider(struct of_phandle_args *clkspec, void *data) ++{ ++ struct clk_dev *clk_data = data; ++ ++ pr_debug("%s: name %s\n", __func__, clk_data->peri->name); ++ return clk_data->clk; ++} ++ ++static void __init clk_dev_parse_device_data(struct device_node *np, ++ struct clk_dev *clk_data, ++ struct device *dev) ++{ ++ struct clk_dev_peri *peri = clk_data->peri; ++ unsigned int frequency = 0; ++ u32 value; ++ ++ if (of_property_read_string(np, "clock-output-names", &peri->name)) { ++ pr_err("clock node is missing 'clock-output-names'\n"); ++ return; ++ } ++ ++ if (!of_property_read_string(np, "clock-names", &peri->parent_name)) ++ return; ++ ++ if (of_property_read_u32(np, "cell-id", &peri->id)) { ++ pr_err("clock node is missing 'cell-id'\n"); ++ return; ++ } ++ ++ if (of_property_read_u32(np, "clk-step", &peri->clk_step)) { ++ pr_err("clock node is missing 'clk-step'\n"); ++ return; ++ } ++ ++ if (of_property_read_u32(np, "clk-input", &peri->in_mask)) { ++ pr_err("clock node is missing 'clk-input'\n"); ++ return; ++ } ++ ++ if (2 == peri->clk_step && ++ of_property_read_u32(np, "clk-input1", &peri->in_mask1)) { ++ pr_err("clock node is missing 'clk-input1'\n"); ++ return; ++ } ++ ++ if (!of_property_read_u32(np, "src-force", &value)) ++ peri->fix_src = value; ++ else ++ peri->fix_src = -1; ++ ++ if (!of_property_read_u32(np, "clk-input-ext1", &value)) ++ peri->in_extclk_1 = value; ++ ++ if (!of_property_read_u32(np, "clk-input-ext2", &value)) ++ peri->in_extclk_2 = value; ++ ++ if (!of_property_read_u32(np, "clock-frequency", &frequency)) ++ clk_data->rate = frequency; ++ ++ peri->base = of_iomap(np, 0); ++ if (!peri->base) { ++ pr_err("Can't map registers for clock %s!\n", peri->name); ++ return; ++ } ++ ++ pr_debug("%8s: id=%2d, base=%p, step=%d, m=0x%04x, m1=0x%04x\n", ++ peri->name, peri->id, peri->base, peri->clk_step, ++ peri->in_mask, peri->in_mask1); ++} ++ ++struct clk *clk_dev_clock_register(const char *name, const char *parent_name, ++ struct clk_hw *hw, const struct clk_ops *ops, ++ unsigned long flags) ++{ ++ struct clk *clk; ++ struct clk_init_data init; ++ ++ init.name = name; ++ init.ops = ops; ++ init.flags = flags; ++ init.parent_names = (parent_name ? &parent_name : NULL); ++ init.num_parents = parent_name ? 1 : 0; ++ hw->init = &init; ++ pr_debug("Register clk %8s: parent %s\n", name, parent_name); ++ ++ clk = clk_register(NULL, hw); ++ if (IS_ERR(clk)) { ++ pr_err("%s: failed to register pll clock %s\n", __func__, ++ init.name); ++ return NULL; ++ } ++ ++ if (clk_register_clkdev(clk, init.name, NULL)) ++ pr_err("%s: failed to register lookup for %s", __func__, ++ init.name); ++ ++ return clk; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int clk_syscore_suspend(void) { return 0; } ++ ++static void clk_syscore_resume(void) {} ++ ++static struct syscore_ops clk_syscore_ops = { ++ .suspend = clk_syscore_suspend, .resume = clk_syscore_resume, ++}; ++#endif /* CONFIG_PM_SLEEP */ ++ ++static void __init clk_dev_of_setup(struct device_node *node) ++{ ++ struct device_node *np; ++ struct clk_dev *clk_data = NULL; ++ struct clk_dev_peri *peri = NULL; ++ struct clk *clk; ++ int i = 0, size = (sizeof(*clk_data) + sizeof(*peri)); ++ int num_clks; ++ ++#ifdef CONFIG_ARM_NEXELL_CPUFREQ ++ char pll[16]; ++ ++ sprintf(pll, "sys-pll%d", CONFIG_NEXELL_CPUFREQ_PLLDEV); ++#endif ++ ++ num_clks = of_get_child_count(node); ++ if (!num_clks) { ++ pr_err("Failed to clocks count for clock generator!\n"); ++ return; ++ } ++ ++ clk_data = kzalloc(size * num_clks, GFP_KERNEL); ++ if (!clk_data) { ++ WARN_ON(1); ++ return; ++ } ++ peri = (struct clk_dev_peri *)(clk_data + num_clks); ++ ++ for_each_child_of_node(node, np) { ++ clk_data[i].peri = &peri[i]; ++ clk_data[i].node = np; ++ clk_dev_parse_device_data(np, &clk_data[i], NULL); ++ of_clk_add_provider(np, clk_dev_get_provider, &clk_data[i++]); ++ } ++ ++ for (i = 0; num_clks > i; i++, clk_data++) { ++ unsigned long flags = 0; ++ const struct clk_ops *ops = &clk_dev_ops; ++ ++ if (peri[i].parent_name) { ++ ops = &clk_empty_ops; ++ flags = CLK_IS_BASIC; ++#ifdef CONFIG_ARM_NEXELL_CPUFREQ ++ if (!strcmp(pll, peri[i].parent_name)) ++ flags |= CLK_SET_RATE_PARENT; ++#endif ++ } ++ ++ clk = clk_dev_clock_register(peri[i].name, peri[i].parent_name, ++ &clk_data->hw, ops, flags); ++ if (NULL == clk) ++ continue; ++ ++ clk_data->clk = clk; ++ if (clk_data->rate) { ++ pr_debug("[%s set boot rate %u]\n", node->name, ++ clk_data->rate); ++ clk_set_rate(clk, clk_data->rate); ++ } ++ } ++ ++#ifdef CONFIG_PM_SLEEP ++ register_syscore_ops(&clk_syscore_ops); ++#endif ++ ++ pr_debug("[%s:%d] %s (%d)\n", __func__, __LINE__, node->name, num_clks); ++} ++CLK_OF_DECLARE(s5pxx18, "nexell,s5pxx18,clocks", clk_dev_of_setup); +diff --git a/drivers/clk/nexell/clk-s5pxx18.h b/drivers/clk/nexell/clk-s5pxx18.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/clk/nexell/clk-s5pxx18.h +@@ -0,0 +1,159 @@ ++/* ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * Author: Youngbok, Park ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef _CLK_S5PXX18_H ++#define _CLK_S5PXX18_H ++ ++#define I_PLL0_BIT (0) ++#define I_PLL1_BIT (1) ++#define I_PLL2_BIT (2) ++#define I_PLL3_BIT (3) ++#define I_EXT1_BIT (4) ++#define I_EXT2_BIT (5) ++#define I_CLKn_BIT (7) ++ ++#define I_CLOCK_NUM 6 /* PLL0, PLL1, PLL2, PLL3, EXT1, EXT2 */ ++ ++#ifdef CONFIG_ARM_NEXELL_CPUFREQ ++#define I_EXECEPT_CLK (1 << CONFIG_NEXELL_CPUFREQ_PLLDEV) ++#else ++#define I_EXECEPT_CLK (0) ++#endif ++ ++#define I_CLOCK_MASK (((1 << I_CLOCK_NUM) - 1) & ~I_EXECEPT_CLK) ++/* ++ * clock ++ */ ++#define CLK_CPU_PLL0 "sys-pll0" ++#define CLK_CPU_PLL1 "sys-pll1" ++#define CLK_CPU_PLL2 "sys-pll2" ++#define CLK_CPU_PLL3 "sys-pll3" ++#define CLK_CPU_FCLK "sys-cfclk" ++#define CLK_CPU_HCLK "sys-chclk" ++#define CLK_MEM_FCLK "sys-mfclk" ++#define CLK_MEM_DCLK "sys-mdclk" ++#define CLK_MEM_BCLK "sys-mbclk" ++#define CLK_MEM_PCLK "sys-mpclk" ++#define CLK_BUS_BCLK "sys-bbclk" ++#define CLK_BUS_PCLK "sys-bpclk" ++#define CLK_VPU_BCLK "sys-vpubclk" ++#define CLK_VPU_PCLK "sys-vpupclk" ++#define CLK_DIS_BCLK "sys-disbclk" ++#define CLK_DIS_PCLK "sys-disspclk" ++#define CLK_CCI_BCLK "sys-ccibclk" ++#define CLK_CCI_PCLK "sys-ccipclk" ++#define CLK_G3D_BCLK "sys-g3dbclk" ++ ++#define CLK_ID_TIMER_1 0 ++#define CLK_ID_TIMER_2 1 ++#define CLK_ID_TIMER_3 2 ++#define CLK_ID_PWM_1 3 ++#define CLK_ID_PWM_2 4 ++#define CLK_ID_PWM_3 5 ++#define CLK_ID_I2C_0 6 ++#define CLK_ID_I2C_1 7 ++#define CLK_ID_I2C_2 8 ++#define CLK_ID_MIPI 9 ++#define CLK_ID_GMAC 10 /* External Clock 1 */ ++#define CLK_ID_SPDIF_TX 11 ++#define CLK_ID_MPEGTSI 12 ++#define CLK_ID_PWM_0 13 ++#define CLK_ID_TIMER_0 14 ++#define CLK_ID_I2S_0 15 /* External Clock 1 */ ++#define CLK_ID_I2S_1 16 /* External Clock 1 */ ++#define CLK_ID_I2S_2 17 /* External Clock 1 */ ++#define CLK_ID_SDHC_0 18 ++#define CLK_ID_SDHC_1 19 ++#define CLK_ID_SDHC_2 20 ++#define CLK_ID_VR 21 ++#define CLK_ID_UART_0 22 /* UART0_MODULE */ ++#define CLK_ID_UART_2 23 /* UART1_MODULE */ ++#define CLK_ID_UART_1 24 /* pl01115_Uart_modem_MODULE */ ++#define CLK_ID_UART_3 25 /* pl01115_Uart_nodma0_MODULE */ ++#define CLK_ID_UART_4 26 /* pl01115_Uart_nodma1_MODULE */ ++#define CLK_ID_UART_5 27 /* pl01115_Uart_nodma2_MODULE */ ++#define CLK_ID_DIT 28 ++#define CLK_ID_PPM 29 ++#define CLK_ID_VIP_0 30 /* External Clock 1 */ ++#define CLK_ID_VIP_1 31 /* External Clock 1, 2 */ ++#define CLK_ID_USB2HOST 32 /* External Clock 2 */ ++#define CLK_ID_CODA 33 ++#define CLK_ID_CRYPTO 34 ++#define CLK_ID_SCALER 35 ++#define CLK_ID_PDM 36 ++#define CLK_ID_SPI_0 37 ++#define CLK_ID_SPI_1 38 ++#define CLK_ID_SPI_2 39 ++#define CLK_ID_MAX 39 ++#define CLK_ID_USBOTG 40 /* Shared with USB2HOST */ ++ ++#define I_PLL0_BIT (0) ++#define I_PLL1_BIT (1) ++#define I_PLL2_BIT (2) ++#define I_PLL3_BIT (3) ++#define I_EXT1_BIT (4) ++#define I_EXT2_BIT (5) ++#define I_CLKn_BIT (7) ++ ++#define I_PLL0 (1 << I_PLL0_BIT) ++#define I_PLL1 (1 << I_PLL1_BIT) ++#define I_PLL2 (1 << I_PLL2_BIT) ++#define I_PLL3 (1 << I_PLL3_BIT) ++#define I_EXTCLK1 (1 << I_EXT1_BIT) ++#define I_EXTCLK2 (1 << I_EXT2_BIT) ++ ++#define I_PLL_0_1 (I_PLL0 | I_PLL1) ++#define I_PLL_0_2 (I_PLL_0_1 | I_PLL2) ++#define I_PLL_0_3 (I_PLL_0_2 | I_PLL3) ++#define I_CLKnOUT (0) ++ ++#define I_PCLK (1 << 8) ++#define I_BCLK (1 << 9) ++#define I_GATE_PCLK (1 << 12) ++#define I_GATE_BCLK (1 << 13) ++#define I_PCLK_MASK (I_GATE_PCLK | I_PCLK) ++#define I_BCLK_MASK (I_GATE_BCLK | I_BCLK) ++ ++#define CLK_INPUT_TIMER (I_PLL_0_2) ++#define CLK_INPUT_UART (I_PLL_0_2) ++#define CLK_INPUT_PWM (I_PLL_0_2) ++#define CLK_INPUT_I2C (I_GATE_PCLK) ++#define CLK_INPUT_SDHC (I_PLL_0_2 | I_GATE_PCLK) ++#define CLK_INPUT_I2S (I_PLL_0_3 | I_EXTCLK1) ++#define CLK_INPUT_I2S_IN1 (I_CLKnOUT) ++#define CLK_INPUT_SPI (I_PLL_0_2) ++#define CLK_INPUT_VIP0 (I_PLL_0_3 | I_EXTCLK1 | I_GATE_BCLK) ++#define CLK_INPUT_VIP1 (I_PLL_0_3 | I_EXTCLK1 | I_EXTCLK2 | I_GATE_BCLK) ++#define CLK_INPUT_MIPI (I_PLL_0_2) ++#define CLK_INPUT_GMAC (I_PLL_0_3 | I_EXTCLK1) ++#define CLK_INPUT_GMAC_IN1 (I_CLKnOUT) ++#define CLK_INPUT_SPDIFTX (I_PLL_0_2) ++#define CLK_INPUT_MPEGTS (I_GATE_BCLK) ++#define CLK_INPUT_VR (I_GATE_BCLK) ++#define CLK_INPUT_DIT (I_GATE_BCLK) ++#define CLK_INPUT_PPM (I_PLL_0_2) ++#define CLK_INPUT_EHCI (I_PLL_0_3) ++#define CLK_INPUT_EHCI_IN1 (I_PLL_0_3 | I_EXTCLK1) ++#define CLK_INPUT_VPU (I_GATE_PCLK | I_GATE_BCLK) ++#define CLK_INPUT_CRYPTO (I_GATE_PCLK) ++#define CLK_INPUT_SCALER (I_GATE_BCLK) ++#define CLK_INPUT_OTG (I_PLL_0_3) ++#define CLK_INPUT_OTG_IN1 (I_PLL_0_3 | I_EXTCLK1) ++#define CLK_INPUT_PDM (I_GATE_PCLK) ++ ++#endif +diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -615,4 +615,11 @@ config CLKSRC_ST_LPC Enable this option to use the Low Power controller timer as clocksource. - + +config CLKSRC_NEXELL_TIMER + bool "Support for s5p6818 timer generation" + def_bool y if ARCH_S5P6818 @@ -9664,20 +10323,23 @@ diff -ENwbur a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig + This is a new clocksource driver for the Nexell timer. + endmenu -diff -ENwbur a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile ---- a/drivers/clocksource/Makefile 2018-05-06 08:47:36.269301092 +0200 -+++ b/drivers/clocksource/Makefile 2018-05-06 08:49:49.082691523 +0200 -@@ -54,6 +54,7 @@ +diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/clocksource/Makefile ++++ b/drivers/clocksource/Makefile +@@ -54,6 +54,7 @@ obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o obj-$(CONFIG_OWL_TIMER) += owl-timer.o +obj-$(CONFIG_CLKSRC_NEXELL_TIMER) += s5pxx18_timer.o - + obj-$(CONFIG_ARC_TIMERS) += arc_timer.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o -diff -ENwbur a/drivers/clocksource/s5pxx18_timer.c b/drivers/clocksource/s5pxx18_timer.c ---- a/drivers/clocksource/s5pxx18_timer.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/clocksource/s5pxx18_timer.c 2018-05-06 08:49:49.082691523 +0200 +diff --git a/drivers/clocksource/s5pxx18_timer.c b/drivers/clocksource/s5pxx18_timer.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/clocksource/s5pxx18_timer.c @@ -0,0 +1,498 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -10177,12 +10839,13 @@ diff -ENwbur a/drivers/clocksource/s5pxx18_timer.c b/drivers/clocksource/s5pxx18 +} + +CLOCKSOURCE_OF_DECLARE(s5p6818, "nexell,s5p6818-timer", timer_of_init_dt); -diff -ENwbur a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm ---- a/drivers/cpufreq/Kconfig.arm 2018-05-06 08:47:36.273301254 +0200 -+++ b/drivers/cpufreq/Kconfig.arm 2018-05-06 08:49:49.086691685 +0200 -@@ -292,3 +292,45 @@ +diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm +index 111111111111..222222222222 100644 +--- a/drivers/cpufreq/Kconfig.arm ++++ b/drivers/cpufreq/Kconfig.arm +@@ -292,3 +292,45 @@ config ACPI_CPPC_CPUFREQ support for its operation. - + If in doubt, say N. + +config ARM_NEXELL_CPUFREQ @@ -10226,20 +10889,23 @@ diff -ENwbur a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm + default 1 if NEXELL_CPUFREQ_PLL_1 + default 2 if NEXELL_CPUFREQ_PLL_2 + default 3 if NEXELL_CPUFREQ_PLL_3 -diff -ENwbur a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile ---- a/drivers/cpufreq/Makefile 2018-05-06 08:47:36.273301254 +0200 -+++ b/drivers/cpufreq/Makefile 2018-05-06 08:49:49.086691685 +0200 -@@ -83,6 +83,7 @@ +diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/cpufreq/Makefile ++++ b/drivers/cpufreq/Makefile +@@ -83,6 +83,7 @@ obj-$(CONFIG_ARM_TI_CPUFREQ) += ti-cpufreq.o obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o +obj-$(CONFIG_ARM_NEXELL_CPUFREQ) += nexell-cpufreq.o - - + + ################################################################################## -diff -ENwbur a/drivers/cpufreq/nexell-cpufreq.c b/drivers/cpufreq/nexell-cpufreq.c ---- a/drivers/cpufreq/nexell-cpufreq.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/cpufreq/nexell-cpufreq.c 2018-05-06 08:49:49.090691848 +0200 +diff --git a/drivers/cpufreq/nexell-cpufreq.c b/drivers/cpufreq/nexell-cpufreq.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/cpufreq/nexell-cpufreq.c @@ -0,0 +1,902 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -11143,9 +11809,11 @@ diff -ENwbur a/drivers/cpufreq/nexell-cpufreq.c b/drivers/cpufreq/nexell-cpufreq + }, +}; +module_platform_driver(cpufreq_driver); -diff -ENwbur a/drivers/cpufreq/s5p6818-cpufreq.h b/drivers/cpufreq/s5p6818-cpufreq.h ---- a/drivers/cpufreq/s5p6818-cpufreq.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/cpufreq/s5p6818-cpufreq.h 2018-05-06 08:49:49.094692010 +0200 +diff --git a/drivers/cpufreq/s5p6818-cpufreq.h b/drivers/cpufreq/s5p6818-cpufreq.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/cpufreq/s5p6818-cpufreq.h @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -11449,9 +12117,38 @@ diff -ENwbur a/drivers/cpufreq/s5p6818-cpufreq.h b/drivers/cpufreq/s5p6818-cpufr + .get_vol_margin = s5p6818_asv_get_vol_margin, +}; +#endif -diff -ENwbur a/drivers/cpuidle/cpuidle-nexell.c b/drivers/cpuidle/cpuidle-nexell.c ---- a/drivers/cpuidle/cpuidle-nexell.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/cpuidle/cpuidle-nexell.c 2018-05-06 08:49:49.094692010 +0200 +diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm +index 111111111111..222222222222 100644 +--- a/drivers/cpuidle/Kconfig.arm ++++ b/drivers/cpuidle/Kconfig.arm +@@ -75,3 +75,10 @@ config ARM_MVEBU_V7_CPUIDLE + depends on ARCH_MVEBU && !ARM64 + help + Select this to enable cpuidle on Armada 370, 38x and XP processors. ++ ++config ARM_NEXELL_CPUIDLE ++ bool "Cpu Idle Driver for the nexell processors" ++ depends on ARCH_S5P4418 || ARCH_S5P6818 ++ select DT_IDLE_STATES ++ help ++ Select this to enable cpuidle for Nexell processors +diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/cpuidle/Makefile ++++ b/drivers/cpuidle/Makefile +@@ -19,6 +19,7 @@ obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o + obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o + obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o + obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o ++obj-$(CONFIG_ARM_NEXELL_CPUIDLE) += cpuidle-nexell.o + obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o + + ############################################################################### +diff --git a/drivers/cpuidle/cpuidle-nexell.c b/drivers/cpuidle/cpuidle-nexell.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/cpuidle/cpuidle-nexell.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -11558,38 +12255,14 @@ diff -ENwbur a/drivers/cpuidle/cpuidle-nexell.c b/drivers/cpuidle/cpuidle-nexell + return ret; +} +device_initcall(nexell_idle_init); -diff -ENwbur a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm ---- a/drivers/cpuidle/Kconfig.arm 2018-05-06 08:47:36.281301578 +0200 -+++ b/drivers/cpuidle/Kconfig.arm 2018-05-06 08:49:49.094692010 +0200 -@@ -75,3 +75,10 @@ - depends on ARCH_MVEBU && !ARM64 - help - Select this to enable cpuidle on Armada 370, 38x and XP processors. -+ -+config ARM_NEXELL_CPUIDLE -+ bool "Cpu Idle Driver for the nexell processors" -+ depends on ARCH_S5P4418 || ARCH_S5P6818 -+ select DT_IDLE_STATES -+ help -+ Select this to enable cpuidle for Nexell processors -diff -ENwbur a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile ---- a/drivers/cpuidle/Makefile 2018-05-06 08:47:36.281301578 +0200 -+++ b/drivers/cpuidle/Makefile 2018-05-06 08:49:49.094692010 +0200 -@@ -19,6 +19,7 @@ - obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o - obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o - obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o -+obj-$(CONFIG_ARM_NEXELL_CPUIDLE) += cpuidle-nexell.o - obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o - - ############################################################################### -diff -ENwbur a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig ---- a/drivers/devfreq/Kconfig 2018-05-06 08:47:36.309302715 +0200 -+++ b/drivers/devfreq/Kconfig 2018-05-06 08:49:49.122693147 +0200 -@@ -113,6 +113,14 @@ +diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/devfreq/Kconfig ++++ b/drivers/devfreq/Kconfig +@@ -114,6 +114,14 @@ config ARM_RK3399_DMC_DEVFREQ It sets the frequency for the memory controller and reads the usage counts from hardware. - + +config ARM_S5Pxx18_DEVFREQ + tristate "Nexell S5Pxx18 Bus DEVFREQ Driver" + depends on ARCH_S5P6818 @@ -11599,22 +12272,25 @@ diff -ENwbur a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig + This adds the DEVFREQ driver for Nexell S5Pxx18 Series SoC bus interface. + source "drivers/devfreq/event/Kconfig" - + endif # PM_DEVFREQ -diff -ENwbur a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile ---- a/drivers/devfreq/Makefile 2018-05-06 08:47:36.309302715 +0200 -+++ b/drivers/devfreq/Makefile 2018-05-06 08:49:49.122693147 +0200 -@@ -11,6 +11,7 @@ +diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/devfreq/Makefile ++++ b/drivers/devfreq/Makefile +@@ -11,6 +11,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra-devfreq.o +obj-$(CONFIG_ARM_S5Pxx18_DEVFREQ) += nx-devfreq.o - + # DEVFREQ Event Drivers obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/ -diff -ENwbur a/drivers/devfreq/nx-devfreq.c b/drivers/devfreq/nx-devfreq.c ---- a/drivers/devfreq/nx-devfreq.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/devfreq/nx-devfreq.c 2018-05-06 08:49:49.122693147 +0200 +diff --git a/drivers/devfreq/nx-devfreq.c b/drivers/devfreq/nx-devfreq.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/devfreq/nx-devfreq.c @@ -0,0 +1,592 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -12208,9 +12884,22 @@ diff -ENwbur a/drivers/devfreq/nx-devfreq.c b/drivers/devfreq/nx-devfreq.c +MODULE_AUTHOR("SungwooPark "); +MODULE_DESCRIPTION("Nexell S5Pxx18 series SoC devfreq driver"); +MODULE_LICENSE("GPL v2"); -diff -ENwbur a/drivers/gpu/arm/Kbuild b/drivers/gpu/arm/Kbuild ---- a/drivers/gpu/arm/Kbuild 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/Kbuild 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/gpu/Makefile ++++ b/drivers/gpu/Makefile +@@ -2,5 +2,5 @@ + # taken to initialize them in the correct order. Link order is the only way + # to ensure this currently. + obj-$(CONFIG_TEGRA_HOST1X) += host1x/ +-obj-y += drm/ vga/ ++obj-y += drm/ vga/ arm/ + obj-$(CONFIG_IMX_IPUV3_CORE) += ipu-v3/ +diff --git a/drivers/gpu/arm/Kbuild b/drivers/gpu/arm/Kbuild +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/Kbuild @@ -0,0 +1,13 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. @@ -12225,9 +12914,11 @@ diff -ENwbur a/drivers/gpu/arm/Kbuild b/drivers/gpu/arm/Kbuild + + +obj-$(CONFIG_MALI400) += mali400/ -diff -ENwbur a/drivers/gpu/arm/Kconfig b/drivers/gpu/arm/Kconfig ---- a/drivers/gpu/arm/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/Kconfig 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/Kconfig b/drivers/gpu/arm/Kconfig +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/Kconfig @@ -0,0 +1,15 @@ +# +# (C) COPYRIGHT 2012 ARM Limited. All rights reserved. @@ -12244,9 +12935,655 @@ diff -ENwbur a/drivers/gpu/arm/Kconfig b/drivers/gpu/arm/Kconfig +menu "ARM GPU Configuration" +source "drivers/gpu/arm/mali400/Kconfig" +endmenu -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_broadcast.c b/drivers/gpu/arm/mali400/common/mali_broadcast.c ---- a/drivers/gpu/arm/mali400/common/mali_broadcast.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_broadcast.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/.gitignore b/drivers/gpu/arm/mali400/.gitignore +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/.gitignore +@@ -0,0 +1 @@ ++__malidrv_build_info.c +diff --git a/drivers/gpu/arm/mali400/Kbuild b/drivers/gpu/arm/mali400/Kbuild +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/Kbuild +@@ -0,0 +1,261 @@ ++# ++# Copyright (C) 2010-2011 ARM Limited. All rights reserved. ++# ++# 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. ++# ++ ++# This file is called by the Linux build system. ++ ++# set up defaults if not defined by the user ++TIMESTAMP ?= default ++OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 ++USING_GPU_UTILIZATION ?= 0 ++PROFILING_SKIP_PP_JOBS ?= 0 ++PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 ++MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0 ++MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0 ++MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0 ++MALI_UPPER_HALF_SCHEDULING ?= 1 ++MALI_ENABLE_CPU_CYCLES ?= 0 ++ ++# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: ++# The ARM proprietary product will only include the license/proprietary directory ++# The GPL product will only include the license/gpl directory ++ifeq ($(wildcard $(src)/linux/license/gpl/*),) ++ ccflags-y += -I$(src)/linux/license/proprietary ++ ifeq ($(CONFIG_MALI400_PROFILING),y) ++ $(error Profiling is incompatible with non-GPL license) ++ endif ++ ifeq ($(CONFIG_PM_RUNTIME),y) ++ $(error Runtime PM is incompatible with non-GPL license) ++ endif ++ ifeq ($(CONFIG_DMA_SHARED_BUFFER),y) ++ $(error DMA-BUF is incompatible with non-GPL license) ++ endif ++ $(error Linux Device integration is incompatible with non-GPL license) ++else ++ ccflags-y += -I$(src)/linux/license/gpl ++endif ++ ++ifeq ($(USING_GPU_UTILIZATION), 1) ++ ifeq ($(USING_DVFS), 1) ++ $(error USING_GPU_UTILIZATION conflict with USING_DVFS you can read the Integration Guide to choose which one do you need) ++ endif ++endif ++ ++ifeq ($(CONFIG_MALI_PLATFORM_S5P4418),y) ++export MALI_PLATFORM=nexell ++endif ++ ++ifeq ($(CONFIG_MALI_PLATFORM_S5P6818),y) ++export MALI_PLATFORM=nexell ++endif ++ ++ifeq ($(CONFIG_ARCH_EXYNOS4),y) ++export MALI_PLATFORM=exynos4 ++endif ++ ++ifeq ($(MALI_PLATFORM_FILES),) ++EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1 ++export MALI_PLATFORM_FILES_BUILDIN = $(notdir $(wildcard $(src)/platform/$(MALI_PLATFORM)/*.c)) ++export MALI_PLATFORM_FILES_ADD_PREFIX = $(addprefix platform/$(MALI_PLATFORM)/,$(MALI_PLATFORM_FILES_BUILDIN)) ++endif ++ ++mali-y += \ ++ linux/mali_osk_atomics.o \ ++ linux/mali_osk_irq.o \ ++ linux/mali_osk_wq.o \ ++ linux/mali_osk_locks.o \ ++ linux/mali_osk_wait_queue.o \ ++ linux/mali_osk_low_level_mem.o \ ++ linux/mali_osk_math.o \ ++ linux/mali_osk_memory.o \ ++ linux/mali_osk_misc.o \ ++ linux/mali_osk_mali.o \ ++ linux/mali_osk_notification.o \ ++ linux/mali_osk_time.o \ ++ linux/mali_osk_timers.o \ ++ linux/mali_osk_bitmap.o ++ ++mali-y += linux/mali_memory.o linux/mali_memory_os_alloc.o ++mali-y += linux/mali_memory_external.o ++mali-y += linux/mali_memory_block_alloc.o ++mali-y += linux/mali_memory_swap_alloc.o ++ ++mali-y += \ ++ linux/mali_memory_manager.o \ ++ linux/mali_memory_virtual.o \ ++ linux/mali_memory_util.o \ ++ linux/mali_memory_cow.o \ ++ linux/mali_memory_defer_bind.o ++ ++mali-y += \ ++ linux/mali_ukk_mem.o \ ++ linux/mali_ukk_gp.o \ ++ linux/mali_ukk_pp.o \ ++ linux/mali_ukk_core.o \ ++ linux/mali_ukk_soft_job.o \ ++ linux/mali_ukk_timeline.o ++ ++mali-$(CONFIG_MALI_DEVFREQ) += \ ++ linux/mali_devfreq.o \ ++ common/mali_pm_metrics.o ++ ++# Source files which always are included in a build ++mali-y += \ ++ common/mali_kernel_core.o \ ++ linux/mali_kernel_linux.o \ ++ common/mali_session.o \ ++ linux/mali_device_pause_resume.o \ ++ common/mali_kernel_vsync.o \ ++ linux/mali_ukk_vsync.o \ ++ linux/mali_kernel_sysfs.o \ ++ common/mali_mmu.o \ ++ common/mali_mmu_page_directory.o \ ++ common/mali_mem_validation.o \ ++ common/mali_hw_core.o \ ++ common/mali_gp.o \ ++ common/mali_pp.o \ ++ common/mali_pp_job.o \ ++ common/mali_gp_job.o \ ++ common/mali_soft_job.o \ ++ common/mali_scheduler.o \ ++ common/mali_executor.o \ ++ common/mali_group.o \ ++ common/mali_dlbu.o \ ++ common/mali_broadcast.o \ ++ common/mali_pm.o \ ++ common/mali_pmu.o \ ++ common/mali_user_settings_db.o \ ++ common/mali_kernel_utilization.o \ ++ common/mali_control_timer.o \ ++ common/mali_l2_cache.o \ ++ common/mali_timeline.o \ ++ common/mali_timeline_fence_wait.o \ ++ common/mali_timeline_sync_fence.o \ ++ common/mali_spinlock_reentrant.o \ ++ common/mali_pm_domain.o \ ++ linux/mali_osk_pm.o \ ++ linux/mali_pmu_power_up_down.o \ ++ __malidrv_build_info.o ++ ++ifneq ($(wildcard $(src)/linux/mali_slp_global_lock.c),) ++ mali-y += linux/mali_slp_global_lock.o ++endif ++ ++ifneq ($(MALI_PLATFORM_FILES),) ++ mali-y += $(MALI_PLATFORM_FILES:.c=.o) ++endif ++ ++ifneq ($(MALI_PLATFORM_FILES_ADD_PREFIX),) ++ mali-y += $(MALI_PLATFORM_FILES_ADD_PREFIX:.c=.o) ++endif ++ ++mali-$(CONFIG_MALI400_PROFILING) += linux/mali_ukk_profiling.o ++mali-$(CONFIG_MALI400_PROFILING) += linux/mali_osk_profiling.o ++ ++mali-$(CONFIG_MALI400_INTERNAL_PROFILING) += linux/mali_profiling_internal.o timestamp-$(TIMESTAMP)/mali_timestamp.o ++ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(src)/timestamp-$(TIMESTAMP) ++ ++mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_memory_dma_buf.o ++mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_memory_secure.o ++mali-$(CONFIG_SYNC) += linux/mali_sync.o ++mali-$(CONFIG_MALI_DMA_BUF_FENCE) += linux/mali_dma_fence.o ++ccflags-$(CONFIG_SYNC) += -Idrivers/staging/android ++ ++mali-$(CONFIG_MALI400_UMP) += linux/mali_memory_ump.o ++ ++mali-$(CONFIG_MALI_DVFS) += common/mali_dvfs_policy.o ++ ++# Tell the Linux build system from which .o file to create the kernel module ++obj-$(CONFIG_MALI400) := mali.o ++ ++ccflags-y += $(EXTRA_DEFINES) ++ ++# Set up our defines, which will be passed to gcc ++ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) ++ccflags-y += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) ++ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) ++ccflags-y += -DMALI_STATE_TRACKING=1 ++ccflags-y += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) ++ccflags-y += -DUSING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) ++ccflags-y += -DMALI_ENABLE_CPU_CYCLES=$(MALI_ENABLE_CPU_CYCLES) ++ ++ifeq ($(MALI_UPPER_HALF_SCHEDULING),1) ++ ccflags-y += -DMALI_UPPER_HALF_SCHEDULING ++endif ++ ++#build-in include path is different ++ifeq ($(MALI_PLATFORM_FILES),) ++ccflags-$(CONFIG_MALI400_UMP) += -I$(src)/../ump/include/ ++else ++ccflags-$(CONFIG_MALI400_UMP) += -I$(src)/../../ump/include/ump ++endif ++ccflags-$(CONFIG_MALI400_DEBUG) += -DDEBUG ++ ++# Use our defines when compiling ++ccflags-y += -I$(src) -I$(src)/include -I$(src)/common -I$(src)/linux -I$(src)/platform -Wno-date-time ++ ++# Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available ++MALI_RELEASE_NAME=$(shell cat $(src)/.version 2> /dev/null) ++ ++SVN_INFO = (cd $(src); svn info 2>/dev/null) ++ ++ifneq ($(shell $(SVN_INFO) 2>/dev/null),) ++# SVN detected ++SVN_REV := $(shell $(SVN_INFO) | grep '^Revision: '| sed -e 's/^Revision: //' 2>/dev/null) ++DRIVER_REV := $(MALI_RELEASE_NAME)-r$(SVN_REV) ++CHANGE_DATE := $(shell $(SVN_INFO) | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-) ++CHANGED_REVISION := $(shell $(SVN_INFO) | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-) ++REPO_URL := $(shell $(SVN_INFO) | grep '^URL: ' | cut -d: -f2- | cut -b2-) ++ ++else # SVN ++GIT_REV := $(shell cd $(src); git describe --always 2>/dev/null) ++ifneq ($(GIT_REV),) ++# Git detected ++DRIVER_REV := $(MALI_RELEASE_NAME)-$(GIT_REV) ++CHANGE_DATE := $(shell cd $(src); git log -1 --format="%ci") ++CHANGED_REVISION := $(GIT_REV) ++REPO_URL := $(shell cd $(src); git describe --all --always 2>/dev/null) ++ ++else # Git ++# No Git or SVN detected ++DRIVER_REV := $(MALI_RELEASE_NAME) ++CHANGE_DATE := $(MALI_RELEASE_NAME) ++CHANGED_REVISION := $(MALI_RELEASE_NAME) ++endif ++endif ++ ++ccflags-y += -DSVN_REV_STRING=\"$(DRIVER_REV)\" ++ ++VERSION_STRINGS := ++VERSION_STRINGS += API_VERSION=$(shell cd $(src); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) ++VERSION_STRINGS += REPO_URL=$(REPO_URL) ++VERSION_STRINGS += REVISION=$(DRIVER_REV) ++VERSION_STRINGS += CHANGED_REVISION=$(CHANGED_REVISION) ++VERSION_STRINGS += CHANGE_DATE=$(CHANGE_DATE) ++VERSION_STRINGS += BUILD_DATE=$(shell date) ++ifdef CONFIG_MALI400_DEBUG ++VERSION_STRINGS += BUILD=debug ++else ++VERSION_STRINGS += BUILD=release ++endif ++VERSION_STRINGS += TARGET_PLATFORM=$(TARGET_PLATFORM) ++VERSION_STRINGS += MALI_PLATFORM=$(MALI_PLATFORM) ++VERSION_STRINGS += KDIR=$(KDIR) ++VERSION_STRINGS += OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) ++VERSION_STRINGS += USING_UMP=$(CONFIG_MALI400_UMP) ++VERSION_STRINGS += USING_PROFILING=$(CONFIG_MALI400_PROFILING) ++VERSION_STRINGS += USING_INTERNAL_PROFILING=$(CONFIG_MALI400_INTERNAL_PROFILING) ++VERSION_STRINGS += USING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) ++VERSION_STRINGS += USING_DVFS=$(CONFIG_MALI_DVFS) ++VERSION_STRINGS += USING_DMA_BUF_FENCE = $(CONFIG_MALI_DMA_BUF_FENCE) ++VERSION_STRINGS += MALI_UPPER_HALF_SCHEDULING=$(MALI_UPPER_HALF_SCHEDULING) ++ ++# Create file with Mali driver configuration ++$(src)/__malidrv_build_info.c: ++ @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(src)/__malidrv_build_info.c +diff --git a/drivers/gpu/arm/mali400/Kconfig b/drivers/gpu/arm/mali400/Kconfig +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/Kconfig +@@ -0,0 +1,152 @@ ++config MALI400 ++ tristate "Mali-300/400/450 support" ++ depends on ARM || ARM64 ++ select DMA_SHARED_BUFFER ++ ---help--- ++ This enables support for the ARM Mali-300, Mali-400, and Mali-450 ++ GPUs. ++ ++ To compile this driver as a module, choose M here: the module will be ++ called mali. ++ ++config MALI450 ++ bool "Enable Mali-450 support" ++ depends on MALI400 ++ ---help--- ++ This enables support for Mali-450 specific features. ++ ++config MALI470 ++ bool "Enable Mali-470 support" ++ depends on MALI400 ++ ---help--- ++ This enables support for Mali-470 specific features. ++ ++config MALI400_DEBUG ++ bool "Enable debug in Mali driver" ++ depends on MALI400 ++ ---help--- ++ This enabled extra debug checks and messages in the Mali driver. ++ ++choice ++ prompt "Platform configuration" ++ depends on (MALI400 || MALI450 || MALI470) ++ default MALI_PLATFORM_S5P6818 if ARM64 ++ default MALI_PLATFORM_S5P4418 if ARM ++ help ++ Select the SOC platform that contains a Mali utgard GPU ++ ++config MALI_PLATFORM_S5P4418 ++ depends on ARCH_S5P4418 ++ bool "Nexell S5P4418" ++ select MALI_SHARED_INTERRUPTS ++ select MALI_DT ++ help ++ Select S5P4418 SoC configuration ++ ++config MALI_PLATFORM_S5P6818 ++ depends on ARCH_S5P6818 ++ bool "Nexell S5P6818" ++ select MALI_SHARED_INTERRUPTS ++ select MALI_DT ++ help ++ Select S5P6818 SoC configuration ++endchoice ++ ++config MALI400_PROFILING ++ bool "Enable Mali profiling" ++ depends on MALI400 ++ select TRACEPOINTS ++ default y ++ ---help--- ++ This enables gator profiling of Mali GPU events. ++ ++config MALI400_INTERNAL_PROFILING ++ bool "Enable internal Mali profiling API" ++ depends on MALI400_PROFILING ++ default n ++ ---help--- ++ This enables the internal legacy Mali profiling API. ++ ++config MALI400_UMP ++ bool "Enable UMP support" ++ depends on MALI400 ++ ---help--- ++ This enables support for the UMP memory sharing API in the Mali driver. ++ ++config MALI_DVFS ++ bool "Enable Mali dynamically frequency change" ++ depends on MALI400 && !MALI_DEVFREQ ++ default y ++ ---help--- ++ This enables support for dynamic change frequency of Mali with the goal of lowering power consumption. ++ ++config MALI_DMA_BUF_MAP_ON_ATTACH ++ bool "Map dma-buf attachments on attach" ++ depends on MALI400 && DMA_SHARED_BUFFER ++ default y ++ ---help--- ++ This makes the Mali driver map dma-buf attachments after doing ++ attach. If this is not set the dma-buf attachments will be mapped for ++ every time the GPU need to access the buffer. ++ ++ Mapping for each access can cause lower performance. ++ ++config MALI_SHARED_INTERRUPTS ++ bool "Support for shared interrupts" ++ depends on MALI400 ++ default n ++ ---help--- ++ Adds functionality required to properly support shared interrupts. Without this support, ++ the device driver will fail during insmod if it detects shared interrupts. This also ++ works when the GPU is not using shared interrupts, but might have a slight performance ++ impact. ++ ++config MALI_PMU_PARALLEL_POWER_UP ++ bool "Power up Mali PMU domains in parallel" ++ depends on MALI400 ++ default n ++ ---help--- ++ This makes the Mali driver power up all PMU power domains in parallel, instead of ++ powering up domains one by one, with a slight delay in between. Powering on all power ++ domains at the same time may cause peak currents higher than what some systems can handle. ++ These systems must not enable this option. ++ ++config MALI_DT ++ bool "Using device tree to initialize module" ++ depends on MALI400 && OF ++ default n ++ ---help--- ++ This enable the Mali driver to choose the device tree path to get platform resoures ++ and disable the old config method. Mali driver could run on the platform which the ++ device tree is enabled in kernel and corresponding hardware description is implemented ++ properly in device DTS file. ++ ++config MALI_DEVFREQ ++ bool "Using devfreq to tuning frequency" ++ depends on MALI400 && PM_DEVFREQ ++ default n ++ ---help--- ++ Support devfreq for Mali. ++ ++ Using the devfreq framework and, by default, the simpleondemand ++ governor, the frequency of Mali will be dynamically selected from the ++ available OPPs. ++ ++config MALI_QUIET ++ bool "Make Mali driver very quiet" ++ depends on MALI400 && !MALI400_DEBUG ++ default n ++ ---help--- ++ This forces the Mali driver to never print any messages. ++ ++ If unsure, say N. ++ ++config MALI_DMA_BUF_FENCE ++ bool "Make DMA BUF Fence" ++ depends on MALI400 ++ default n ++ ---help--- ++ Choose this option if you want to use fences and reservations for ++ synchronization of shared dma-buf access between different drivers. ++ ++ If unsure, say N. +diff --git a/drivers/gpu/arm/mali400/Makefile b/drivers/gpu/arm/mali400/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/Makefile +@@ -0,0 +1,206 @@ ++# ++# Copyright (C) 2010-2016 ARM Limited. All rights reserved. ++# ++# 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. ++# ++ ++USE_UMPV2=0 ++USING_PROFILING ?= 1 ++USING_INTERNAL_PROFILING ?= 0 ++USING_DVFS ?= 1 ++USING_DMA_BUF_FENCE ?= 0 ++MALI_HEATMAPS_ENABLED ?= 0 ++MALI_DMA_BUF_MAP_ON_ATTACH ?= 1 ++MALI_PMU_PARALLEL_POWER_UP ?= 0 ++USING_DT ?= 0 ++MALI_MEM_SWAP_TRACKING ?= 0 ++USING_DEVFREQ ?= 0 ++ ++# The Makefile sets up "arch" based on the CONFIG, creates the version info ++# string and the __malidrv_build_info.c file, and then call the Linux build ++# system to actually build the driver. After that point the Kbuild file takes ++# over. ++ ++# set up defaults if not defined by the user ++ARCH ?= arm ++ ++OSKOS=linux ++FILES_PREFIX= ++ ++check_cc2 = \ ++ $(shell if $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \ ++ then \ ++ echo "$(2)"; \ ++ else \ ++ echo "$(3)"; \ ++ fi ;) ++ ++# This conditional makefile exports the global definition ARM_INTERNAL_BUILD. Customer releases will not include arm_internal.mak ++-include ../../../arm_internal.mak ++ ++# Give warning of old config parameters are used ++ifneq ($(CONFIG),) ++$(warning "You have specified the CONFIG variable which is no longer in used. Use TARGET_PLATFORM instead.") ++endif ++ ++ifneq ($(CPU),) ++$(warning "You have specified the CPU variable which is no longer in used. Use TARGET_PLATFORM instead.") ++endif ++ ++# Include the mapping between TARGET_PLATFORM and KDIR + MALI_PLATFORM ++-include MALI_CONFIGURATION ++export KDIR ?= $(KDIR-$(TARGET_PLATFORM)) ++export MALI_PLATFORM ?= $(MALI_PLATFORM-$(TARGET_PLATFORM)) ++ ++ifneq ($(TARGET_PLATFORM),) ++ifeq ($(MALI_PLATFORM),) ++$(error "Invalid TARGET_PLATFORM: $(TARGET_PLATFORM)") ++endif ++endif ++ ++# validate lookup result ++ifeq ($(KDIR),) ++$(error No KDIR found for platform $(TARGET_PLATFORM)) ++endif ++ ++ifeq ($(USING_GPU_UTILIZATION), 1) ++ ifeq ($(USING_DVFS), 1) ++ $(error USING_GPU_UTILIZATION conflict with USING_DVFS you can read the Integration Guide to choose which one do you need) ++ endif ++endif ++ ++ifeq ($(USING_UMP),1) ++export CONFIG_MALI400_UMP=y ++export EXTRA_DEFINES += -DCONFIG_MALI400_UMP=1 ++ifeq ($(USE_UMPV2),1) ++UMP_SYMVERS_FILE ?= ../umpv2/Module.symvers ++else ++UMP_SYMVERS_FILE ?= ../ump/Module.symvers ++endif ++KBUILD_EXTRA_SYMBOLS = $(realpath $(UMP_SYMVERS_FILE)) ++$(warning $(KBUILD_EXTRA_SYMBOLS)) ++endif ++ ++# Define host system directory ++KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build ++ ++include $(KDIR)/.config ++ ++ifeq ($(ARCH), arm) ++# when compiling for ARM we're cross compiling ++export CROSS_COMPILE ?= $(call check_cc2, arm-linux-gnueabi-gcc, arm-linux-gnueabi-, arm-none-linux-gnueabi-) ++endif ++ ++# report detected/selected settings ++ifdef ARM_INTERNAL_BUILD ++$(warning TARGET_PLATFORM $(TARGET_PLATFORM)) ++$(warning KDIR $(KDIR)) ++$(warning MALI_PLATFORM $(MALI_PLATFORM)) ++endif ++ ++# Set up build config ++export CONFIG_MALI400=m ++export CONFIG_MALI450=y ++export CONFIG_MALI470=y ++ ++export EXTRA_DEFINES += -DCONFIG_MALI400=1 ++export EXTRA_DEFINES += -DCONFIG_MALI450=1 ++export EXTRA_DEFINES += -DCONFIG_MALI470=1 ++ ++ifneq ($(MALI_PLATFORM),) ++export EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1 ++export MALI_PLATFORM_FILES = $(wildcard platform/$(MALI_PLATFORM)/*.c) ++endif ++ ++ifeq ($(USING_PROFILING),1) ++ifeq ($(CONFIG_TRACEPOINTS),) ++$(warning CONFIG_TRACEPOINTS required for profiling) ++else ++export CONFIG_MALI400_PROFILING=y ++export EXTRA_DEFINES += -DCONFIG_MALI400_PROFILING=1 ++ifeq ($(USING_INTERNAL_PROFILING),1) ++export CONFIG_MALI400_INTERNAL_PROFILING=y ++export EXTRA_DEFINES += -DCONFIG_MALI400_INTERNAL_PROFILING=1 ++endif ++ifeq ($(MALI_HEATMAPS_ENABLED),1) ++export MALI_HEATMAPS_ENABLED=y ++export EXTRA_DEFINES += -DCONFIG_MALI400_HEATMAPS_ENABLED ++endif ++endif ++endif ++ ++ifeq ($(MALI_DMA_BUF_MAP_ON_ATTACH),1) ++export CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH=y ++export EXTRA_DEFINES += -DCONFIG_MALI_DMA_BUF_MAP_ON_ATTACH ++endif ++ ++ifeq ($(MALI_SHARED_INTERRUPTS),1) ++export CONFIG_MALI_SHARED_INTERRUPTS=y ++export EXTRA_DEFINES += -DCONFIG_MALI_SHARED_INTERRUPTS ++endif ++ ++ifeq ($(USING_DVFS),1) ++export CONFIG_MALI_DVFS=y ++export EXTRA_DEFINES += -DCONFIG_MALI_DVFS ++endif ++ ++ifeq ($(USING_DMA_BUF_FENCE),1) ++export CONFIG_MALI_DMA_BUF_FENCE=y ++export EXTRA_DEFINES += -DCONFIG_MALI_DMA_BUF_FENCE ++endif ++ ++ifeq ($(MALI_PMU_PARALLEL_POWER_UP),1) ++export CONFIG_MALI_PMU_PARALLEL_POWER_UP=y ++export EXTRA_DEFINES += -DCONFIG_MALI_PMU_PARALLEL_POWER_UP ++endif ++ ++ifdef CONFIG_OF ++ifeq ($(USING_DT),1) ++export CONFIG_MALI_DT=y ++export EXTRA_DEFINES += -DCONFIG_MALI_DT ++endif ++endif ++ ++ifeq ($(USING_DEVFREQ), 1) ++ifdef CONFIG_PM_DEVFREQ ++export CONFIG_MALI_DEVFREQ=y ++export EXTRA_DEFINES += -DCONFIG_MALI_DEVFREQ=1 ++else ++$(warning "You want to support DEVFREQ but kernel didn't support DEVFREQ.") ++endif ++endif ++ ++ifneq ($(BUILD),release) ++# Debug ++export CONFIG_MALI400_DEBUG=y ++else ++# Release ++ifeq ($(MALI_QUIET),1) ++export CONFIG_MALI_QUIET=y ++export EXTRA_DEFINES += -DCONFIG_MALI_QUIET ++endif ++endif ++ ++ifeq ($(MALI_SKIP_JOBS),1) ++EXTRA_DEFINES += -DPROFILING_SKIP_PP_JOBS=1 -DPROFILING_SKIP_GP_JOBS=1 ++endif ++ ++ifeq ($(MALI_MEM_SWAP_TRACKING),1) ++EXTRA_DEFINES += -DMALI_MEM_SWAP_TRACKING=1 ++endif ++ ++all: $(UMP_SYMVERS_FILE) ++ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) modules ++ @rm $(FILES_PREFIX)__malidrv_build_info.c $(FILES_PREFIX)__malidrv_build_info.o ++ ++clean: ++ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean ++ ++kernelrelease: ++ $(MAKE) ARCH=$(ARCH) -C $(KDIR) kernelrelease ++ ++export CONFIG KBUILD_EXTRA_SYMBOLS +diff --git a/drivers/gpu/arm/mali400/common/mali_broadcast.c b/drivers/gpu/arm/mali400/common/mali_broadcast.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_broadcast.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2012-2014, 2016 ARM Limited. All rights reserved. @@ -12390,9 +13727,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_broadcast.c b/drivers/gpu/arm + MALI_BROADCAST_REG_INTERRUPT_MASK, + 0x0); +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_broadcast.h b/drivers/gpu/arm/mali400/common/mali_broadcast.h ---- a/drivers/gpu/arm/mali400/common/mali_broadcast.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_broadcast.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_broadcast.h b/drivers/gpu/arm/mali400/common/mali_broadcast.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_broadcast.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2012-2014, 2016 ARM Limited. All rights reserved. @@ -12410,7 +13749,7 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_broadcast.h b/drivers/gpu/arm +/* + * Interface for the broadcast unit on Mali-450. + * -+ * - Represents up to 8 × (MMU + PP) pairs. ++ * - Represents up to 8 × (MMU + PP) pairs. + * - Supports dynamically changing which (MMU + PP) pairs receive the broadcast by + * setting a mask. + */ @@ -12451,9 +13790,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_broadcast.h b/drivers/gpu/arm +} + +#endif /* __MALI_BROADCAST_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_control_timer.c b/drivers/gpu/arm/mali400/common/mali_control_timer.c ---- a/drivers/gpu/arm/mali400/common/mali_control_timer.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_control_timer.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_control_timer.c b/drivers/gpu/arm/mali400/common/mali_control_timer.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_control_timer.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2010-2012, 2014-2016 ARM Limited. All rights reserved. @@ -12583,9 +13924,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_control_timer.c b/drivers/gpu + mali_utilization_data_unlock(); + } +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_control_timer.h b/drivers/gpu/arm/mali400/common/mali_control_timer.h ---- a/drivers/gpu/arm/mali400/common/mali_control_timer.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_control_timer.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_control_timer.h b/drivers/gpu/arm/mali400/common/mali_control_timer.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_control_timer.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2010-2012, 2014, 2016 ARM Limited. All rights reserved. @@ -12615,9 +13958,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_control_timer.h b/drivers/gpu + +#endif /* __MALI_CONTROL_TIMER_H__ */ + -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_dlbu.c b/drivers/gpu/arm/mali400/common/mali_dlbu.c ---- a/drivers/gpu/arm/mali400/common/mali_dlbu.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_dlbu.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_dlbu.c b/drivers/gpu/arm/mali400/common/mali_dlbu.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_dlbu.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2012-2014, 2016 ARM Limited. All rights reserved. @@ -12832,9 +14177,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_dlbu.c b/drivers/gpu/arm/mali + mali_hw_core_register_write_array_relaxed(&dlbu->hw_core, MALI_DLBU_REGISTER_TLLIST_VBASEADDR, registers, 4); + +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_dlbu.h b/drivers/gpu/arm/mali400/common/mali_dlbu.h ---- a/drivers/gpu/arm/mali400/common/mali_dlbu.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_dlbu.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_dlbu.h b/drivers/gpu/arm/mali400/common/mali_dlbu.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_dlbu.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2012-2014, 2016 ARM Limited. All rights reserved. @@ -12881,9 +14228,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_dlbu.h b/drivers/gpu/arm/mali +void mali_dlbu_config_job(struct mali_dlbu_core *dlbu, struct mali_pp_job *job); + +#endif /* __MALI_DLBU_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_dvfs_policy.c b/drivers/gpu/arm/mali400/common/mali_dvfs_policy.c ---- a/drivers/gpu/arm/mali400/common/mali_dvfs_policy.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_dvfs_policy.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_dvfs_policy.c b/drivers/gpu/arm/mali400/common/mali_dvfs_policy.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_dvfs_policy.c @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2010-2012, 2014, 2016 ARM Limited. All rights reserved. @@ -13197,9 +14546,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_dvfs_policy.c b/drivers/gpu/a +} +#endif + -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_dvfs_policy.h b/drivers/gpu/arm/mali400/common/mali_dvfs_policy.h ---- a/drivers/gpu/arm/mali400/common/mali_dvfs_policy.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_dvfs_policy.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_dvfs_policy.h b/drivers/gpu/arm/mali400/common/mali_dvfs_policy.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_dvfs_policy.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010-2012, 2014, 2016 ARM Limited. All rights reserved. @@ -13235,9 +14586,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_dvfs_policy.h b/drivers/gpu/a +#endif + +#endif/* __MALI_DVFS_POLICY_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_executor.c b/drivers/gpu/arm/mali400/common/mali_executor.c ---- a/drivers/gpu/arm/mali400/common/mali_executor.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_executor.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_executor.c b/drivers/gpu/arm/mali400/common/mali_executor.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_executor.c @@ -0,0 +1,2693 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -15932,9 +17285,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_executor.c b/drivers/gpu/arm/ + mali_scheduler_unlock(); + mali_executor_unlock(); +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_executor.h b/drivers/gpu/arm/mali400/common/mali_executor.h ---- a/drivers/gpu/arm/mali400/common/mali_executor.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_executor.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_executor.h b/drivers/gpu/arm/mali400/common/mali_executor.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_executor.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2012, 2014-2016 ARM Limited. All rights reserved. @@ -16038,9 +17393,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_executor.h b/drivers/gpu/arm/ +void mali_executor_lock(void); +void mali_executor_unlock(void); +#endif /* __MALI_EXECUTOR_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_gp.c b/drivers/gpu/arm/mali400/common/mali_gp.c ---- a/drivers/gpu/arm/mali400/common/mali_gp.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_gp.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_gp.c b/drivers/gpu/arm/mali400/common/mali_gp.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_gp.c @@ -0,0 +1,357 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -16399,9 +17756,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_gp.c b/drivers/gpu/arm/mali40 +#endif + } +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_gp.h b/drivers/gpu/arm/mali400/common/mali_gp.h ---- a/drivers/gpu/arm/mali400/common/mali_gp.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_gp.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_gp.h b/drivers/gpu/arm/mali400/common/mali_gp.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_gp.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2011-2014, 2016 ARM Limited. All rights reserved. @@ -16530,9 +17889,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_gp.h b/drivers/gpu/arm/mali40 +} + +#endif /* __MALI_GP_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_gp_job.c b/drivers/gpu/arm/mali400/common/mali_gp_job.c ---- a/drivers/gpu/arm/mali400/common/mali_gp_job.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_gp_job.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_gp_job.c b/drivers/gpu/arm/mali400/common/mali_gp_job.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_gp_job.c @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -16836,9 +18197,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_gp_job.c b/drivers/gpu/arm/ma + + return schedule_mask; +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_gp_job.h b/drivers/gpu/arm/mali400/common/mali_gp_job.h ---- a/drivers/gpu/arm/mali400/common/mali_gp_job.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_gp_job.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_gp_job.h b/drivers/gpu/arm/mali400/common/mali_gp_job.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_gp_job.h @@ -0,0 +1,324 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -17164,9 +18527,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_gp_job.h b/drivers/gpu/arm/ma +mali_scheduler_mask mali_gp_job_signal_pp_tracker(struct mali_gp_job *job, mali_bool success); + +#endif /* __MALI_GP_JOB_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_group.c b/drivers/gpu/arm/mali400/common/mali_group.c ---- a/drivers/gpu/arm/mali400/common/mali_group.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_group.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_group.c b/drivers/gpu/arm/mali400/common/mali_group.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_group.c @@ -0,0 +1,1865 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -19033,9 +20398,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_group.c b/drivers/gpu/arm/mal + _mali_osk_profiling_add_event(profiling_channel, source1 << 8 | source0, value0, value1, 0, 0); +} +#endif /* #if defined(CONFIG_MALI400_PROFILING) */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_group.h b/drivers/gpu/arm/mali400/common/mali_group.h ---- a/drivers/gpu/arm/mali400/common/mali_group.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_group.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_group.h b/drivers/gpu/arm/mali400/common/mali_group.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_group.h @@ -0,0 +1,460 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -19497,9 +20864,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_group.h b/drivers/gpu/arm/mal +} + +#endif /* __MALI_GROUP_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_hw_core.c b/drivers/gpu/arm/mali400/common/mali_hw_core.c ---- a/drivers/gpu/arm/mali400/common/mali_hw_core.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_hw_core.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_hw_core.c b/drivers/gpu/arm/mali400/common/mali_hw_core.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_hw_core.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011-2014, 2016 ARM Limited. All rights reserved. @@ -19548,9 +20917,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_hw_core.c b/drivers/gpu/arm/m + } + _mali_osk_mem_unreqregion(core->phys_addr, core->size); +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_hw_core.h b/drivers/gpu/arm/mali400/common/mali_hw_core.h ---- a/drivers/gpu/arm/mali400/common/mali_hw_core.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_hw_core.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_hw_core.h b/drivers/gpu/arm/mali400/common/mali_hw_core.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_hw_core.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -19701,9 +21072,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_hw_core.h b/drivers/gpu/arm/m +} + +#endif /* __MALI_HW_CORE_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_common.h b/drivers/gpu/arm/mali400/common/mali_kernel_common.h ---- a/drivers/gpu/arm/mali400/common/mali_kernel_common.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_kernel_common.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_kernel_common.h b/drivers/gpu/arm/mali400/common/mali_kernel_common.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_kernel_common.h @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2010, 2012-2014, 2016 ARM Limited. All rights reserved. @@ -19886,9 +21259,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_common.h b/drivers/gpu +#endif + +#endif /* __MALI_KERNEL_COMMON_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_core.c b/drivers/gpu/arm/mali400/common/mali_kernel_core.c ---- a/drivers/gpu/arm/mali400/common/mali_kernel_core.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_kernel_core.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_kernel_core.c b/drivers/gpu/arm/mali400/common/mali_kernel_core.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_kernel_core.c @@ -0,0 +1,1339 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -21229,9 +22604,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_core.c b/drivers/gpu/a + return n; +} +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_core.h b/drivers/gpu/arm/mali400/common/mali_kernel_core.h ---- a/drivers/gpu/arm/mali400/common/mali_kernel_core.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_kernel_core.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_kernel_core.h b/drivers/gpu/arm/mali400/common/mali_kernel_core.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_kernel_core.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -21290,9 +22667,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_core.h b/drivers/gpu/a + return MALI_TRUE; +} +#endif /* __MALI_KERNEL_CORE_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_utilization.c b/drivers/gpu/arm/mali400/common/mali_kernel_utilization.c ---- a/drivers/gpu/arm/mali400/common/mali_kernel_utilization.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_kernel_utilization.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_kernel_utilization.c b/drivers/gpu/arm/mali400/common/mali_kernel_utilization.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_kernel_utilization.c @@ -0,0 +1,440 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -21734,9 +23113,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_utilization.c b/driver +{ + return last_utilization_pp; +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_utilization.h b/drivers/gpu/arm/mali400/common/mali_kernel_utilization.h ---- a/drivers/gpu/arm/mali400/common/mali_kernel_utilization.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_kernel_utilization.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_kernel_utilization.h b/drivers/gpu/arm/mali400/common/mali_kernel_utilization.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_kernel_utilization.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -21810,9 +23191,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_utilization.h b/driver + + +#endif /* __MALI_KERNEL_UTILIZATION_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_vsync.c b/drivers/gpu/arm/mali400/common/mali_kernel_vsync.c ---- a/drivers/gpu/arm/mali400/common/mali_kernel_vsync.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_kernel_vsync.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_kernel_vsync.c b/drivers/gpu/arm/mali400/common/mali_kernel_vsync.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_kernel_vsync.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2011-2014, 2016 ARM Limited. All rights reserved. @@ -21859,9 +23242,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_kernel_vsync.c b/drivers/gpu/ + MALI_SUCCESS; +} + -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_l2_cache.c b/drivers/gpu/arm/mali400/common/mali_l2_cache.c ---- a/drivers/gpu/arm/mali400/common/mali_l2_cache.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_l2_cache.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_l2_cache.c b/drivers/gpu/arm/mali400/common/mali_l2_cache.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_l2_cache.c @@ -0,0 +1,534 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -22397,9 +23782,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_l2_cache.c b/drivers/gpu/arm/ + + return _MALI_OSK_ERR_OK; +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_l2_cache.h b/drivers/gpu/arm/mali400/common/mali_l2_cache.h ---- a/drivers/gpu/arm/mali400/common/mali_l2_cache.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_l2_cache.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_l2_cache.h b/drivers/gpu/arm/mali400/common/mali_l2_cache.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_l2_cache.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -22525,9 +23912,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_l2_cache.h b/drivers/gpu/arm/ +void mali_l2_cache_invalidate_all_pages(u32 *pages, u32 num_pages); + +#endif /* __MALI_KERNEL_L2_CACHE_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mem_validation.c b/drivers/gpu/arm/mali400/common/mali_mem_validation.c ---- a/drivers/gpu/arm/mali400/common/mali_mem_validation.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_mem_validation.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_mem_validation.c b/drivers/gpu/arm/mali400/common/mali_mem_validation.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_mem_validation.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2011-2014, 2016 ARM Limited. All rights reserved. @@ -22594,9 +23983,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mem_validation.c b/drivers/gp + + return _MALI_OSK_ERR_FAULT; +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mem_validation.h b/drivers/gpu/arm/mali400/common/mali_mem_validation.h ---- a/drivers/gpu/arm/mali400/common/mali_mem_validation.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_mem_validation.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_mem_validation.h b/drivers/gpu/arm/mali400/common/mali_mem_validation.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_mem_validation.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011-2013, 2016 ARM Limited. All rights reserved. @@ -22617,9 +24008,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mem_validation.h b/drivers/gp +_mali_osk_errcode_t mali_mem_validation_check(u32 phys_addr, u32 size); + +#endif /* __MALI_MEM_VALIDATION_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mmu.c b/drivers/gpu/arm/mali400/common/mali_mmu.c ---- a/drivers/gpu/arm/mali400/common/mali_mmu.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_mmu.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_mmu.c b/drivers/gpu/arm/mali400/common/mali_mmu.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_mmu.c @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -23054,9 +24447,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mmu.c b/drivers/gpu/arm/mali4 + MALI_DEBUG_PRINT(2, ("MMU: State of %s is 0x%08x\n", mmu->hw_core.description, mali_hw_core_register_read(&mmu->hw_core, MALI_MMU_REGISTER_STATUS))); +} +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mmu.h b/drivers/gpu/arm/mali400/common/mali_mmu.h ---- a/drivers/gpu/arm/mali400/common/mali_mmu.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_mmu.h 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_mmu.h b/drivers/gpu/arm/mali400/common/mali_mmu.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_mmu.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -23182,9 +24577,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mmu.h b/drivers/gpu/arm/mali4 +} + +#endif /* __MALI_MMU_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.c b/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.c ---- a/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.c 2018-05-06 08:49:49.174695256 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.c b/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.c @@ -0,0 +1,495 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -23681,9 +25078,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.c b/driver + + MALI_SUCCESS; +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.h b/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.h ---- a/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.h b/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2011-2014, 2016 ARM Limited. All rights reserved. @@ -23795,175 +25194,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_mmu_page_directory.h b/driver +void mali_mmu_pagedir_diag(struct mali_page_directory *pagedir, u32 fault_addr); + +#endif /* __MALI_MMU_PAGE_DIRECTORY_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_osk_bitops.h b/drivers/gpu/arm/mali400/common/mali_osk_bitops.h ---- a/drivers/gpu/arm/mali400/common/mali_osk_bitops.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_osk_bitops.h 2018-05-06 08:49:49.178695419 +0200 -@@ -0,0 +1,162 @@ -+/* -+ * Copyright (C) 2010, 2013-2014, 2016 ARM Limited. All rights reserved. -+ * -+ * 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. -+ */ -+ -+/** -+ * @file mali_osk_bitops.h -+ * Implementation of the OS abstraction layer for the kernel device driver -+ */ -+ -+#ifndef __MALI_OSK_BITOPS_H__ -+#define __MALI_OSK_BITOPS_H__ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+MALI_STATIC_INLINE void _mali_internal_clear_bit(u32 bit, u32 *addr) -+{ -+ MALI_DEBUG_ASSERT(bit < 32); -+ MALI_DEBUG_ASSERT(NULL != addr); -+ -+ (*addr) &= ~(1 << bit); -+} -+ -+MALI_STATIC_INLINE void _mali_internal_set_bit(u32 bit, u32 *addr) -+{ -+ MALI_DEBUG_ASSERT(bit < 32); -+ MALI_DEBUG_ASSERT(NULL != addr); -+ -+ (*addr) |= (1 << bit); -+} -+ -+MALI_STATIC_INLINE u32 _mali_internal_test_bit(u32 bit, u32 value) -+{ -+ MALI_DEBUG_ASSERT(bit < 32); -+ return value & (1 << bit); -+} -+ -+MALI_STATIC_INLINE int _mali_internal_find_first_zero_bit(u32 value) -+{ -+ u32 inverted; -+ u32 negated; -+ u32 isolated; -+ u32 leading_zeros; -+ -+ /* Begin with xxx...x0yyy...y, where ys are 1, number of ys is in range 0..31 */ -+ inverted = ~value; /* zzz...z1000...0 */ -+ /* Using count_trailing_zeros on inverted value - -+ * See ARM System Developers Guide for details of count_trailing_zeros */ -+ -+ /* Isolate the zero: it is preceeded by a run of 1s, so add 1 to it */ -+ negated = (u32) - inverted ; /* -a == ~a + 1 (mod 2^n) for n-bit numbers */ -+ /* negated = xxx...x1000...0 */ -+ -+ isolated = negated & inverted ; /* xxx...x1000...0 & zzz...z1000...0, zs are ~xs */ -+ /* And so the first zero bit is in the same position as the 1 == number of 1s that preceeded it -+ * Note that the output is zero if value was all 1s */ -+ -+ leading_zeros = _mali_osk_clz(isolated); -+ -+ return 31 - leading_zeros; -+} -+ -+ -+/** @defgroup _mali_osk_bitops OSK Non-atomic Bit-operations -+ * @{ */ -+ -+/** -+ * These bit-operations do not work atomically, and so locks must be used if -+ * atomicity is required. -+ * -+ * Reference implementations for Little Endian are provided, and so it should -+ * not normally be necessary to re-implement these. Efficient bit-twiddling -+ * techniques are used where possible, implemented in portable C. -+ * -+ * Note that these reference implementations rely on _mali_osk_clz() being -+ * implemented. -+ */ -+ -+/** @brief Clear a bit in a sequence of 32-bit words -+ * @param nr bit number to clear, starting from the (Little-endian) least -+ * significant bit -+ * @param addr starting point for counting. -+ */ -+MALI_STATIC_INLINE void _mali_osk_clear_nonatomic_bit(u32 nr, u32 *addr) -+{ -+ addr += nr >> 5; /* find the correct word */ -+ nr = nr & ((1 << 5) - 1); /* The bit number within the word */ -+ -+ _mali_internal_clear_bit(nr, addr); -+} -+ -+/** @brief Set a bit in a sequence of 32-bit words -+ * @param nr bit number to set, starting from the (Little-endian) least -+ * significant bit -+ * @param addr starting point for counting. -+ */ -+MALI_STATIC_INLINE void _mali_osk_set_nonatomic_bit(u32 nr, u32 *addr) -+{ -+ addr += nr >> 5; /* find the correct word */ -+ nr = nr & ((1 << 5) - 1); /* The bit number within the word */ -+ -+ _mali_internal_set_bit(nr, addr); -+} -+ -+/** @brief Test a bit in a sequence of 32-bit words -+ * @param nr bit number to test, starting from the (Little-endian) least -+ * significant bit -+ * @param addr starting point for counting. -+ * @return zero if bit was clear, non-zero if set. Do not rely on the return -+ * value being related to the actual word under test. -+ */ -+MALI_STATIC_INLINE u32 _mali_osk_test_bit(u32 nr, u32 *addr) -+{ -+ addr += nr >> 5; /* find the correct word */ -+ nr = nr & ((1 << 5) - 1); /* The bit number within the word */ -+ -+ return _mali_internal_test_bit(nr, *addr); -+} -+ -+/* Return maxbit if not found */ -+/** @brief Find the first zero bit in a sequence of 32-bit words -+ * @param addr starting point for search. -+ * @param maxbit the maximum number of bits to search -+ * @return the number of the first zero bit found, or maxbit if none were found -+ * in the specified range. -+ */ -+MALI_STATIC_INLINE u32 _mali_osk_find_first_zero_bit(const u32 *addr, u32 maxbit) -+{ -+ u32 total; -+ -+ for (total = 0; total < maxbit; total += 32, ++addr) { -+ int result; -+ result = _mali_internal_find_first_zero_bit(*addr); -+ -+ /* non-negative signifies the bit was found */ -+ if (result >= 0) { -+ total += (u32)result; -+ break; -+ } -+ } -+ -+ /* Now check if we reached maxbit or above */ -+ if (total >= maxbit) { -+ total = maxbit; -+ } -+ -+ return total; /* either the found bit nr, or maxbit if not found */ -+} -+/** @} */ /* end group _mali_osk_bitops */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* __MALI_OSK_BITOPS_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_osk.h b/drivers/gpu/arm/mali400/common/mali_osk.h ---- a/drivers/gpu/arm/mali400/common/mali_osk.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_osk.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_osk.h b/drivers/gpu/arm/mali400/common/mali_osk.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_osk.h @@ -0,0 +1,1389 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -25354,9 +26589,179 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_osk.h b/drivers/gpu/arm/mali4 +#endif + +#endif /* __MALI_OSK_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_osk_list.h b/drivers/gpu/arm/mali400/common/mali_osk_list.h ---- a/drivers/gpu/arm/mali400/common/mali_osk_list.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_osk_list.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_osk_bitops.h b/drivers/gpu/arm/mali400/common/mali_osk_bitops.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_osk_bitops.h +@@ -0,0 +1,162 @@ ++/* ++ * Copyright (C) 2010, 2013-2014, 2016 ARM Limited. All rights reserved. ++ * ++ * 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. ++ */ ++ ++/** ++ * @file mali_osk_bitops.h ++ * Implementation of the OS abstraction layer for the kernel device driver ++ */ ++ ++#ifndef __MALI_OSK_BITOPS_H__ ++#define __MALI_OSK_BITOPS_H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++MALI_STATIC_INLINE void _mali_internal_clear_bit(u32 bit, u32 *addr) ++{ ++ MALI_DEBUG_ASSERT(bit < 32); ++ MALI_DEBUG_ASSERT(NULL != addr); ++ ++ (*addr) &= ~(1 << bit); ++} ++ ++MALI_STATIC_INLINE void _mali_internal_set_bit(u32 bit, u32 *addr) ++{ ++ MALI_DEBUG_ASSERT(bit < 32); ++ MALI_DEBUG_ASSERT(NULL != addr); ++ ++ (*addr) |= (1 << bit); ++} ++ ++MALI_STATIC_INLINE u32 _mali_internal_test_bit(u32 bit, u32 value) ++{ ++ MALI_DEBUG_ASSERT(bit < 32); ++ return value & (1 << bit); ++} ++ ++MALI_STATIC_INLINE int _mali_internal_find_first_zero_bit(u32 value) ++{ ++ u32 inverted; ++ u32 negated; ++ u32 isolated; ++ u32 leading_zeros; ++ ++ /* Begin with xxx...x0yyy...y, where ys are 1, number of ys is in range 0..31 */ ++ inverted = ~value; /* zzz...z1000...0 */ ++ /* Using count_trailing_zeros on inverted value - ++ * See ARM System Developers Guide for details of count_trailing_zeros */ ++ ++ /* Isolate the zero: it is preceeded by a run of 1s, so add 1 to it */ ++ negated = (u32) - inverted ; /* -a == ~a + 1 (mod 2^n) for n-bit numbers */ ++ /* negated = xxx...x1000...0 */ ++ ++ isolated = negated & inverted ; /* xxx...x1000...0 & zzz...z1000...0, zs are ~xs */ ++ /* And so the first zero bit is in the same position as the 1 == number of 1s that preceeded it ++ * Note that the output is zero if value was all 1s */ ++ ++ leading_zeros = _mali_osk_clz(isolated); ++ ++ return 31 - leading_zeros; ++} ++ ++ ++/** @defgroup _mali_osk_bitops OSK Non-atomic Bit-operations ++ * @{ */ ++ ++/** ++ * These bit-operations do not work atomically, and so locks must be used if ++ * atomicity is required. ++ * ++ * Reference implementations for Little Endian are provided, and so it should ++ * not normally be necessary to re-implement these. Efficient bit-twiddling ++ * techniques are used where possible, implemented in portable C. ++ * ++ * Note that these reference implementations rely on _mali_osk_clz() being ++ * implemented. ++ */ ++ ++/** @brief Clear a bit in a sequence of 32-bit words ++ * @param nr bit number to clear, starting from the (Little-endian) least ++ * significant bit ++ * @param addr starting point for counting. ++ */ ++MALI_STATIC_INLINE void _mali_osk_clear_nonatomic_bit(u32 nr, u32 *addr) ++{ ++ addr += nr >> 5; /* find the correct word */ ++ nr = nr & ((1 << 5) - 1); /* The bit number within the word */ ++ ++ _mali_internal_clear_bit(nr, addr); ++} ++ ++/** @brief Set a bit in a sequence of 32-bit words ++ * @param nr bit number to set, starting from the (Little-endian) least ++ * significant bit ++ * @param addr starting point for counting. ++ */ ++MALI_STATIC_INLINE void _mali_osk_set_nonatomic_bit(u32 nr, u32 *addr) ++{ ++ addr += nr >> 5; /* find the correct word */ ++ nr = nr & ((1 << 5) - 1); /* The bit number within the word */ ++ ++ _mali_internal_set_bit(nr, addr); ++} ++ ++/** @brief Test a bit in a sequence of 32-bit words ++ * @param nr bit number to test, starting from the (Little-endian) least ++ * significant bit ++ * @param addr starting point for counting. ++ * @return zero if bit was clear, non-zero if set. Do not rely on the return ++ * value being related to the actual word under test. ++ */ ++MALI_STATIC_INLINE u32 _mali_osk_test_bit(u32 nr, u32 *addr) ++{ ++ addr += nr >> 5; /* find the correct word */ ++ nr = nr & ((1 << 5) - 1); /* The bit number within the word */ ++ ++ return _mali_internal_test_bit(nr, *addr); ++} ++ ++/* Return maxbit if not found */ ++/** @brief Find the first zero bit in a sequence of 32-bit words ++ * @param addr starting point for search. ++ * @param maxbit the maximum number of bits to search ++ * @return the number of the first zero bit found, or maxbit if none were found ++ * in the specified range. ++ */ ++MALI_STATIC_INLINE u32 _mali_osk_find_first_zero_bit(const u32 *addr, u32 maxbit) ++{ ++ u32 total; ++ ++ for (total = 0; total < maxbit; total += 32, ++addr) { ++ int result; ++ result = _mali_internal_find_first_zero_bit(*addr); ++ ++ /* non-negative signifies the bit was found */ ++ if (result >= 0) { ++ total += (u32)result; ++ break; ++ } ++ } ++ ++ /* Now check if we reached maxbit or above */ ++ if (total >= maxbit) { ++ total = maxbit; ++ } ++ ++ return total; /* either the found bit nr, or maxbit if not found */ ++} ++/** @} */ /* end group _mali_osk_bitops */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __MALI_OSK_BITOPS_H__ */ +diff --git a/drivers/gpu/arm/mali400/common/mali_osk_list.h b/drivers/gpu/arm/mali400/common/mali_osk_list.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_osk_list.h @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -25631,9 +27036,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_osk_list.h b/drivers/gpu/arm/ +#endif + +#endif /* __MALI_OSK_LIST_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_osk_mali.h b/drivers/gpu/arm/mali400/common/mali_osk_mali.h ---- a/drivers/gpu/arm/mali400/common/mali_osk_mali.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_osk_mali.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_osk_mali.h b/drivers/gpu/arm/mali400/common/mali_osk_mali.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_osk_mali.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -25786,9 +27193,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_osk_mali.h b/drivers/gpu/arm/ +#endif + +#endif /* __MALI_OSK_MALI_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_osk_profiling.h b/drivers/gpu/arm/mali400/common/mali_osk_profiling.h ---- a/drivers/gpu/arm/mali400/common/mali_osk_profiling.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_osk_profiling.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_osk_profiling.h b/drivers/gpu/arm/mali400/common/mali_osk_profiling.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_osk_profiling.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -25936,9 +27345,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_osk_profiling.h b/drivers/gpu +#endif /* __MALI_OSK_PROFILING_H__ */ + + -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_osk_types.h b/drivers/gpu/arm/mali400/common/mali_osk_types.h ---- a/drivers/gpu/arm/mali400/common/mali_osk_types.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_osk_types.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_osk_types.h b/drivers/gpu/arm/mali400/common/mali_osk_types.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_osk_types.h @@ -0,0 +1,471 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -26411,9 +27822,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_osk_types.h b/drivers/gpu/arm +#endif + +#endif /* __MALI_OSK_TYPES_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pm.c b/drivers/gpu/arm/mali400/common/mali_pm.c ---- a/drivers/gpu/arm/mali400/common/mali_pm.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pm.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_pm.c b/drivers/gpu/arm/mali400/common/mali_pm.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pm.c @@ -0,0 +1,1362 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -27777,9 +29190,108 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pm.c b/drivers/gpu/arm/mali40 +{ + return pd_mask_wanted; +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pm_domain.c b/drivers/gpu/arm/mali400/common/mali_pm_domain.c ---- a/drivers/gpu/arm/mali400/common/mali_pm_domain.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pm_domain.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_pm.h b/drivers/gpu/arm/mali400/common/mali_pm.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pm.h +@@ -0,0 +1,91 @@ ++/* ++ * Copyright (C) 2011-2016 ARM Limited. All rights reserved. ++ * ++ * 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 __MALI_PM_H__ ++#define __MALI_PM_H__ ++ ++#include "mali_osk.h" ++#include "mali_pm_domain.h" ++ ++#define MALI_DOMAIN_INDEX_GP 0 ++#define MALI_DOMAIN_INDEX_PP0 1 ++#define MALI_DOMAIN_INDEX_PP1 2 ++#define MALI_DOMAIN_INDEX_PP2 3 ++#define MALI_DOMAIN_INDEX_PP3 4 ++#define MALI_DOMAIN_INDEX_PP4 5 ++#define MALI_DOMAIN_INDEX_PP5 6 ++#define MALI_DOMAIN_INDEX_PP6 7 ++#define MALI_DOMAIN_INDEX_PP7 8 ++#define MALI_DOMAIN_INDEX_L20 9 ++#define MALI_DOMAIN_INDEX_L21 10 ++#define MALI_DOMAIN_INDEX_L22 11 ++/* ++ * The dummy domain is used when there is no physical power domain ++ * (e.g. no PMU or always on cores) ++ */ ++#define MALI_DOMAIN_INDEX_DUMMY 12 ++#define MALI_MAX_NUMBER_OF_DOMAINS 13 ++ ++/** ++ * Initialize the Mali PM module ++ * ++ * PM module covers Mali PM core, PM domains and Mali PMU ++ */ ++_mali_osk_errcode_t mali_pm_initialize(void); ++ ++/** ++ * Terminate the Mali PM module ++ */ ++void mali_pm_terminate(void); ++ ++void mali_pm_exec_lock(void); ++void mali_pm_exec_unlock(void); ++ ++ ++struct mali_pm_domain *mali_pm_register_l2_cache(u32 domain_index, ++ struct mali_l2_cache_core *l2_cache); ++struct mali_pm_domain *mali_pm_register_group(u32 domain_index, ++ struct mali_group *group); ++ ++mali_bool mali_pm_get_domain_refs(struct mali_pm_domain **domains, ++ struct mali_group **groups, ++ u32 num_domains); ++mali_bool mali_pm_put_domain_refs(struct mali_pm_domain **domains, ++ u32 num_domains); ++ ++void mali_pm_init_begin(void); ++void mali_pm_init_end(void); ++ ++void mali_pm_update_sync(void); ++void mali_pm_update_async(void); ++ ++/* Callback functions for system power management */ ++void mali_pm_os_suspend(mali_bool os_suspend); ++void mali_pm_os_resume(void); ++ ++mali_bool mali_pm_runtime_suspend(void); ++void mali_pm_runtime_resume(void); ++ ++#if MALI_STATE_TRACKING ++u32 mali_pm_dump_state_domain(struct mali_pm_domain *domain, ++ char *buf, u32 size); ++#endif ++ ++void mali_pm_power_cost_setup(void); ++ ++void mali_pm_get_best_power_cost_mask(int num_requested, int *dst); ++ ++#if defined(DEBUG) ++const char *mali_pm_mask_to_string(u32 mask); ++#endif ++ ++u32 mali_pm_get_current_mask(void); ++u32 mali_pm_get_wanted_mask(void); ++#endif /* __MALI_PM_H__ */ +diff --git a/drivers/gpu/arm/mali400/common/mali_pm_domain.c b/drivers/gpu/arm/mali400/common/mali_pm_domain.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pm_domain.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2013-2014, 2016 ARM Limited. All rights reserved. @@ -27990,9 +29502,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pm_domain.c b/drivers/gpu/arm + return MALI_TRUE; +} +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pm_domain.h b/drivers/gpu/arm/mali400/common/mali_pm_domain.h ---- a/drivers/gpu/arm/mali400/common/mali_pm_domain.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pm_domain.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_pm_domain.h b/drivers/gpu/arm/mali400/common/mali_pm_domain.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pm_domain.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2013-2014, 2016 ARM Limited. All rights reserved. @@ -28098,104 +29612,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pm_domain.h b/drivers/gpu/arm +#endif + +#endif /* __MALI_PM_DOMAIN_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pm.h b/drivers/gpu/arm/mali400/common/mali_pm.h ---- a/drivers/gpu/arm/mali400/common/mali_pm.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pm.h 2018-05-06 08:49:49.178695419 +0200 -@@ -0,0 +1,91 @@ -+/* -+ * Copyright (C) 2011-2016 ARM Limited. All rights reserved. -+ * -+ * 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 __MALI_PM_H__ -+#define __MALI_PM_H__ -+ -+#include "mali_osk.h" -+#include "mali_pm_domain.h" -+ -+#define MALI_DOMAIN_INDEX_GP 0 -+#define MALI_DOMAIN_INDEX_PP0 1 -+#define MALI_DOMAIN_INDEX_PP1 2 -+#define MALI_DOMAIN_INDEX_PP2 3 -+#define MALI_DOMAIN_INDEX_PP3 4 -+#define MALI_DOMAIN_INDEX_PP4 5 -+#define MALI_DOMAIN_INDEX_PP5 6 -+#define MALI_DOMAIN_INDEX_PP6 7 -+#define MALI_DOMAIN_INDEX_PP7 8 -+#define MALI_DOMAIN_INDEX_L20 9 -+#define MALI_DOMAIN_INDEX_L21 10 -+#define MALI_DOMAIN_INDEX_L22 11 -+/* -+ * The dummy domain is used when there is no physical power domain -+ * (e.g. no PMU or always on cores) -+ */ -+#define MALI_DOMAIN_INDEX_DUMMY 12 -+#define MALI_MAX_NUMBER_OF_DOMAINS 13 -+ -+/** -+ * Initialize the Mali PM module -+ * -+ * PM module covers Mali PM core, PM domains and Mali PMU -+ */ -+_mali_osk_errcode_t mali_pm_initialize(void); -+ -+/** -+ * Terminate the Mali PM module -+ */ -+void mali_pm_terminate(void); -+ -+void mali_pm_exec_lock(void); -+void mali_pm_exec_unlock(void); -+ -+ -+struct mali_pm_domain *mali_pm_register_l2_cache(u32 domain_index, -+ struct mali_l2_cache_core *l2_cache); -+struct mali_pm_domain *mali_pm_register_group(u32 domain_index, -+ struct mali_group *group); -+ -+mali_bool mali_pm_get_domain_refs(struct mali_pm_domain **domains, -+ struct mali_group **groups, -+ u32 num_domains); -+mali_bool mali_pm_put_domain_refs(struct mali_pm_domain **domains, -+ u32 num_domains); -+ -+void mali_pm_init_begin(void); -+void mali_pm_init_end(void); -+ -+void mali_pm_update_sync(void); -+void mali_pm_update_async(void); -+ -+/* Callback functions for system power management */ -+void mali_pm_os_suspend(mali_bool os_suspend); -+void mali_pm_os_resume(void); -+ -+mali_bool mali_pm_runtime_suspend(void); -+void mali_pm_runtime_resume(void); -+ -+#if MALI_STATE_TRACKING -+u32 mali_pm_dump_state_domain(struct mali_pm_domain *domain, -+ char *buf, u32 size); -+#endif -+ -+void mali_pm_power_cost_setup(void); -+ -+void mali_pm_get_best_power_cost_mask(int num_requested, int *dst); -+ -+#if defined(DEBUG) -+const char *mali_pm_mask_to_string(u32 mask); -+#endif -+ -+u32 mali_pm_get_current_mask(void); -+u32 mali_pm_get_wanted_mask(void); -+#endif /* __MALI_PM_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pm_metrics.c b/drivers/gpu/arm/mali400/common/mali_pm_metrics.c ---- a/drivers/gpu/arm/mali400/common/mali_pm_metrics.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pm_metrics.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_pm_metrics.c b/drivers/gpu/arm/mali400/common/mali_pm_metrics.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pm_metrics.c @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -28452,9 +29873,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pm_metrics.c b/drivers/gpu/ar + struct mali_device *mdev = dev_get_drvdata(&mali_platform_device->dev); + _mali_osk_spinlock_irq_unlock(mdev->mali_metrics.lock); +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pm_metrics.h b/drivers/gpu/arm/mali400/common/mali_pm_metrics.h ---- a/drivers/gpu/arm/mali400/common/mali_pm_metrics.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pm_metrics.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_pm_metrics.h b/drivers/gpu/arm/mali400/common/mali_pm_metrics.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pm_metrics.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -28530,9 +29953,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pm_metrics.h b/drivers/gpu/ar +void mali_pm_record_gpu_active(mali_bool is_gp) {} +#endif +#endif /* __MALI_PM_METRICS_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pmu.c b/drivers/gpu/arm/mali400/common/mali_pmu.c ---- a/drivers/gpu/arm/mali400/common/mali_pmu.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pmu.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_pmu.c b/drivers/gpu/arm/mali400/common/mali_pmu.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pmu.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -28804,9 +30229,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pmu.c b/drivers/gpu/arm/mali4 + + return _MALI_OSK_ERR_OK; +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pmu.h b/drivers/gpu/arm/mali400/common/mali_pmu.h ---- a/drivers/gpu/arm/mali400/common/mali_pmu.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pmu.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_pmu.h b/drivers/gpu/arm/mali400/common/mali_pmu.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pmu.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -28931,9 +30358,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pmu.h b/drivers/gpu/arm/mali4 +_mali_osk_errcode_t mali_pmu_power_up(struct mali_pmu_core *pmu, u32 mask); + +#endif /* __MALI_PMU_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pp.c b/drivers/gpu/arm/mali400/common/mali_pp.c ---- a/drivers/gpu/arm/mali400/common/mali_pp.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pp.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_pp.c b/drivers/gpu/arm/mali400/common/mali_pp.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pp.c @@ -0,0 +1,502 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -29437,9 +30866,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pp.c b/drivers/gpu/arm/mali40 + return n; +} +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pp.h b/drivers/gpu/arm/mali400/common/mali_pp.h ---- a/drivers/gpu/arm/mali400/common/mali_pp.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pp.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_pp.h b/drivers/gpu/arm/mali400/common/mali_pp.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pp.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -29579,9 +31010,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pp.h b/drivers/gpu/arm/mali40 +} + +#endif /* __MALI_PP_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pp_job.c b/drivers/gpu/arm/mali400/common/mali_pp_job.c ---- a/drivers/gpu/arm/mali400/common/mali_pp_job.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pp_job.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_pp_job.c b/drivers/gpu/arm/mali400/common/mali_pp_job.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pp_job.c @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -29898,9 +31331,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pp_job.c b/drivers/gpu/arm/ma + MALI_DEBUG_ASSERT(sub_job < _MALI_PP_MAX_SUB_JOBS); + return pp_counter_per_sub_job_src1[sub_job]; +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pp_job.h b/drivers/gpu/arm/mali400/common/mali_pp_job.h ---- a/drivers/gpu/arm/mali400/common/mali_pp_job.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_pp_job.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_pp_job.h b/drivers/gpu/arm/mali400/common/mali_pp_job.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_pp_job.h @@ -0,0 +1,591 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -30493,9 +31928,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_pp_job.h b/drivers/gpu/arm/ma + + +#endif /* __MALI_PP_JOB_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_scheduler.c b/drivers/gpu/arm/mali400/common/mali_scheduler.c ---- a/drivers/gpu/arm/mali400/common/mali_scheduler.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_scheduler.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_scheduler.c b/drivers/gpu/arm/mali400/common/mali_scheduler.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_scheduler.c @@ -0,0 +1,1548 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -32045,9 +33482,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_scheduler.c b/drivers/gpu/arm + /* dump group running job status */ + mali_executor_running_status_print(); +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_scheduler.h b/drivers/gpu/arm/mali400/common/mali_scheduler.h ---- a/drivers/gpu/arm/mali400/common/mali_scheduler.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_scheduler.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_scheduler.h b/drivers/gpu/arm/mali400/common/mali_scheduler.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_scheduler.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -32180,9 +33619,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_scheduler.h b/drivers/gpu/arm +void mali_scheduler_gp_pp_job_queue_print(void); + +#endif /* __MALI_SCHEDULER_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_scheduler_types.h b/drivers/gpu/arm/mali400/common/mali_scheduler_types.h ---- a/drivers/gpu/arm/mali400/common/mali_scheduler_types.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_scheduler_types.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_scheduler_types.h b/drivers/gpu/arm/mali400/common/mali_scheduler_types.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_scheduler_types.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2013-2014, 2016 ARM Limited. All rights reserved. @@ -32213,9 +33654,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_scheduler_types.h b/drivers/g +#define MALI_SCHEDULER_MASK_ALL (MALI_SCHEDULER_MASK_GP | MALI_SCHEDULER_MASK_PP) + +#endif /* __MALI_SCHEDULER_TYPES_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_session.c b/drivers/gpu/arm/mali400/common/mali_session.c ---- a/drivers/gpu/arm/mali400/common/mali_session.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_session.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_session.c b/drivers/gpu/arm/mali400/common/mali_session.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_session.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -32372,9 +33815,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_session.c b/drivers/gpu/arm/m + _mali_osk_ctxprintf(print_ctx, "Mali swap mem pool : %u\nMali swap mem unlock: %u\n", swap_pool_size, swap_unlock_size); +#endif +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_session.h b/drivers/gpu/arm/mali400/common/mali_session.h ---- a/drivers/gpu/arm/mali400/common/mali_session.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_session.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_session.h b/drivers/gpu/arm/mali400/common/mali_session.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_session.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -32512,9 +33957,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_session.h b/drivers/gpu/arm/m +void mali_session_memory_tracking(_mali_osk_print_ctx *print_ctx); + +#endif /* __MALI_SESSION_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_soft_job.c b/drivers/gpu/arm/mali400/common/mali_soft_job.c ---- a/drivers/gpu/arm/mali400/common/mali_soft_job.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_soft_job.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_soft_job.c b/drivers/gpu/arm/mali400/common/mali_soft_job.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_soft_job.c @@ -0,0 +1,438 @@ +/* + * Copyright (C) 2013-2014, 2016 ARM Limited. All rights reserved. @@ -32954,9 +34401,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_soft_job.c b/drivers/gpu/arm/ + mali_soft_job_destroy(job); + } +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_soft_job.h b/drivers/gpu/arm/mali400/common/mali_soft_job.h ---- a/drivers/gpu/arm/mali400/common/mali_soft_job.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_soft_job.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_soft_job.h b/drivers/gpu/arm/mali400/common/mali_soft_job.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_soft_job.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2013-2014, 2016 ARM Limited. All rights reserved. @@ -33148,9 +34597,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_soft_job.h b/drivers/gpu/arm/ +void mali_soft_job_system_abort(struct mali_soft_job_system *system); + +#endif /* __MALI_SOFT_JOB_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.c b/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.c ---- a/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.c b/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2013, 2016 ARM Limited. All rights reserved. @@ -33229,9 +34680,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.c b/driver + _mali_osk_spinlock_irq_unlock(spinlock->lock); + } +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.h b/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.h ---- a/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.h b/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2013, 2016 ARM Limited. All rights reserved. @@ -33303,9 +34756,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_spinlock_reentrant.h b/driver +} + +#endif /* __MALI_SPINLOCK_REENTRANT_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_timeline.c b/drivers/gpu/arm/mali400/common/mali_timeline.c ---- a/drivers/gpu/arm/mali400/common/mali_timeline.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_timeline.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_timeline.c b/drivers/gpu/arm/mali400/common/mali_timeline.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_timeline.c @@ -0,0 +1,1748 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -35055,286 +36510,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_timeline.c b/drivers/gpu/arm/ + } +} +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.c b/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.c ---- a/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.c 2018-05-06 08:49:49.178695419 +0200 -@@ -0,0 +1,202 @@ -+/* -+ * Copyright (C) 2013-2014, 2016 ARM Limited. All rights reserved. -+ * -+ * 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. -+ */ -+ -+#include "mali_timeline_fence_wait.h" -+ -+#include "mali_osk.h" -+#include "mali_kernel_common.h" -+#include "mali_spinlock_reentrant.h" -+ -+/** -+ * Allocate a fence waiter tracker. -+ * -+ * @return New fence waiter if successful, NULL if not. -+ */ -+static struct mali_timeline_fence_wait_tracker *mali_timeline_fence_wait_tracker_alloc(void) -+{ -+ return (struct mali_timeline_fence_wait_tracker *) _mali_osk_calloc(1, sizeof(struct mali_timeline_fence_wait_tracker)); -+} -+ -+/** -+ * Free fence waiter tracker. -+ * -+ * @param wait Fence wait tracker to free. -+ */ -+static void mali_timeline_fence_wait_tracker_free(struct mali_timeline_fence_wait_tracker *wait) -+{ -+ MALI_DEBUG_ASSERT_POINTER(wait); -+ _mali_osk_atomic_term(&wait->refcount); -+ _mali_osk_free(wait); -+} -+ -+/** -+ * Check if fence wait tracker has been activated. Used as a wait queue condition. -+ * -+ * @param data Fence waiter. -+ * @return MALI_TRUE if tracker has been activated, MALI_FALSE if not. -+ */ -+static mali_bool mali_timeline_fence_wait_tracker_is_activated(void *data) -+{ -+ struct mali_timeline_fence_wait_tracker *wait; -+ -+ wait = (struct mali_timeline_fence_wait_tracker *) data; -+ MALI_DEBUG_ASSERT_POINTER(wait); -+ -+ return wait->activated; -+} -+ -+/** -+ * Check if fence has been signaled. -+ * -+ * @param system Timeline system. -+ * @param fence Timeline fence. -+ * @return MALI_TRUE if fence is signaled, MALI_FALSE if not. -+ */ -+static mali_bool mali_timeline_fence_wait_check_status(struct mali_timeline_system *system, struct mali_timeline_fence *fence) -+{ -+ int i; -+ u32 tid = _mali_osk_get_tid(); -+ mali_bool ret = MALI_TRUE; -+#if defined(CONFIG_SYNC) -+ struct sync_fence *sync_fence = NULL; -+#endif -+ -+ MALI_DEBUG_ASSERT_POINTER(system); -+ MALI_DEBUG_ASSERT_POINTER(fence); -+ -+ mali_spinlock_reentrant_wait(system->spinlock, tid); -+ -+ for (i = 0; i < MALI_TIMELINE_MAX; ++i) { -+ struct mali_timeline *timeline; -+ mali_timeline_point point; -+ -+ point = fence->points[i]; -+ -+ if (likely(MALI_TIMELINE_NO_POINT == point)) { -+ /* Fence contains no point on this timeline. */ -+ continue; -+ } -+ -+ timeline = system->timelines[i]; -+ MALI_DEBUG_ASSERT_POINTER(timeline); -+ -+ if (unlikely(!mali_timeline_is_point_valid(timeline, point))) { -+ MALI_PRINT_ERROR(("Mali Timeline: point %d is not valid (oldest=%d, next=%d)\n", point, timeline->point_oldest, timeline->point_next)); -+ } -+ -+ if (!mali_timeline_is_point_released(timeline, point)) { -+ ret = MALI_FALSE; -+ goto exit; -+ } -+ } -+ -+#if defined(CONFIG_SYNC) -+ if (-1 != fence->sync_fd) { -+ sync_fence = sync_fence_fdget(fence->sync_fd); -+ if (likely(NULL != sync_fence)) { -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) -+ if (0 == sync_fence->status) { -+#else -+ if (0 == atomic_read(&sync_fence->status)) { -+#endif -+ ret = MALI_FALSE; -+ } -+ } else { -+ MALI_PRINT_ERROR(("Mali Timeline: failed to get sync fence from fd %d\n", fence->sync_fd)); -+ } -+ } -+#endif /* defined(CONFIG_SYNC) */ -+ -+exit: -+ mali_spinlock_reentrant_signal(system->spinlock, tid); -+ -+#if defined(CONFIG_SYNC) -+ if (NULL != sync_fence) { -+ sync_fence_put(sync_fence); -+ } -+#endif /* defined(CONFIG_SYNC) */ -+ -+ return ret; -+} -+ -+mali_bool mali_timeline_fence_wait(struct mali_timeline_system *system, struct mali_timeline_fence *fence, u32 timeout) -+{ -+ struct mali_timeline_fence_wait_tracker *wait; -+ mali_timeline_point point; -+ mali_bool ret; -+ -+ MALI_DEBUG_ASSERT_POINTER(system); -+ MALI_DEBUG_ASSERT_POINTER(fence); -+ -+ MALI_DEBUG_PRINT(4, ("Mali Timeline: wait on fence\n")); -+ -+ if (MALI_TIMELINE_FENCE_WAIT_TIMEOUT_IMMEDIATELY == timeout) { -+ return mali_timeline_fence_wait_check_status(system, fence); -+ } -+ -+ wait = mali_timeline_fence_wait_tracker_alloc(); -+ if (unlikely(NULL == wait)) { -+ MALI_PRINT_ERROR(("Mali Timeline: failed to allocate data for fence wait\n")); -+ return MALI_FALSE; -+ } -+ -+ wait->activated = MALI_FALSE; -+ wait->system = system; -+ -+ /* Initialize refcount to two references. The reference first will be released by this -+ * function after the wait is over. The second reference will be released when the tracker -+ * is activated. */ -+ _mali_osk_atomic_init(&wait->refcount, 2); -+ -+ /* Add tracker to timeline system, but not to a timeline. */ -+ mali_timeline_tracker_init(&wait->tracker, MALI_TIMELINE_TRACKER_WAIT, fence, wait); -+ point = mali_timeline_system_add_tracker(system, &wait->tracker, MALI_TIMELINE_NONE); -+ MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT == point); -+ MALI_IGNORE(point); -+ -+ /* Wait for the tracker to be activated or time out. */ -+ if (MALI_TIMELINE_FENCE_WAIT_TIMEOUT_NEVER == timeout) { -+ _mali_osk_wait_queue_wait_event(system->wait_queue, mali_timeline_fence_wait_tracker_is_activated, (void *) wait); -+ } else { -+ _mali_osk_wait_queue_wait_event_timeout(system->wait_queue, mali_timeline_fence_wait_tracker_is_activated, (void *) wait, timeout); -+ } -+ -+ ret = wait->activated; -+ -+ if (0 == _mali_osk_atomic_dec_return(&wait->refcount)) { -+ mali_timeline_fence_wait_tracker_free(wait); -+ } -+ -+ return ret; -+} -+ -+void mali_timeline_fence_wait_activate(struct mali_timeline_fence_wait_tracker *wait) -+{ -+ mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY; -+ -+ MALI_DEBUG_ASSERT_POINTER(wait); -+ MALI_DEBUG_ASSERT_POINTER(wait->system); -+ -+ MALI_DEBUG_PRINT(4, ("Mali Timeline: activation for fence wait tracker\n")); -+ -+ MALI_DEBUG_ASSERT(MALI_FALSE == wait->activated); -+ wait->activated = MALI_TRUE; -+ -+ _mali_osk_wait_queue_wake_up(wait->system->wait_queue); -+ -+ /* Nothing can wait on this tracker, so nothing to schedule after release. */ -+ schedule_mask = mali_timeline_tracker_release(&wait->tracker); -+ MALI_DEBUG_ASSERT(MALI_SCHEDULER_MASK_EMPTY == schedule_mask); -+ MALI_IGNORE(schedule_mask); -+ -+ if (0 == _mali_osk_atomic_dec_return(&wait->refcount)) { -+ mali_timeline_fence_wait_tracker_free(wait); -+ } -+} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.h b/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.h ---- a/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.h 2018-05-06 08:49:49.178695419 +0200 -@@ -0,0 +1,67 @@ -+/* -+ * Copyright (C) 2013, 2016 ARM Limited. All rights reserved. -+ * -+ * 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. -+ */ -+ -+/** -+ * @file mali_timeline_fence_wait.h -+ * -+ * This file contains functions used to wait until a Timeline fence is signaled. -+ */ -+ -+#ifndef __MALI_TIMELINE_FENCE_WAIT_H__ -+#define __MALI_TIMELINE_FENCE_WAIT_H__ -+ -+#include "mali_osk.h" -+#include "mali_timeline.h" -+ -+/** -+ * If used as the timeout argument in @ref mali_timeline_fence_wait, a timer is not used and the -+ * function only returns when the fence is signaled. -+ */ -+#define MALI_TIMELINE_FENCE_WAIT_TIMEOUT_NEVER ((u32) -1) -+ -+/** -+ * If used as the timeout argument in @ref mali_timeline_fence_wait, the function will return -+ * immediately with the current state of the fence. -+ */ -+#define MALI_TIMELINE_FENCE_WAIT_TIMEOUT_IMMEDIATELY 0 -+ -+/** -+ * Fence wait tracker. -+ * -+ * The fence wait tracker is added to the Timeline system with the fence we are waiting on as a -+ * dependency. We will then perform a blocking wait, possibly with a timeout, until the tracker is -+ * activated, which happens when the fence is signaled. -+ */ -+struct mali_timeline_fence_wait_tracker { -+ mali_bool activated; /**< MALI_TRUE if the tracker has been activated, MALI_FALSE if not. */ -+ _mali_osk_atomic_t refcount; /**< Reference count. */ -+ struct mali_timeline_system *system; /**< Timeline system. */ -+ struct mali_timeline_tracker tracker; /**< Timeline tracker. */ -+}; -+ -+/** -+ * Wait for a fence to be signaled, or timeout is reached. -+ * -+ * @param system Timeline system. -+ * @param fence Fence to wait on. -+ * @param timeout Timeout in ms, or MALI_TIMELINE_FENCE_WAIT_TIMEOUT_NEVER or -+ * MALI_TIMELINE_FENCE_WAIT_TIMEOUT_IMMEDIATELY. -+ * @return MALI_TRUE if signaled, MALI_FALSE if timed out. -+ */ -+mali_bool mali_timeline_fence_wait(struct mali_timeline_system *system, struct mali_timeline_fence *fence, u32 timeout); -+ -+/** -+ * Used by the Timeline system to activate a fence wait tracker. -+ * -+ * @param fence_wait_tracker Fence waiter tracker. -+ */ -+void mali_timeline_fence_wait_activate(struct mali_timeline_fence_wait_tracker *fence_wait_tracker); -+ -+#endif /* __MALI_TIMELINE_FENCE_WAIT_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_timeline.h b/drivers/gpu/arm/mali400/common/mali_timeline.h ---- a/drivers/gpu/arm/mali400/common/mali_timeline.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_timeline.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_timeline.h b/drivers/gpu/arm/mali400/common/mali_timeline.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_timeline.h @@ -0,0 +1,548 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -35884,9 +37064,292 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_timeline.h b/drivers/gpu/arm/ +#endif + +#endif /* __MALI_TIMELINE_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.c b/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.c ---- a/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.c b/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.c +@@ -0,0 +1,202 @@ ++/* ++ * Copyright (C) 2013-2014, 2016 ARM Limited. All rights reserved. ++ * ++ * 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. ++ */ ++ ++#include "mali_timeline_fence_wait.h" ++ ++#include "mali_osk.h" ++#include "mali_kernel_common.h" ++#include "mali_spinlock_reentrant.h" ++ ++/** ++ * Allocate a fence waiter tracker. ++ * ++ * @return New fence waiter if successful, NULL if not. ++ */ ++static struct mali_timeline_fence_wait_tracker *mali_timeline_fence_wait_tracker_alloc(void) ++{ ++ return (struct mali_timeline_fence_wait_tracker *) _mali_osk_calloc(1, sizeof(struct mali_timeline_fence_wait_tracker)); ++} ++ ++/** ++ * Free fence waiter tracker. ++ * ++ * @param wait Fence wait tracker to free. ++ */ ++static void mali_timeline_fence_wait_tracker_free(struct mali_timeline_fence_wait_tracker *wait) ++{ ++ MALI_DEBUG_ASSERT_POINTER(wait); ++ _mali_osk_atomic_term(&wait->refcount); ++ _mali_osk_free(wait); ++} ++ ++/** ++ * Check if fence wait tracker has been activated. Used as a wait queue condition. ++ * ++ * @param data Fence waiter. ++ * @return MALI_TRUE if tracker has been activated, MALI_FALSE if not. ++ */ ++static mali_bool mali_timeline_fence_wait_tracker_is_activated(void *data) ++{ ++ struct mali_timeline_fence_wait_tracker *wait; ++ ++ wait = (struct mali_timeline_fence_wait_tracker *) data; ++ MALI_DEBUG_ASSERT_POINTER(wait); ++ ++ return wait->activated; ++} ++ ++/** ++ * Check if fence has been signaled. ++ * ++ * @param system Timeline system. ++ * @param fence Timeline fence. ++ * @return MALI_TRUE if fence is signaled, MALI_FALSE if not. ++ */ ++static mali_bool mali_timeline_fence_wait_check_status(struct mali_timeline_system *system, struct mali_timeline_fence *fence) ++{ ++ int i; ++ u32 tid = _mali_osk_get_tid(); ++ mali_bool ret = MALI_TRUE; ++#if defined(CONFIG_SYNC) ++ struct sync_fence *sync_fence = NULL; ++#endif ++ ++ MALI_DEBUG_ASSERT_POINTER(system); ++ MALI_DEBUG_ASSERT_POINTER(fence); ++ ++ mali_spinlock_reentrant_wait(system->spinlock, tid); ++ ++ for (i = 0; i < MALI_TIMELINE_MAX; ++i) { ++ struct mali_timeline *timeline; ++ mali_timeline_point point; ++ ++ point = fence->points[i]; ++ ++ if (likely(MALI_TIMELINE_NO_POINT == point)) { ++ /* Fence contains no point on this timeline. */ ++ continue; ++ } ++ ++ timeline = system->timelines[i]; ++ MALI_DEBUG_ASSERT_POINTER(timeline); ++ ++ if (unlikely(!mali_timeline_is_point_valid(timeline, point))) { ++ MALI_PRINT_ERROR(("Mali Timeline: point %d is not valid (oldest=%d, next=%d)\n", point, timeline->point_oldest, timeline->point_next)); ++ } ++ ++ if (!mali_timeline_is_point_released(timeline, point)) { ++ ret = MALI_FALSE; ++ goto exit; ++ } ++ } ++ ++#if defined(CONFIG_SYNC) ++ if (-1 != fence->sync_fd) { ++ sync_fence = sync_fence_fdget(fence->sync_fd); ++ if (likely(NULL != sync_fence)) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) ++ if (0 == sync_fence->status) { ++#else ++ if (0 == atomic_read(&sync_fence->status)) { ++#endif ++ ret = MALI_FALSE; ++ } ++ } else { ++ MALI_PRINT_ERROR(("Mali Timeline: failed to get sync fence from fd %d\n", fence->sync_fd)); ++ } ++ } ++#endif /* defined(CONFIG_SYNC) */ ++ ++exit: ++ mali_spinlock_reentrant_signal(system->spinlock, tid); ++ ++#if defined(CONFIG_SYNC) ++ if (NULL != sync_fence) { ++ sync_fence_put(sync_fence); ++ } ++#endif /* defined(CONFIG_SYNC) */ ++ ++ return ret; ++} ++ ++mali_bool mali_timeline_fence_wait(struct mali_timeline_system *system, struct mali_timeline_fence *fence, u32 timeout) ++{ ++ struct mali_timeline_fence_wait_tracker *wait; ++ mali_timeline_point point; ++ mali_bool ret; ++ ++ MALI_DEBUG_ASSERT_POINTER(system); ++ MALI_DEBUG_ASSERT_POINTER(fence); ++ ++ MALI_DEBUG_PRINT(4, ("Mali Timeline: wait on fence\n")); ++ ++ if (MALI_TIMELINE_FENCE_WAIT_TIMEOUT_IMMEDIATELY == timeout) { ++ return mali_timeline_fence_wait_check_status(system, fence); ++ } ++ ++ wait = mali_timeline_fence_wait_tracker_alloc(); ++ if (unlikely(NULL == wait)) { ++ MALI_PRINT_ERROR(("Mali Timeline: failed to allocate data for fence wait\n")); ++ return MALI_FALSE; ++ } ++ ++ wait->activated = MALI_FALSE; ++ wait->system = system; ++ ++ /* Initialize refcount to two references. The reference first will be released by this ++ * function after the wait is over. The second reference will be released when the tracker ++ * is activated. */ ++ _mali_osk_atomic_init(&wait->refcount, 2); ++ ++ /* Add tracker to timeline system, but not to a timeline. */ ++ mali_timeline_tracker_init(&wait->tracker, MALI_TIMELINE_TRACKER_WAIT, fence, wait); ++ point = mali_timeline_system_add_tracker(system, &wait->tracker, MALI_TIMELINE_NONE); ++ MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT == point); ++ MALI_IGNORE(point); ++ ++ /* Wait for the tracker to be activated or time out. */ ++ if (MALI_TIMELINE_FENCE_WAIT_TIMEOUT_NEVER == timeout) { ++ _mali_osk_wait_queue_wait_event(system->wait_queue, mali_timeline_fence_wait_tracker_is_activated, (void *) wait); ++ } else { ++ _mali_osk_wait_queue_wait_event_timeout(system->wait_queue, mali_timeline_fence_wait_tracker_is_activated, (void *) wait, timeout); ++ } ++ ++ ret = wait->activated; ++ ++ if (0 == _mali_osk_atomic_dec_return(&wait->refcount)) { ++ mali_timeline_fence_wait_tracker_free(wait); ++ } ++ ++ return ret; ++} ++ ++void mali_timeline_fence_wait_activate(struct mali_timeline_fence_wait_tracker *wait) ++{ ++ mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY; ++ ++ MALI_DEBUG_ASSERT_POINTER(wait); ++ MALI_DEBUG_ASSERT_POINTER(wait->system); ++ ++ MALI_DEBUG_PRINT(4, ("Mali Timeline: activation for fence wait tracker\n")); ++ ++ MALI_DEBUG_ASSERT(MALI_FALSE == wait->activated); ++ wait->activated = MALI_TRUE; ++ ++ _mali_osk_wait_queue_wake_up(wait->system->wait_queue); ++ ++ /* Nothing can wait on this tracker, so nothing to schedule after release. */ ++ schedule_mask = mali_timeline_tracker_release(&wait->tracker); ++ MALI_DEBUG_ASSERT(MALI_SCHEDULER_MASK_EMPTY == schedule_mask); ++ MALI_IGNORE(schedule_mask); ++ ++ if (0 == _mali_osk_atomic_dec_return(&wait->refcount)) { ++ mali_timeline_fence_wait_tracker_free(wait); ++ } ++} +diff --git a/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.h b/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_timeline_fence_wait.h +@@ -0,0 +1,67 @@ ++/* ++ * Copyright (C) 2013, 2016 ARM Limited. All rights reserved. ++ * ++ * 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. ++ */ ++ ++/** ++ * @file mali_timeline_fence_wait.h ++ * ++ * This file contains functions used to wait until a Timeline fence is signaled. ++ */ ++ ++#ifndef __MALI_TIMELINE_FENCE_WAIT_H__ ++#define __MALI_TIMELINE_FENCE_WAIT_H__ ++ ++#include "mali_osk.h" ++#include "mali_timeline.h" ++ ++/** ++ * If used as the timeout argument in @ref mali_timeline_fence_wait, a timer is not used and the ++ * function only returns when the fence is signaled. ++ */ ++#define MALI_TIMELINE_FENCE_WAIT_TIMEOUT_NEVER ((u32) -1) ++ ++/** ++ * If used as the timeout argument in @ref mali_timeline_fence_wait, the function will return ++ * immediately with the current state of the fence. ++ */ ++#define MALI_TIMELINE_FENCE_WAIT_TIMEOUT_IMMEDIATELY 0 ++ ++/** ++ * Fence wait tracker. ++ * ++ * The fence wait tracker is added to the Timeline system with the fence we are waiting on as a ++ * dependency. We will then perform a blocking wait, possibly with a timeout, until the tracker is ++ * activated, which happens when the fence is signaled. ++ */ ++struct mali_timeline_fence_wait_tracker { ++ mali_bool activated; /**< MALI_TRUE if the tracker has been activated, MALI_FALSE if not. */ ++ _mali_osk_atomic_t refcount; /**< Reference count. */ ++ struct mali_timeline_system *system; /**< Timeline system. */ ++ struct mali_timeline_tracker tracker; /**< Timeline tracker. */ ++}; ++ ++/** ++ * Wait for a fence to be signaled, or timeout is reached. ++ * ++ * @param system Timeline system. ++ * @param fence Fence to wait on. ++ * @param timeout Timeout in ms, or MALI_TIMELINE_FENCE_WAIT_TIMEOUT_NEVER or ++ * MALI_TIMELINE_FENCE_WAIT_TIMEOUT_IMMEDIATELY. ++ * @return MALI_TRUE if signaled, MALI_FALSE if timed out. ++ */ ++mali_bool mali_timeline_fence_wait(struct mali_timeline_system *system, struct mali_timeline_fence *fence, u32 timeout); ++ ++/** ++ * Used by the Timeline system to activate a fence wait tracker. ++ * ++ * @param fence_wait_tracker Fence waiter tracker. ++ */ ++void mali_timeline_fence_wait_activate(struct mali_timeline_fence_wait_tracker *fence_wait_tracker); ++ ++#endif /* __MALI_TIMELINE_FENCE_WAIT_H__ */ +diff --git a/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.c b/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2013, 2016 ARM Limited. All rights reserved. @@ -36046,9 +37509,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.c b/drive +} + +#endif /* defined(CONFIG_SYNC) */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.h b/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.h ---- a/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.h b/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2013, 2016 ARM Limited. All rights reserved. @@ -36101,9 +37566,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_timeline_sync_fence.h b/drive +#endif /* defined(CONFIG_SYNC) */ + +#endif /* __MALI_TIMELINE_SYNC_FENCE_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_ukk.h b/drivers/gpu/arm/mali400/common/mali_ukk.h ---- a/drivers/gpu/arm/mali400/common/mali_ukk.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_ukk.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_ukk.h b/drivers/gpu/arm/mali400/common/mali_ukk.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_ukk.h @@ -0,0 +1,551 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -36656,9 +38123,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_ukk.h b/drivers/gpu/arm/mali4 +#endif + +#endif /* __MALI_UKK_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_user_settings_db.c b/drivers/gpu/arm/mali400/common/mali_user_settings_db.c ---- a/drivers/gpu/arm/mali400/common/mali_user_settings_db.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_user_settings_db.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_user_settings_db.c b/drivers/gpu/arm/mali400/common/mali_user_settings_db.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_user_settings_db.c @@ -0,0 +1,147 @@ +/** + * Copyright (C) 2012-2014, 2016 ARM Limited. All rights reserved. @@ -36807,9 +38276,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_user_settings_db.c b/drivers/ + + return _MALI_OSK_ERR_OK; +} -diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_user_settings_db.h b/drivers/gpu/arm/mali400/common/mali_user_settings_db.h ---- a/drivers/gpu/arm/mali400/common/mali_user_settings_db.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/common/mali_user_settings_db.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/common/mali_user_settings_db.h b/drivers/gpu/arm/mali400/common/mali_user_settings_db.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/common/mali_user_settings_db.h @@ -0,0 +1,39 @@ +/** + * Copyright (C) 2012-2013, 2016 ARM Limited. All rights reserved. @@ -36850,14 +38321,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/common/mali_user_settings_db.h b/drivers/ +} +#endif +#endif /* __MALI_KERNEL_USER_SETTING__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/.gitignore b/drivers/gpu/arm/mali400/.gitignore ---- a/drivers/gpu/arm/mali400/.gitignore 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/.gitignore 2018-05-06 08:49:49.174695256 +0200 -@@ -0,0 +1 @@ -+__malidrv_build_info.c -diff -ENwbur a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard.h b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard.h ---- a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard.h b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard.h @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -37390,9 +38858,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard.h b/driver + int mali_perf_set_num_pp_cores(unsigned int num_cores); + +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_ioctl.h b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_ioctl.h ---- a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_ioctl.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_ioctl.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_ioctl.h b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_ioctl.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_ioctl.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -37494,9 +38964,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_ioctl.h b/ +#endif + +#endif /* __MALI_UTGARD_IOCTL_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_events.h b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_events.h ---- a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_events.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_events.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_events.h b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_events.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_events.h @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -37698,9 +39170,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_ + + +#endif /*_MALI_UTGARD_PROFILING_EVENTS_H_*/ -diff -ENwbur a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_gator_api.h b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_gator_api.h ---- a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_gator_api.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_gator_api.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_gator_api.h b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_gator_api.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_gator_api.h @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2013, 2015-2016 ARM Limited. All rights reserved. @@ -38017,9 +39491,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_profiling_ +#endif + +#endif /* __MALI_UTGARD_PROFILING_GATOR_API_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_uk_types.h b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_uk_types.h ---- a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_uk_types.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_uk_types.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_uk_types.h b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_uk_types.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_uk_types.h @@ -0,0 +1,1100 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -39121,430 +40597,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/include/linux/mali/mali_utgard_uk_types.h +#endif + +#endif /* __MALI_UTGARD_UK_TYPES_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/Kbuild b/drivers/gpu/arm/mali400/Kbuild ---- a/drivers/gpu/arm/mali400/Kbuild 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/Kbuild 2018-05-06 08:49:49.174695256 +0200 -@@ -0,0 +1,261 @@ -+# -+# Copyright (C) 2010-2011 ARM Limited. All rights reserved. -+# -+# 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. -+# -+ -+# This file is called by the Linux build system. -+ -+# set up defaults if not defined by the user -+TIMESTAMP ?= default -+OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 -+USING_GPU_UTILIZATION ?= 0 -+PROFILING_SKIP_PP_JOBS ?= 0 -+PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 -+MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP ?= 0 -+MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0 -+MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0 -+MALI_UPPER_HALF_SCHEDULING ?= 1 -+MALI_ENABLE_CPU_CYCLES ?= 0 -+ -+# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: -+# The ARM proprietary product will only include the license/proprietary directory -+# The GPL product will only include the license/gpl directory -+ifeq ($(wildcard $(src)/linux/license/gpl/*),) -+ ccflags-y += -I$(src)/linux/license/proprietary -+ ifeq ($(CONFIG_MALI400_PROFILING),y) -+ $(error Profiling is incompatible with non-GPL license) -+ endif -+ ifeq ($(CONFIG_PM_RUNTIME),y) -+ $(error Runtime PM is incompatible with non-GPL license) -+ endif -+ ifeq ($(CONFIG_DMA_SHARED_BUFFER),y) -+ $(error DMA-BUF is incompatible with non-GPL license) -+ endif -+ $(error Linux Device integration is incompatible with non-GPL license) -+else -+ ccflags-y += -I$(src)/linux/license/gpl -+endif -+ -+ifeq ($(USING_GPU_UTILIZATION), 1) -+ ifeq ($(USING_DVFS), 1) -+ $(error USING_GPU_UTILIZATION conflict with USING_DVFS you can read the Integration Guide to choose which one do you need) -+ endif -+endif -+ -+ifeq ($(CONFIG_MALI_PLATFORM_S5P4418),y) -+export MALI_PLATFORM=nexell -+endif -+ -+ifeq ($(CONFIG_MALI_PLATFORM_S5P6818),y) -+export MALI_PLATFORM=nexell -+endif -+ -+ifeq ($(CONFIG_ARCH_EXYNOS4),y) -+export MALI_PLATFORM=exynos4 -+endif -+ -+ifeq ($(MALI_PLATFORM_FILES),) -+EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1 -+export MALI_PLATFORM_FILES_BUILDIN = $(notdir $(wildcard $(src)/platform/$(MALI_PLATFORM)/*.c)) -+export MALI_PLATFORM_FILES_ADD_PREFIX = $(addprefix platform/$(MALI_PLATFORM)/,$(MALI_PLATFORM_FILES_BUILDIN)) -+endif -+ -+mali-y += \ -+ linux/mali_osk_atomics.o \ -+ linux/mali_osk_irq.o \ -+ linux/mali_osk_wq.o \ -+ linux/mali_osk_locks.o \ -+ linux/mali_osk_wait_queue.o \ -+ linux/mali_osk_low_level_mem.o \ -+ linux/mali_osk_math.o \ -+ linux/mali_osk_memory.o \ -+ linux/mali_osk_misc.o \ -+ linux/mali_osk_mali.o \ -+ linux/mali_osk_notification.o \ -+ linux/mali_osk_time.o \ -+ linux/mali_osk_timers.o \ -+ linux/mali_osk_bitmap.o -+ -+mali-y += linux/mali_memory.o linux/mali_memory_os_alloc.o -+mali-y += linux/mali_memory_external.o -+mali-y += linux/mali_memory_block_alloc.o -+mali-y += linux/mali_memory_swap_alloc.o -+ -+mali-y += \ -+ linux/mali_memory_manager.o \ -+ linux/mali_memory_virtual.o \ -+ linux/mali_memory_util.o \ -+ linux/mali_memory_cow.o \ -+ linux/mali_memory_defer_bind.o -+ -+mali-y += \ -+ linux/mali_ukk_mem.o \ -+ linux/mali_ukk_gp.o \ -+ linux/mali_ukk_pp.o \ -+ linux/mali_ukk_core.o \ -+ linux/mali_ukk_soft_job.o \ -+ linux/mali_ukk_timeline.o -+ -+mali-$(CONFIG_MALI_DEVFREQ) += \ -+ linux/mali_devfreq.o \ -+ common/mali_pm_metrics.o -+ -+# Source files which always are included in a build -+mali-y += \ -+ common/mali_kernel_core.o \ -+ linux/mali_kernel_linux.o \ -+ common/mali_session.o \ -+ linux/mali_device_pause_resume.o \ -+ common/mali_kernel_vsync.o \ -+ linux/mali_ukk_vsync.o \ -+ linux/mali_kernel_sysfs.o \ -+ common/mali_mmu.o \ -+ common/mali_mmu_page_directory.o \ -+ common/mali_mem_validation.o \ -+ common/mali_hw_core.o \ -+ common/mali_gp.o \ -+ common/mali_pp.o \ -+ common/mali_pp_job.o \ -+ common/mali_gp_job.o \ -+ common/mali_soft_job.o \ -+ common/mali_scheduler.o \ -+ common/mali_executor.o \ -+ common/mali_group.o \ -+ common/mali_dlbu.o \ -+ common/mali_broadcast.o \ -+ common/mali_pm.o \ -+ common/mali_pmu.o \ -+ common/mali_user_settings_db.o \ -+ common/mali_kernel_utilization.o \ -+ common/mali_control_timer.o \ -+ common/mali_l2_cache.o \ -+ common/mali_timeline.o \ -+ common/mali_timeline_fence_wait.o \ -+ common/mali_timeline_sync_fence.o \ -+ common/mali_spinlock_reentrant.o \ -+ common/mali_pm_domain.o \ -+ linux/mali_osk_pm.o \ -+ linux/mali_pmu_power_up_down.o \ -+ __malidrv_build_info.o -+ -+ifneq ($(wildcard $(src)/linux/mali_slp_global_lock.c),) -+ mali-y += linux/mali_slp_global_lock.o -+endif -+ -+ifneq ($(MALI_PLATFORM_FILES),) -+ mali-y += $(MALI_PLATFORM_FILES:.c=.o) -+endif -+ -+ifneq ($(MALI_PLATFORM_FILES_ADD_PREFIX),) -+ mali-y += $(MALI_PLATFORM_FILES_ADD_PREFIX:.c=.o) -+endif -+ -+mali-$(CONFIG_MALI400_PROFILING) += linux/mali_ukk_profiling.o -+mali-$(CONFIG_MALI400_PROFILING) += linux/mali_osk_profiling.o -+ -+mali-$(CONFIG_MALI400_INTERNAL_PROFILING) += linux/mali_profiling_internal.o timestamp-$(TIMESTAMP)/mali_timestamp.o -+ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(src)/timestamp-$(TIMESTAMP) -+ -+mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_memory_dma_buf.o -+mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_memory_secure.o -+mali-$(CONFIG_SYNC) += linux/mali_sync.o -+mali-$(CONFIG_MALI_DMA_BUF_FENCE) += linux/mali_dma_fence.o -+ccflags-$(CONFIG_SYNC) += -Idrivers/staging/android -+ -+mali-$(CONFIG_MALI400_UMP) += linux/mali_memory_ump.o -+ -+mali-$(CONFIG_MALI_DVFS) += common/mali_dvfs_policy.o -+ -+# Tell the Linux build system from which .o file to create the kernel module -+obj-$(CONFIG_MALI400) := mali.o -+ -+ccflags-y += $(EXTRA_DEFINES) -+ -+# Set up our defines, which will be passed to gcc -+ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) -+ccflags-y += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) -+ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) -+ccflags-y += -DMALI_STATE_TRACKING=1 -+ccflags-y += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) -+ccflags-y += -DUSING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) -+ccflags-y += -DMALI_ENABLE_CPU_CYCLES=$(MALI_ENABLE_CPU_CYCLES) -+ -+ifeq ($(MALI_UPPER_HALF_SCHEDULING),1) -+ ccflags-y += -DMALI_UPPER_HALF_SCHEDULING -+endif -+ -+#build-in include path is different -+ifeq ($(MALI_PLATFORM_FILES),) -+ccflags-$(CONFIG_MALI400_UMP) += -I$(src)/../ump/include/ -+else -+ccflags-$(CONFIG_MALI400_UMP) += -I$(src)/../../ump/include/ump -+endif -+ccflags-$(CONFIG_MALI400_DEBUG) += -DDEBUG -+ -+# Use our defines when compiling -+ccflags-y += -I$(src) -I$(src)/include -I$(src)/common -I$(src)/linux -I$(src)/platform -Wno-date-time -+ -+# Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available -+MALI_RELEASE_NAME=$(shell cat $(src)/.version 2> /dev/null) -+ -+SVN_INFO = (cd $(src); svn info 2>/dev/null) -+ -+ifneq ($(shell $(SVN_INFO) 2>/dev/null),) -+# SVN detected -+SVN_REV := $(shell $(SVN_INFO) | grep '^Revision: '| sed -e 's/^Revision: //' 2>/dev/null) -+DRIVER_REV := $(MALI_RELEASE_NAME)-r$(SVN_REV) -+CHANGE_DATE := $(shell $(SVN_INFO) | grep '^Last Changed Date: ' | cut -d: -f2- | cut -b2-) -+CHANGED_REVISION := $(shell $(SVN_INFO) | grep '^Last Changed Rev: ' | cut -d: -f2- | cut -b2-) -+REPO_URL := $(shell $(SVN_INFO) | grep '^URL: ' | cut -d: -f2- | cut -b2-) -+ -+else # SVN -+GIT_REV := $(shell cd $(src); git describe --always 2>/dev/null) -+ifneq ($(GIT_REV),) -+# Git detected -+DRIVER_REV := $(MALI_RELEASE_NAME)-$(GIT_REV) -+CHANGE_DATE := $(shell cd $(src); git log -1 --format="%ci") -+CHANGED_REVISION := $(GIT_REV) -+REPO_URL := $(shell cd $(src); git describe --all --always 2>/dev/null) -+ -+else # Git -+# No Git or SVN detected -+DRIVER_REV := $(MALI_RELEASE_NAME) -+CHANGE_DATE := $(MALI_RELEASE_NAME) -+CHANGED_REVISION := $(MALI_RELEASE_NAME) -+endif -+endif -+ -+ccflags-y += -DSVN_REV_STRING=\"$(DRIVER_REV)\" -+ -+VERSION_STRINGS := -+VERSION_STRINGS += API_VERSION=$(shell cd $(src); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) -+VERSION_STRINGS += REPO_URL=$(REPO_URL) -+VERSION_STRINGS += REVISION=$(DRIVER_REV) -+VERSION_STRINGS += CHANGED_REVISION=$(CHANGED_REVISION) -+VERSION_STRINGS += CHANGE_DATE=$(CHANGE_DATE) -+VERSION_STRINGS += BUILD_DATE=$(shell date) -+ifdef CONFIG_MALI400_DEBUG -+VERSION_STRINGS += BUILD=debug -+else -+VERSION_STRINGS += BUILD=release -+endif -+VERSION_STRINGS += TARGET_PLATFORM=$(TARGET_PLATFORM) -+VERSION_STRINGS += MALI_PLATFORM=$(MALI_PLATFORM) -+VERSION_STRINGS += KDIR=$(KDIR) -+VERSION_STRINGS += OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) -+VERSION_STRINGS += USING_UMP=$(CONFIG_MALI400_UMP) -+VERSION_STRINGS += USING_PROFILING=$(CONFIG_MALI400_PROFILING) -+VERSION_STRINGS += USING_INTERNAL_PROFILING=$(CONFIG_MALI400_INTERNAL_PROFILING) -+VERSION_STRINGS += USING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) -+VERSION_STRINGS += USING_DVFS=$(CONFIG_MALI_DVFS) -+VERSION_STRINGS += USING_DMA_BUF_FENCE = $(CONFIG_MALI_DMA_BUF_FENCE) -+VERSION_STRINGS += MALI_UPPER_HALF_SCHEDULING=$(MALI_UPPER_HALF_SCHEDULING) -+ -+# Create file with Mali driver configuration -+$(src)/__malidrv_build_info.c: -+ @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(src)/__malidrv_build_info.c -diff -ENwbur a/drivers/gpu/arm/mali400/Kconfig b/drivers/gpu/arm/mali400/Kconfig ---- a/drivers/gpu/arm/mali400/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/Kconfig 2018-05-06 08:49:49.174695256 +0200 -@@ -0,0 +1,152 @@ -+config MALI400 -+ tristate "Mali-300/400/450 support" -+ depends on ARM || ARM64 -+ select DMA_SHARED_BUFFER -+ ---help--- -+ This enables support for the ARM Mali-300, Mali-400, and Mali-450 -+ GPUs. -+ -+ To compile this driver as a module, choose M here: the module will be -+ called mali. -+ -+config MALI450 -+ bool "Enable Mali-450 support" -+ depends on MALI400 -+ ---help--- -+ This enables support for Mali-450 specific features. -+ -+config MALI470 -+ bool "Enable Mali-470 support" -+ depends on MALI400 -+ ---help--- -+ This enables support for Mali-470 specific features. -+ -+config MALI400_DEBUG -+ bool "Enable debug in Mali driver" -+ depends on MALI400 -+ ---help--- -+ This enabled extra debug checks and messages in the Mali driver. -+ -+choice -+ prompt "Platform configuration" -+ depends on (MALI400 || MALI450 || MALI470) -+ default MALI_PLATFORM_S5P6818 if ARM64 -+ default MALI_PLATFORM_S5P4418 if ARM -+ help -+ Select the SOC platform that contains a Mali utgard GPU -+ -+config MALI_PLATFORM_S5P4418 -+ depends on ARCH_S5P4418 -+ bool "Nexell S5P4418" -+ select MALI_SHARED_INTERRUPTS -+ select MALI_DT -+ help -+ Select S5P4418 SoC configuration -+ -+config MALI_PLATFORM_S5P6818 -+ depends on ARCH_S5P6818 -+ bool "Nexell S5P6818" -+ select MALI_SHARED_INTERRUPTS -+ select MALI_DT -+ help -+ Select S5P6818 SoC configuration -+endchoice -+ -+config MALI400_PROFILING -+ bool "Enable Mali profiling" -+ depends on MALI400 -+ select TRACEPOINTS -+ default y -+ ---help--- -+ This enables gator profiling of Mali GPU events. -+ -+config MALI400_INTERNAL_PROFILING -+ bool "Enable internal Mali profiling API" -+ depends on MALI400_PROFILING -+ default n -+ ---help--- -+ This enables the internal legacy Mali profiling API. -+ -+config MALI400_UMP -+ bool "Enable UMP support" -+ depends on MALI400 -+ ---help--- -+ This enables support for the UMP memory sharing API in the Mali driver. -+ -+config MALI_DVFS -+ bool "Enable Mali dynamically frequency change" -+ depends on MALI400 && !MALI_DEVFREQ -+ default y -+ ---help--- -+ This enables support for dynamic change frequency of Mali with the goal of lowering power consumption. -+ -+config MALI_DMA_BUF_MAP_ON_ATTACH -+ bool "Map dma-buf attachments on attach" -+ depends on MALI400 && DMA_SHARED_BUFFER -+ default y -+ ---help--- -+ This makes the Mali driver map dma-buf attachments after doing -+ attach. If this is not set the dma-buf attachments will be mapped for -+ every time the GPU need to access the buffer. -+ -+ Mapping for each access can cause lower performance. -+ -+config MALI_SHARED_INTERRUPTS -+ bool "Support for shared interrupts" -+ depends on MALI400 -+ default n -+ ---help--- -+ Adds functionality required to properly support shared interrupts. Without this support, -+ the device driver will fail during insmod if it detects shared interrupts. This also -+ works when the GPU is not using shared interrupts, but might have a slight performance -+ impact. -+ -+config MALI_PMU_PARALLEL_POWER_UP -+ bool "Power up Mali PMU domains in parallel" -+ depends on MALI400 -+ default n -+ ---help--- -+ This makes the Mali driver power up all PMU power domains in parallel, instead of -+ powering up domains one by one, with a slight delay in between. Powering on all power -+ domains at the same time may cause peak currents higher than what some systems can handle. -+ These systems must not enable this option. -+ -+config MALI_DT -+ bool "Using device tree to initialize module" -+ depends on MALI400 && OF -+ default n -+ ---help--- -+ This enable the Mali driver to choose the device tree path to get platform resoures -+ and disable the old config method. Mali driver could run on the platform which the -+ device tree is enabled in kernel and corresponding hardware description is implemented -+ properly in device DTS file. -+ -+config MALI_DEVFREQ -+ bool "Using devfreq to tuning frequency" -+ depends on MALI400 && PM_DEVFREQ -+ default n -+ ---help--- -+ Support devfreq for Mali. -+ -+ Using the devfreq framework and, by default, the simpleondemand -+ governor, the frequency of Mali will be dynamically selected from the -+ available OPPs. -+ -+config MALI_QUIET -+ bool "Make Mali driver very quiet" -+ depends on MALI400 && !MALI400_DEBUG -+ default n -+ ---help--- -+ This forces the Mali driver to never print any messages. -+ -+ If unsure, say N. -+ -+config MALI_DMA_BUF_FENCE -+ bool "Make DMA BUF Fence" -+ depends on MALI400 -+ default n -+ ---help--- -+ Choose this option if you want to use fences and reservations for -+ synchronization of shared dma-buf access between different drivers. -+ -+ If unsure, say N. -diff -ENwbur a/drivers/gpu/arm/mali400/linux/license/gpl/mali_kernel_license.h b/drivers/gpu/arm/mali400/linux/license/gpl/mali_kernel_license.h ---- a/drivers/gpu/arm/mali400/linux/license/gpl/mali_kernel_license.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/license/gpl/mali_kernel_license.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/license/gpl/mali_kernel_license.h b/drivers/gpu/arm/mali400/linux/license/gpl/mali_kernel_license.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/license/gpl/mali_kernel_license.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2010, 2013, 2016 ARM Limited. All rights reserved. @@ -39576,9 +40633,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/license/gpl/mali_kernel_license.h b +#endif + +#endif /* __MALI_KERNEL_LICENSE_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_devfreq.c b/drivers/gpu/arm/mali400/linux/mali_devfreq.c ---- a/drivers/gpu/arm/mali400/linux/mali_devfreq.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_devfreq.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_devfreq.c b/drivers/gpu/arm/mali400/linux/mali_devfreq.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_devfreq.c @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -39890,9 +40949,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_devfreq.c b/drivers/gpu/arm/ma + else + mdev->devfreq = NULL; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_devfreq.h b/drivers/gpu/arm/mali400/linux/mali_devfreq.h ---- a/drivers/gpu/arm/mali400/linux/mali_devfreq.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_devfreq.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_devfreq.h b/drivers/gpu/arm/mali400/linux/mali_devfreq.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_devfreq.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -39911,9 +40972,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_devfreq.h b/drivers/gpu/arm/ma +void mali_devfreq_term(struct mali_device *mdev); + +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_device_pause_resume.c b/drivers/gpu/arm/mali400/linux/mali_device_pause_resume.c ---- a/drivers/gpu/arm/mali400/linux/mali_device_pause_resume.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_device_pause_resume.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_device_pause_resume.c b/drivers/gpu/arm/mali400/linux/mali_device_pause_resume.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_device_pause_resume.c @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -39951,9 +41014,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_device_pause_resume.c b/driver +} + +EXPORT_SYMBOL(mali_dev_resume); -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_dma_fence.c b/drivers/gpu/arm/mali400/linux/mali_dma_fence.c ---- a/drivers/gpu/arm/mali400/linux/mali_dma_fence.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_dma_fence.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_dma_fence.c b/drivers/gpu/arm/mali400/linux/mali_dma_fence.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_dma_fence.c @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -40307,9 +41372,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_dma_fence.c b/drivers/gpu/arm/ + + ww_acquire_fini(ww_actx); +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_dma_fence.h b/drivers/gpu/arm/mali400/linux/mali_dma_fence.h ---- a/drivers/gpu/arm/mali400/linux/mali_dma_fence.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_dma_fence.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_dma_fence.h b/drivers/gpu/arm/mali400/linux/mali_dma_fence.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_dma_fence.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -40420,9 +41487,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_dma_fence.h b/drivers/gpu/arm/ +void mali_dma_fence_unlock_reservation_object_list(struct reservation_object **dma_reservation_object_list, + u32 num_dma_reservation_object, struct ww_acquire_ctx *ww_actx); +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_kernel_linux.c b/drivers/gpu/arm/mali400/linux/mali_kernel_linux.c ---- a/drivers/gpu/arm/mali400/linux/mali_kernel_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_kernel_linux.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_kernel_linux.c b/drivers/gpu/arm/mali400/linux/mali_kernel_linux.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_kernel_linux.c @@ -0,0 +1,1154 @@ +/** + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -41578,9 +42647,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_kernel_linux.c b/drivers/gpu/a +MODULE_LICENSE(MALI_KERNEL_LINUX_LICENSE); +MODULE_AUTHOR("ARM Ltd."); +MODULE_VERSION(SVN_REV_STRING); -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_kernel_linux.h b/drivers/gpu/arm/mali400/linux/mali_kernel_linux.h ---- a/drivers/gpu/arm/mali400/linux/mali_kernel_linux.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_kernel_linux.h 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_kernel_linux.h b/drivers/gpu/arm/mali400/linux/mali_kernel_linux.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_kernel_linux.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -41618,9 +42689,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_kernel_linux.h b/drivers/gpu/a +#endif + +#endif /* __MALI_KERNEL_LINUX_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.c b/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.c ---- a/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.c 2018-05-06 08:49:49.178695419 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.c b/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.c @@ -0,0 +1,1410 @@ +/** + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -43032,9 +44105,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.c b/drivers/gpu/a +} + +#endif /* MALI_LICENSE_IS_GPL */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.h b/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.h ---- a/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.h b/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011-2013, 2016 ARM Limited. All rights reserved. @@ -43065,9 +44140,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_kernel_sysfs.h b/drivers/gpu/a +#endif + +#endif /* __MALI_KERNEL_LINUX_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_linux_trace.h b/drivers/gpu/arm/mali400/linux/mali_linux_trace.h ---- a/drivers/gpu/arm/mali400/linux/mali_linux_trace.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_linux_trace.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_linux_trace.h b/drivers/gpu/arm/mali400/linux/mali_linux_trace.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_linux_trace.h @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2012-2014, 2016 ARM Limited. All rights reserved. @@ -43227,437 +44304,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_linux_trace.h b/drivers/gpu/ar +/* This part must exist outside the header guard. */ +#include + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.c b/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.c 2018-05-06 08:49:49.182695581 +0200 -@@ -0,0 +1,362 @@ -+/* -+ * Copyright (C) 2010-2016 ARM Limited. All rights reserved. -+ * -+ * 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. -+ */ -+ -+#include "mali_kernel_common.h" -+#include "mali_memory.h" -+#include "mali_memory_block_alloc.h" -+#include "mali_osk.h" -+#include -+ -+ -+static mali_block_allocator *mali_mem_block_gobal_allocator = NULL; -+ -+unsigned long _mali_blk_item_get_phy_addr(mali_block_item *item) -+{ -+ return (item->phy_addr & ~(MALI_BLOCK_REF_MASK)); -+} -+ -+ -+unsigned long _mali_blk_item_get_pfn(mali_block_item *item) -+{ -+ return (item->phy_addr / MALI_BLOCK_SIZE); -+} -+ -+ -+u32 mali_mem_block_get_ref_count(mali_page_node *node) -+{ -+ MALI_DEBUG_ASSERT(node->type == MALI_PAGE_NODE_BLOCK); -+ return (node->blk_it->phy_addr & MALI_BLOCK_REF_MASK); -+} -+ -+ -+/* Increase the refence count -+* It not atomic, so it need to get sp_lock before call this function -+*/ -+ -+u32 mali_mem_block_add_ref(mali_page_node *node) -+{ -+ MALI_DEBUG_ASSERT(node->type == MALI_PAGE_NODE_BLOCK); -+ MALI_DEBUG_ASSERT(mali_mem_block_get_ref_count(node) < MALI_BLOCK_MAX_REF_COUNT); -+ return (node->blk_it->phy_addr++ & MALI_BLOCK_REF_MASK); -+} -+ -+/* Decase the refence count -+* It not atomic, so it need to get sp_lock before call this function -+*/ -+u32 mali_mem_block_dec_ref(mali_page_node *node) -+{ -+ MALI_DEBUG_ASSERT(node->type == MALI_PAGE_NODE_BLOCK); -+ MALI_DEBUG_ASSERT(mali_mem_block_get_ref_count(node) > 0); -+ return (node->blk_it->phy_addr-- & MALI_BLOCK_REF_MASK); -+} -+ -+ -+static mali_block_allocator *mali_mem_block_allocator_create(u32 base_address, u32 size) -+{ -+ mali_block_allocator *info; -+ u32 usable_size; -+ u32 num_blocks; -+ mali_page_node *m_node; -+ mali_block_item *mali_blk_items = NULL; -+ int i = 0; -+ -+ usable_size = size & ~(MALI_BLOCK_SIZE - 1); -+ MALI_DEBUG_PRINT(3, ("Mali block allocator create for region starting at 0x%08X length 0x%08X\n", base_address, size)); -+ MALI_DEBUG_PRINT(4, ("%d usable bytes\n", usable_size)); -+ num_blocks = usable_size / MALI_BLOCK_SIZE; -+ MALI_DEBUG_PRINT(4, ("which becomes %d blocks\n", num_blocks)); -+ -+ if (usable_size == 0) { -+ MALI_DEBUG_PRINT(1, ("Memory block of size %d is unusable\n", size)); -+ return NULL; -+ } -+ -+ info = _mali_osk_calloc(1, sizeof(mali_block_allocator)); -+ if (NULL != info) { -+ INIT_LIST_HEAD(&info->free); -+ spin_lock_init(&info->sp_lock); -+ info->total_num = num_blocks; -+ mali_blk_items = _mali_osk_calloc(1, sizeof(mali_block_item) * num_blocks); -+ -+ if (mali_blk_items) { -+ info->items = mali_blk_items; -+ /* add blocks(4k size) to free list*/ -+ for (i = 0 ; i < num_blocks ; i++) { -+ /* add block information*/ -+ mali_blk_items[i].phy_addr = base_address + (i * MALI_BLOCK_SIZE); -+ /* add to free list */ -+ m_node = _mali_page_node_allocate(MALI_PAGE_NODE_BLOCK); -+ if (m_node == NULL) -+ goto fail; -+ _mali_page_node_add_block_item(m_node, &(mali_blk_items[i])); -+ list_add_tail(&m_node->list, &info->free); -+ atomic_add(1, &info->free_num); -+ } -+ return info; -+ } -+ } -+fail: -+ mali_mem_block_allocator_destroy(); -+ return NULL; -+} -+ -+void mali_mem_block_allocator_destroy(void) -+{ -+ struct mali_page_node *m_page, *m_tmp; -+ mali_block_allocator *info = mali_mem_block_gobal_allocator; -+ MALI_DEBUG_ASSERT_POINTER(info); -+ MALI_DEBUG_PRINT(4, ("Memory block destroy !\n")); -+ -+ if (NULL == info) -+ return; -+ -+ list_for_each_entry_safe(m_page, m_tmp , &info->free, list) { -+ MALI_DEBUG_ASSERT(m_page->type == MALI_PAGE_NODE_BLOCK); -+ list_del(&m_page->list); -+ kfree(m_page); -+ } -+ -+ _mali_osk_free(info->items); -+ _mali_osk_free(info); -+} -+ -+u32 mali_mem_block_release(mali_mem_backend *mem_bkend) -+{ -+ mali_mem_allocation *alloc = mem_bkend->mali_allocation; -+ u32 free_pages_nr = 0; -+ MALI_DEBUG_ASSERT(mem_bkend->type == MALI_MEM_BLOCK); -+ -+ /* Unmap the memory from the mali virtual address space. */ -+ mali_mem_block_mali_unmap(alloc); -+ mutex_lock(&mem_bkend->mutex); -+ free_pages_nr = mali_mem_block_free(&mem_bkend->block_mem); -+ mutex_unlock(&mem_bkend->mutex); -+ return free_pages_nr; -+} -+ -+ -+int mali_mem_block_alloc(mali_mem_block_mem *block_mem, u32 size) -+{ -+ struct mali_page_node *m_page, *m_tmp; -+ size_t page_count = PAGE_ALIGN(size) / _MALI_OSK_MALI_PAGE_SIZE; -+ mali_block_allocator *info = mali_mem_block_gobal_allocator; -+ MALI_DEBUG_ASSERT_POINTER(info); -+ -+ MALI_DEBUG_PRINT(4, ("BLOCK Mem: Allocate size = 0x%x\n", size)); -+ /*do some init */ -+ INIT_LIST_HEAD(&block_mem->pfns); -+ -+ spin_lock(&info->sp_lock); -+ /*check if have enough space*/ -+ if (atomic_read(&info->free_num) > page_count) { -+ list_for_each_entry_safe(m_page, m_tmp , &info->free, list) { -+ if (page_count > 0) { -+ MALI_DEBUG_ASSERT(m_page->type == MALI_PAGE_NODE_BLOCK); -+ MALI_DEBUG_ASSERT(mali_mem_block_get_ref_count(m_page) == 0); -+ list_move(&m_page->list, &block_mem->pfns); -+ block_mem->count++; -+ atomic_dec(&info->free_num); -+ _mali_page_node_ref(m_page); -+ } else { -+ break; -+ } -+ page_count--; -+ } -+ } else { -+ /* can't allocate from BLOCK memory*/ -+ spin_unlock(&info->sp_lock); -+ return -1; -+ } -+ -+ spin_unlock(&info->sp_lock); -+ return 0; -+} -+ -+u32 mali_mem_block_free(mali_mem_block_mem *block_mem) -+{ -+ u32 free_pages_nr = 0; -+ -+ free_pages_nr = mali_mem_block_free_list(&block_mem->pfns); -+ MALI_DEBUG_PRINT(4, ("BLOCK Mem free : allocated size = 0x%x, free size = 0x%x\n", block_mem->count * _MALI_OSK_MALI_PAGE_SIZE, -+ free_pages_nr * _MALI_OSK_MALI_PAGE_SIZE)); -+ block_mem->count = 0; -+ MALI_DEBUG_ASSERT(list_empty(&block_mem->pfns)); -+ -+ return free_pages_nr; -+} -+ -+ -+u32 mali_mem_block_free_list(struct list_head *list) -+{ -+ struct mali_page_node *m_page, *m_tmp; -+ mali_block_allocator *info = mali_mem_block_gobal_allocator; -+ u32 free_pages_nr = 0; -+ -+ if (info) { -+ spin_lock(&info->sp_lock); -+ list_for_each_entry_safe(m_page, m_tmp , list, list) { -+ if (1 == _mali_page_node_get_ref_count(m_page)) { -+ free_pages_nr++; -+ } -+ mali_mem_block_free_node(m_page); -+ } -+ spin_unlock(&info->sp_lock); -+ } -+ return free_pages_nr; -+} -+ -+/* free the node,*/ -+void mali_mem_block_free_node(struct mali_page_node *node) -+{ -+ mali_block_allocator *info = mali_mem_block_gobal_allocator; -+ -+ /* only handle BLOCK node */ -+ if (node->type == MALI_PAGE_NODE_BLOCK && info) { -+ /*Need to make this atomic?*/ -+ if (1 == _mali_page_node_get_ref_count(node)) { -+ /*Move to free list*/ -+ _mali_page_node_unref(node); -+ list_move_tail(&node->list, &info->free); -+ atomic_add(1, &info->free_num); -+ } else { -+ _mali_page_node_unref(node); -+ list_del(&node->list); -+ kfree(node); -+ } -+ } -+} -+ -+/* unref the node, but not free it */ -+_mali_osk_errcode_t mali_mem_block_unref_node(struct mali_page_node *node) -+{ -+ mali_block_allocator *info = mali_mem_block_gobal_allocator; -+ mali_page_node *new_node; -+ -+ /* only handle BLOCK node */ -+ if (node->type == MALI_PAGE_NODE_BLOCK && info) { -+ /*Need to make this atomic?*/ -+ if (1 == _mali_page_node_get_ref_count(node)) { -+ /* allocate a new node, Add to free list, keep the old node*/ -+ _mali_page_node_unref(node); -+ new_node = _mali_page_node_allocate(MALI_PAGE_NODE_BLOCK); -+ if (new_node) { -+ memcpy(new_node, node, sizeof(mali_page_node)); -+ list_add(&new_node->list, &info->free); -+ atomic_add(1, &info->free_num); -+ } else -+ return _MALI_OSK_ERR_FAULT; -+ -+ } else { -+ _mali_page_node_unref(node); -+ } -+ } -+ return _MALI_OSK_ERR_OK; -+} -+ -+ -+int mali_mem_block_mali_map(mali_mem_block_mem *block_mem, struct mali_session_data *session, u32 vaddr, u32 props) -+{ -+ struct mali_page_directory *pagedir = session->page_directory; -+ struct mali_page_node *m_page; -+ dma_addr_t phys; -+ u32 virt = vaddr; -+ u32 prop = props; -+ -+ list_for_each_entry(m_page, &block_mem->pfns, list) { -+ MALI_DEBUG_ASSERT(m_page->type == MALI_PAGE_NODE_BLOCK); -+ phys = _mali_page_node_get_dma_addr(m_page); -+#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) -+ /* Verify that the "physical" address is 32-bit and -+ * usable for Mali, when on a system with bus addresses -+ * wider than 32-bit. */ -+ MALI_DEBUG_ASSERT(0 == (phys >> 32)); -+#endif -+ mali_mmu_pagedir_update(pagedir, virt, (mali_dma_addr)phys, MALI_MMU_PAGE_SIZE, prop); -+ virt += MALI_MMU_PAGE_SIZE; -+ } -+ -+ return 0; -+} -+ -+void mali_mem_block_mali_unmap(mali_mem_allocation *alloc) -+{ -+ struct mali_session_data *session; -+ MALI_DEBUG_ASSERT_POINTER(alloc); -+ session = alloc->session; -+ MALI_DEBUG_ASSERT_POINTER(session); -+ -+ mali_session_memory_lock(session); -+ mali_mem_mali_map_free(session, alloc->psize, alloc->mali_vma_node.vm_node.start, -+ alloc->flags); -+ mali_session_memory_unlock(session); -+} -+ -+ -+int mali_mem_block_cpu_map(mali_mem_backend *mem_bkend, struct vm_area_struct *vma) -+{ -+ int ret; -+ mali_mem_block_mem *block_mem = &mem_bkend->block_mem; -+ unsigned long addr = vma->vm_start; -+ struct mali_page_node *m_page; -+ MALI_DEBUG_ASSERT(mem_bkend->type == MALI_MEM_BLOCK); -+ -+ list_for_each_entry(m_page, &block_mem->pfns, list) { -+ MALI_DEBUG_ASSERT(m_page->type == MALI_PAGE_NODE_BLOCK); -+ ret = vm_insert_pfn(vma, addr, _mali_page_node_get_pfn(m_page)); -+ -+ if (unlikely(0 != ret)) { -+ return -EFAULT; -+ } -+ addr += _MALI_OSK_MALI_PAGE_SIZE; -+ -+ } -+ -+ return 0; -+} -+ -+ -+_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size) -+{ -+ mali_block_allocator *allocator; -+ -+ /* Do the low level linux operation first */ -+ -+ /* Request ownership of the memory */ -+ if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(start, size, "Dedicated Mali GPU memory")) { -+ MALI_DEBUG_PRINT(1, ("Failed to request memory region for frame buffer (0x%08X - 0x%08X)\n", start, start + size - 1)); -+ return _MALI_OSK_ERR_FAULT; -+ } -+ -+ /* Create generic block allocator object to handle it */ -+ allocator = mali_mem_block_allocator_create(start, size); -+ -+ if (NULL == allocator) { -+ MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n")); -+ _mali_osk_mem_unreqregion(start, size); -+ MALI_ERROR(_MALI_OSK_ERR_FAULT); -+ } -+ -+ mali_mem_block_gobal_allocator = (mali_block_allocator *)allocator; -+ -+ return _MALI_OSK_ERR_OK; -+} -+ -+mali_bool mali_memory_have_dedicated_memory(void) -+{ -+ return mali_mem_block_gobal_allocator ? MALI_TRUE : MALI_FALSE; -+} -+ -+u32 mali_mem_block_allocator_stat(void) -+{ -+ mali_block_allocator *allocator = mali_mem_block_gobal_allocator; -+ MALI_DEBUG_ASSERT_POINTER(allocator); -+ -+ return (allocator->total_num - atomic_read(&allocator->free_num)) * _MALI_OSK_MALI_PAGE_SIZE; -+} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.h b/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.h 2018-05-06 08:49:49.182695581 +0200 -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (C) 2010, 2013, 2015-2016 ARM Limited. All rights reserved. -+ * -+ * 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 __MALI_BLOCK_ALLOCATOR_H__ -+#define __MALI_BLOCK_ALLOCATOR_H__ -+ -+#include "mali_session.h" -+#include "mali_memory.h" -+#include -+ -+#include "mali_memory_types.h" -+ -+#define MALI_BLOCK_SIZE (PAGE_SIZE) /* 4 kB, manage BLOCK memory as page size */ -+#define MALI_BLOCK_REF_MASK (0xFFF) -+#define MALI_BLOCK_MAX_REF_COUNT (0xFFF) -+ -+ -+ -+typedef struct mali_block_allocator { -+ /* -+ * In free list, each node's ref_count is 0, -+ * ref_count added when allocated or referenced in COW -+ */ -+ mali_block_item *items; /* information for each block item*/ -+ struct list_head free; /*free list of mali_memory_node*/ -+ spinlock_t sp_lock; /*lock for reference count & free list opertion*/ -+ u32 total_num; /* Number of total pages*/ -+ atomic_t free_num; /*number of free pages*/ -+} mali_block_allocator; -+ -+unsigned long _mali_blk_item_get_phy_addr(mali_block_item *item); -+unsigned long _mali_blk_item_get_pfn(mali_block_item *item); -+u32 mali_mem_block_get_ref_count(mali_page_node *node); -+u32 mali_mem_block_add_ref(mali_page_node *node); -+u32 mali_mem_block_dec_ref(mali_page_node *node); -+u32 mali_mem_block_release(mali_mem_backend *mem_bkend); -+int mali_mem_block_alloc(mali_mem_block_mem *block_mem, u32 size); -+int mali_mem_block_mali_map(mali_mem_block_mem *block_mem, struct mali_session_data *session, u32 vaddr, u32 props); -+void mali_mem_block_mali_unmap(mali_mem_allocation *alloc); -+ -+int mali_mem_block_cpu_map(mali_mem_backend *mem_bkend, struct vm_area_struct *vma); -+_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size); -+mali_bool mali_memory_have_dedicated_memory(void); -+u32 mali_mem_block_free(mali_mem_block_mem *block_mem); -+u32 mali_mem_block_free_list(struct list_head *list); -+void mali_mem_block_free_node(struct mali_page_node *node); -+void mali_mem_block_allocator_destroy(void); -+_mali_osk_errcode_t mali_mem_block_unref_node(struct mali_page_node *node); -+u32 mali_mem_block_allocator_stat(void); -+ -+#endif /* __MALI_BLOCK_ALLOCATOR_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory.c b/drivers/gpu/arm/mali400/linux/mali_memory.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory.c b/drivers/gpu/arm/mali400/linux/mali_memory.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory.c @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -44190,9 +44841,592 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory.c b/drivers/gpu/arm/mal +} + + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_cow.c b/drivers/gpu/arm/mali400/linux/mali_memory_cow.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_cow.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_cow.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory.h b/drivers/gpu/arm/mali400/linux/mali_memory.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory.h +@@ -0,0 +1,143 @@ ++/* ++ * Copyright (C) 2013-2016 ARM Limited. All rights reserved. ++ * ++ * 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 __MALI_MEMORY_H__ ++#define __MALI_MEMORY_H__ ++ ++#include "mali_osk.h" ++#include "mali_session.h" ++ ++#include ++#include ++ ++#include "mali_memory_types.h" ++#include "mali_memory_os_alloc.h" ++ ++_mali_osk_errcode_t mali_memory_initialize(void); ++void mali_memory_terminate(void); ++ ++/** @brief Allocate a page table page ++ * ++ * Allocate a page for use as a page directory or page table. The page is ++ * mapped into kernel space. ++ * ++ * @return _MALI_OSK_ERR_OK on success, otherwise an error code ++ * @param table_page GPU pointer to the allocated page ++ * @param mapping CPU pointer to the mapping of the allocated page ++ */ ++MALI_STATIC_INLINE _mali_osk_errcode_t ++mali_mmu_get_table_page(mali_dma_addr *table_page, mali_io_address *mapping) ++{ ++ return mali_mem_os_get_table_page(table_page, mapping); ++} ++ ++/** @brief Release a page table page ++ * ++ * Release a page table page allocated through \a mali_mmu_get_table_page ++ * ++ * @param pa the GPU address of the page to release ++ */ ++MALI_STATIC_INLINE void ++mali_mmu_release_table_page(mali_dma_addr phys, void *virt) ++{ ++ mali_mem_os_release_table_page(phys, virt); ++} ++ ++/** @brief mmap function ++ * ++ * mmap syscalls on the Mali device node will end up here. ++ * ++ * This function allocates Mali memory and maps it on CPU and Mali. ++ */ ++int mali_mmap(struct file *filp, struct vm_area_struct *vma); ++ ++/** @brief Start a new memory session ++ * ++ * Called when a process opens the Mali device node. ++ * ++ * @param session Pointer to session to initialize ++ */ ++_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data *session); ++ ++/** @brief Close a memory session ++ * ++ * Called when a process closes the Mali device node. ++ * ++ * Memory allocated by the session will be freed ++ * ++ * @param session Pointer to the session to terminate ++ */ ++void mali_memory_session_end(struct mali_session_data *session); ++ ++/** @brief Prepare Mali page tables for mapping ++ * ++ * This function will prepare the Mali page tables for mapping the memory ++ * described by \a descriptor. ++ * ++ * Page tables will be reference counted and allocated, if not yet present. ++ * ++ * @param descriptor Pointer to the memory descriptor to the mapping ++ */ ++_mali_osk_errcode_t mali_mem_mali_map_prepare(mali_mem_allocation *descriptor); ++ ++/** @brief Resize Mali page tables for mapping ++ * ++ * This function will Resize the Mali page tables for mapping the memory ++ * described by \a descriptor. ++ * ++ * Page tables will be reference counted and allocated, if not yet present. ++ * ++ * @param descriptor Pointer to the memory descriptor to the mapping ++ * @param new_size The new size of descriptor ++ */ ++_mali_osk_errcode_t mali_mem_mali_map_resize(mali_mem_allocation *descriptor, u32 new_size); ++ ++/** @brief Free Mali page tables for mapping ++ * ++ * This function will unmap pages from Mali memory and free the page tables ++ * that are now unused. ++ * ++ * The updated pages in the Mali L2 cache will be invalidated, and the MMU TLBs will be zapped if necessary. ++ * ++ * @param descriptor Pointer to the memory descriptor to unmap ++ */ ++void mali_mem_mali_map_free(struct mali_session_data *session, u32 size, mali_address_t vaddr, u32 flags); ++ ++/** @brief Parse resource and prepare the OS memory allocator ++ * ++ * @param size Maximum size to allocate for Mali GPU. ++ * @return _MALI_OSK_ERR_OK on success, otherwise failure. ++ */ ++_mali_osk_errcode_t mali_memory_core_resource_os_memory(u32 size); ++ ++/** @brief Parse resource and prepare the dedicated memory allocator ++ * ++ * @param start Physical start address of dedicated Mali GPU memory. ++ * @param size Size of dedicated Mali GPU memory. ++ * @return _MALI_OSK_ERR_OK on success, otherwise failure. ++ */ ++_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size); ++ ++ ++struct mali_page_node *_mali_page_node_allocate(mali_page_node_type type); ++ ++void _mali_page_node_ref(struct mali_page_node *node); ++void _mali_page_node_unref(struct mali_page_node *node); ++void _mali_page_node_add_page(struct mali_page_node *node, struct page *page); ++ ++void _mali_page_node_add_block_item(struct mali_page_node *node, mali_block_item *item); ++ ++void _mali_page_node_add_swap_item(struct mali_page_node *node, struct mali_swap_item *item); ++ ++int _mali_page_node_get_ref_count(struct mali_page_node *node); ++dma_addr_t _mali_page_node_get_dma_addr(struct mali_page_node *node); ++unsigned long _mali_page_node_get_pfn(struct mali_page_node *node); ++ ++#endif /* __MALI_MEMORY_H__ */ +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.c b/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.c +@@ -0,0 +1,362 @@ ++/* ++ * Copyright (C) 2010-2016 ARM Limited. All rights reserved. ++ * ++ * 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. ++ */ ++ ++#include "mali_kernel_common.h" ++#include "mali_memory.h" ++#include "mali_memory_block_alloc.h" ++#include "mali_osk.h" ++#include ++ ++ ++static mali_block_allocator *mali_mem_block_gobal_allocator = NULL; ++ ++unsigned long _mali_blk_item_get_phy_addr(mali_block_item *item) ++{ ++ return (item->phy_addr & ~(MALI_BLOCK_REF_MASK)); ++} ++ ++ ++unsigned long _mali_blk_item_get_pfn(mali_block_item *item) ++{ ++ return (item->phy_addr / MALI_BLOCK_SIZE); ++} ++ ++ ++u32 mali_mem_block_get_ref_count(mali_page_node *node) ++{ ++ MALI_DEBUG_ASSERT(node->type == MALI_PAGE_NODE_BLOCK); ++ return (node->blk_it->phy_addr & MALI_BLOCK_REF_MASK); ++} ++ ++ ++/* Increase the refence count ++* It not atomic, so it need to get sp_lock before call this function ++*/ ++ ++u32 mali_mem_block_add_ref(mali_page_node *node) ++{ ++ MALI_DEBUG_ASSERT(node->type == MALI_PAGE_NODE_BLOCK); ++ MALI_DEBUG_ASSERT(mali_mem_block_get_ref_count(node) < MALI_BLOCK_MAX_REF_COUNT); ++ return (node->blk_it->phy_addr++ & MALI_BLOCK_REF_MASK); ++} ++ ++/* Decase the refence count ++* It not atomic, so it need to get sp_lock before call this function ++*/ ++u32 mali_mem_block_dec_ref(mali_page_node *node) ++{ ++ MALI_DEBUG_ASSERT(node->type == MALI_PAGE_NODE_BLOCK); ++ MALI_DEBUG_ASSERT(mali_mem_block_get_ref_count(node) > 0); ++ return (node->blk_it->phy_addr-- & MALI_BLOCK_REF_MASK); ++} ++ ++ ++static mali_block_allocator *mali_mem_block_allocator_create(u32 base_address, u32 size) ++{ ++ mali_block_allocator *info; ++ u32 usable_size; ++ u32 num_blocks; ++ mali_page_node *m_node; ++ mali_block_item *mali_blk_items = NULL; ++ int i = 0; ++ ++ usable_size = size & ~(MALI_BLOCK_SIZE - 1); ++ MALI_DEBUG_PRINT(3, ("Mali block allocator create for region starting at 0x%08X length 0x%08X\n", base_address, size)); ++ MALI_DEBUG_PRINT(4, ("%d usable bytes\n", usable_size)); ++ num_blocks = usable_size / MALI_BLOCK_SIZE; ++ MALI_DEBUG_PRINT(4, ("which becomes %d blocks\n", num_blocks)); ++ ++ if (usable_size == 0) { ++ MALI_DEBUG_PRINT(1, ("Memory block of size %d is unusable\n", size)); ++ return NULL; ++ } ++ ++ info = _mali_osk_calloc(1, sizeof(mali_block_allocator)); ++ if (NULL != info) { ++ INIT_LIST_HEAD(&info->free); ++ spin_lock_init(&info->sp_lock); ++ info->total_num = num_blocks; ++ mali_blk_items = _mali_osk_calloc(1, sizeof(mali_block_item) * num_blocks); ++ ++ if (mali_blk_items) { ++ info->items = mali_blk_items; ++ /* add blocks(4k size) to free list*/ ++ for (i = 0 ; i < num_blocks ; i++) { ++ /* add block information*/ ++ mali_blk_items[i].phy_addr = base_address + (i * MALI_BLOCK_SIZE); ++ /* add to free list */ ++ m_node = _mali_page_node_allocate(MALI_PAGE_NODE_BLOCK); ++ if (m_node == NULL) ++ goto fail; ++ _mali_page_node_add_block_item(m_node, &(mali_blk_items[i])); ++ list_add_tail(&m_node->list, &info->free); ++ atomic_add(1, &info->free_num); ++ } ++ return info; ++ } ++ } ++fail: ++ mali_mem_block_allocator_destroy(); ++ return NULL; ++} ++ ++void mali_mem_block_allocator_destroy(void) ++{ ++ struct mali_page_node *m_page, *m_tmp; ++ mali_block_allocator *info = mali_mem_block_gobal_allocator; ++ MALI_DEBUG_ASSERT_POINTER(info); ++ MALI_DEBUG_PRINT(4, ("Memory block destroy !\n")); ++ ++ if (NULL == info) ++ return; ++ ++ list_for_each_entry_safe(m_page, m_tmp , &info->free, list) { ++ MALI_DEBUG_ASSERT(m_page->type == MALI_PAGE_NODE_BLOCK); ++ list_del(&m_page->list); ++ kfree(m_page); ++ } ++ ++ _mali_osk_free(info->items); ++ _mali_osk_free(info); ++} ++ ++u32 mali_mem_block_release(mali_mem_backend *mem_bkend) ++{ ++ mali_mem_allocation *alloc = mem_bkend->mali_allocation; ++ u32 free_pages_nr = 0; ++ MALI_DEBUG_ASSERT(mem_bkend->type == MALI_MEM_BLOCK); ++ ++ /* Unmap the memory from the mali virtual address space. */ ++ mali_mem_block_mali_unmap(alloc); ++ mutex_lock(&mem_bkend->mutex); ++ free_pages_nr = mali_mem_block_free(&mem_bkend->block_mem); ++ mutex_unlock(&mem_bkend->mutex); ++ return free_pages_nr; ++} ++ ++ ++int mali_mem_block_alloc(mali_mem_block_mem *block_mem, u32 size) ++{ ++ struct mali_page_node *m_page, *m_tmp; ++ size_t page_count = PAGE_ALIGN(size) / _MALI_OSK_MALI_PAGE_SIZE; ++ mali_block_allocator *info = mali_mem_block_gobal_allocator; ++ MALI_DEBUG_ASSERT_POINTER(info); ++ ++ MALI_DEBUG_PRINT(4, ("BLOCK Mem: Allocate size = 0x%x\n", size)); ++ /*do some init */ ++ INIT_LIST_HEAD(&block_mem->pfns); ++ ++ spin_lock(&info->sp_lock); ++ /*check if have enough space*/ ++ if (atomic_read(&info->free_num) > page_count) { ++ list_for_each_entry_safe(m_page, m_tmp , &info->free, list) { ++ if (page_count > 0) { ++ MALI_DEBUG_ASSERT(m_page->type == MALI_PAGE_NODE_BLOCK); ++ MALI_DEBUG_ASSERT(mali_mem_block_get_ref_count(m_page) == 0); ++ list_move(&m_page->list, &block_mem->pfns); ++ block_mem->count++; ++ atomic_dec(&info->free_num); ++ _mali_page_node_ref(m_page); ++ } else { ++ break; ++ } ++ page_count--; ++ } ++ } else { ++ /* can't allocate from BLOCK memory*/ ++ spin_unlock(&info->sp_lock); ++ return -1; ++ } ++ ++ spin_unlock(&info->sp_lock); ++ return 0; ++} ++ ++u32 mali_mem_block_free(mali_mem_block_mem *block_mem) ++{ ++ u32 free_pages_nr = 0; ++ ++ free_pages_nr = mali_mem_block_free_list(&block_mem->pfns); ++ MALI_DEBUG_PRINT(4, ("BLOCK Mem free : allocated size = 0x%x, free size = 0x%x\n", block_mem->count * _MALI_OSK_MALI_PAGE_SIZE, ++ free_pages_nr * _MALI_OSK_MALI_PAGE_SIZE)); ++ block_mem->count = 0; ++ MALI_DEBUG_ASSERT(list_empty(&block_mem->pfns)); ++ ++ return free_pages_nr; ++} ++ ++ ++u32 mali_mem_block_free_list(struct list_head *list) ++{ ++ struct mali_page_node *m_page, *m_tmp; ++ mali_block_allocator *info = mali_mem_block_gobal_allocator; ++ u32 free_pages_nr = 0; ++ ++ if (info) { ++ spin_lock(&info->sp_lock); ++ list_for_each_entry_safe(m_page, m_tmp , list, list) { ++ if (1 == _mali_page_node_get_ref_count(m_page)) { ++ free_pages_nr++; ++ } ++ mali_mem_block_free_node(m_page); ++ } ++ spin_unlock(&info->sp_lock); ++ } ++ return free_pages_nr; ++} ++ ++/* free the node,*/ ++void mali_mem_block_free_node(struct mali_page_node *node) ++{ ++ mali_block_allocator *info = mali_mem_block_gobal_allocator; ++ ++ /* only handle BLOCK node */ ++ if (node->type == MALI_PAGE_NODE_BLOCK && info) { ++ /*Need to make this atomic?*/ ++ if (1 == _mali_page_node_get_ref_count(node)) { ++ /*Move to free list*/ ++ _mali_page_node_unref(node); ++ list_move_tail(&node->list, &info->free); ++ atomic_add(1, &info->free_num); ++ } else { ++ _mali_page_node_unref(node); ++ list_del(&node->list); ++ kfree(node); ++ } ++ } ++} ++ ++/* unref the node, but not free it */ ++_mali_osk_errcode_t mali_mem_block_unref_node(struct mali_page_node *node) ++{ ++ mali_block_allocator *info = mali_mem_block_gobal_allocator; ++ mali_page_node *new_node; ++ ++ /* only handle BLOCK node */ ++ if (node->type == MALI_PAGE_NODE_BLOCK && info) { ++ /*Need to make this atomic?*/ ++ if (1 == _mali_page_node_get_ref_count(node)) { ++ /* allocate a new node, Add to free list, keep the old node*/ ++ _mali_page_node_unref(node); ++ new_node = _mali_page_node_allocate(MALI_PAGE_NODE_BLOCK); ++ if (new_node) { ++ memcpy(new_node, node, sizeof(mali_page_node)); ++ list_add(&new_node->list, &info->free); ++ atomic_add(1, &info->free_num); ++ } else ++ return _MALI_OSK_ERR_FAULT; ++ ++ } else { ++ _mali_page_node_unref(node); ++ } ++ } ++ return _MALI_OSK_ERR_OK; ++} ++ ++ ++int mali_mem_block_mali_map(mali_mem_block_mem *block_mem, struct mali_session_data *session, u32 vaddr, u32 props) ++{ ++ struct mali_page_directory *pagedir = session->page_directory; ++ struct mali_page_node *m_page; ++ dma_addr_t phys; ++ u32 virt = vaddr; ++ u32 prop = props; ++ ++ list_for_each_entry(m_page, &block_mem->pfns, list) { ++ MALI_DEBUG_ASSERT(m_page->type == MALI_PAGE_NODE_BLOCK); ++ phys = _mali_page_node_get_dma_addr(m_page); ++#if defined(CONFIG_ARCH_DMA_ADDR_T_64BIT) ++ /* Verify that the "physical" address is 32-bit and ++ * usable for Mali, when on a system with bus addresses ++ * wider than 32-bit. */ ++ MALI_DEBUG_ASSERT(0 == (phys >> 32)); ++#endif ++ mali_mmu_pagedir_update(pagedir, virt, (mali_dma_addr)phys, MALI_MMU_PAGE_SIZE, prop); ++ virt += MALI_MMU_PAGE_SIZE; ++ } ++ ++ return 0; ++} ++ ++void mali_mem_block_mali_unmap(mali_mem_allocation *alloc) ++{ ++ struct mali_session_data *session; ++ MALI_DEBUG_ASSERT_POINTER(alloc); ++ session = alloc->session; ++ MALI_DEBUG_ASSERT_POINTER(session); ++ ++ mali_session_memory_lock(session); ++ mali_mem_mali_map_free(session, alloc->psize, alloc->mali_vma_node.vm_node.start, ++ alloc->flags); ++ mali_session_memory_unlock(session); ++} ++ ++ ++int mali_mem_block_cpu_map(mali_mem_backend *mem_bkend, struct vm_area_struct *vma) ++{ ++ int ret; ++ mali_mem_block_mem *block_mem = &mem_bkend->block_mem; ++ unsigned long addr = vma->vm_start; ++ struct mali_page_node *m_page; ++ MALI_DEBUG_ASSERT(mem_bkend->type == MALI_MEM_BLOCK); ++ ++ list_for_each_entry(m_page, &block_mem->pfns, list) { ++ MALI_DEBUG_ASSERT(m_page->type == MALI_PAGE_NODE_BLOCK); ++ ret = vm_insert_pfn(vma, addr, _mali_page_node_get_pfn(m_page)); ++ ++ if (unlikely(0 != ret)) { ++ return -EFAULT; ++ } ++ addr += _MALI_OSK_MALI_PAGE_SIZE; ++ ++ } ++ ++ return 0; ++} ++ ++ ++_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size) ++{ ++ mali_block_allocator *allocator; ++ ++ /* Do the low level linux operation first */ ++ ++ /* Request ownership of the memory */ ++ if (_MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(start, size, "Dedicated Mali GPU memory")) { ++ MALI_DEBUG_PRINT(1, ("Failed to request memory region for frame buffer (0x%08X - 0x%08X)\n", start, start + size - 1)); ++ return _MALI_OSK_ERR_FAULT; ++ } ++ ++ /* Create generic block allocator object to handle it */ ++ allocator = mali_mem_block_allocator_create(start, size); ++ ++ if (NULL == allocator) { ++ MALI_DEBUG_PRINT(1, ("Memory bank registration failed\n")); ++ _mali_osk_mem_unreqregion(start, size); ++ MALI_ERROR(_MALI_OSK_ERR_FAULT); ++ } ++ ++ mali_mem_block_gobal_allocator = (mali_block_allocator *)allocator; ++ ++ return _MALI_OSK_ERR_OK; ++} ++ ++mali_bool mali_memory_have_dedicated_memory(void) ++{ ++ return mali_mem_block_gobal_allocator ? MALI_TRUE : MALI_FALSE; ++} ++ ++u32 mali_mem_block_allocator_stat(void) ++{ ++ mali_block_allocator *allocator = mali_mem_block_gobal_allocator; ++ MALI_DEBUG_ASSERT_POINTER(allocator); ++ ++ return (allocator->total_num - atomic_read(&allocator->free_num)) * _MALI_OSK_MALI_PAGE_SIZE; ++} +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.h b/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_block_alloc.h +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (C) 2010, 2013, 2015-2016 ARM Limited. All rights reserved. ++ * ++ * 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 __MALI_BLOCK_ALLOCATOR_H__ ++#define __MALI_BLOCK_ALLOCATOR_H__ ++ ++#include "mali_session.h" ++#include "mali_memory.h" ++#include ++ ++#include "mali_memory_types.h" ++ ++#define MALI_BLOCK_SIZE (PAGE_SIZE) /* 4 kB, manage BLOCK memory as page size */ ++#define MALI_BLOCK_REF_MASK (0xFFF) ++#define MALI_BLOCK_MAX_REF_COUNT (0xFFF) ++ ++ ++ ++typedef struct mali_block_allocator { ++ /* ++ * In free list, each node's ref_count is 0, ++ * ref_count added when allocated or referenced in COW ++ */ ++ mali_block_item *items; /* information for each block item*/ ++ struct list_head free; /*free list of mali_memory_node*/ ++ spinlock_t sp_lock; /*lock for reference count & free list opertion*/ ++ u32 total_num; /* Number of total pages*/ ++ atomic_t free_num; /*number of free pages*/ ++} mali_block_allocator; ++ ++unsigned long _mali_blk_item_get_phy_addr(mali_block_item *item); ++unsigned long _mali_blk_item_get_pfn(mali_block_item *item); ++u32 mali_mem_block_get_ref_count(mali_page_node *node); ++u32 mali_mem_block_add_ref(mali_page_node *node); ++u32 mali_mem_block_dec_ref(mali_page_node *node); ++u32 mali_mem_block_release(mali_mem_backend *mem_bkend); ++int mali_mem_block_alloc(mali_mem_block_mem *block_mem, u32 size); ++int mali_mem_block_mali_map(mali_mem_block_mem *block_mem, struct mali_session_data *session, u32 vaddr, u32 props); ++void mali_mem_block_mali_unmap(mali_mem_allocation *alloc); ++ ++int mali_mem_block_cpu_map(mali_mem_backend *mem_bkend, struct vm_area_struct *vma); ++_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size); ++mali_bool mali_memory_have_dedicated_memory(void); ++u32 mali_mem_block_free(mali_mem_block_mem *block_mem); ++u32 mali_mem_block_free_list(struct list_head *list); ++void mali_mem_block_free_node(struct mali_page_node *node); ++void mali_mem_block_allocator_destroy(void); ++_mali_osk_errcode_t mali_mem_block_unref_node(struct mali_page_node *node); ++u32 mali_mem_block_allocator_stat(void); ++ ++#endif /* __MALI_BLOCK_ALLOCATOR_H__ */ +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_cow.c b/drivers/gpu/arm/mali400/linux/mali_memory_cow.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_cow.c @@ -0,0 +1,776 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -44970,9 +46204,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_cow.c b/drivers/gpu/arm + _mali_osk_mutex_signal(session->memory_lock); + return _MALI_OSK_ERR_OK; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_cow.h b/drivers/gpu/arm/mali400/linux/mali_memory_cow.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_cow.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_cow.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_cow.h b/drivers/gpu/arm/mali400/linux/mali_memory_cow.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_cow.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -45022,9 +46258,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_cow.h b/drivers/gpu/arm +_mali_osk_errcode_t mali_mem_cow_allocate_on_demand(mali_mem_backend *mem_bkend, u32 offset_page); +#endif + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.c b/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.c b/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.c @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -45288,9 +46526,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.c b/drivers/ + } +} + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.h b/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.h b/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -45356,9 +46596,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_defer_bind.h b/drivers/ +void mali_mem_defer_dmem_free(struct mali_gp_job *gp); + +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.c b/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.c b/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.c @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -45729,9 +46971,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.c b/drivers/gpu + + _mali_osk_free(mem); +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.h b/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.h b/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -45786,9 +47030,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_dma_buf.h b/drivers/gpu +#endif + +#endif /* __MALI_MEMORY_DMA_BUF_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_external.c b/drivers/gpu/arm/mali400/linux/mali_memory_external.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_external.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_external.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_external.c b/drivers/gpu/arm/mali400/linux/mali_memory_external.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_external.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -45879,9 +47125,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_external.c b/drivers/gp + MALI_SUCCESS; +} + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_external.h b/drivers/gpu/arm/mali400/linux/mali_memory_external.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_external.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_external.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_external.h b/drivers/gpu/arm/mali400/linux/mali_memory_external.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_external.h @@ -0,0 +1,29 @@ + +/* @@ -45912,156 +47160,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_external.h b/drivers/gp +#endif + +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory.h b/drivers/gpu/arm/mali400/linux/mali_memory.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory.h 2018-05-06 08:49:49.182695581 +0200 -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (C) 2013-2016 ARM Limited. All rights reserved. -+ * -+ * 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 __MALI_MEMORY_H__ -+#define __MALI_MEMORY_H__ -+ -+#include "mali_osk.h" -+#include "mali_session.h" -+ -+#include -+#include -+ -+#include "mali_memory_types.h" -+#include "mali_memory_os_alloc.h" -+ -+_mali_osk_errcode_t mali_memory_initialize(void); -+void mali_memory_terminate(void); -+ -+/** @brief Allocate a page table page -+ * -+ * Allocate a page for use as a page directory or page table. The page is -+ * mapped into kernel space. -+ * -+ * @return _MALI_OSK_ERR_OK on success, otherwise an error code -+ * @param table_page GPU pointer to the allocated page -+ * @param mapping CPU pointer to the mapping of the allocated page -+ */ -+MALI_STATIC_INLINE _mali_osk_errcode_t -+mali_mmu_get_table_page(mali_dma_addr *table_page, mali_io_address *mapping) -+{ -+ return mali_mem_os_get_table_page(table_page, mapping); -+} -+ -+/** @brief Release a page table page -+ * -+ * Release a page table page allocated through \a mali_mmu_get_table_page -+ * -+ * @param pa the GPU address of the page to release -+ */ -+MALI_STATIC_INLINE void -+mali_mmu_release_table_page(mali_dma_addr phys, void *virt) -+{ -+ mali_mem_os_release_table_page(phys, virt); -+} -+ -+/** @brief mmap function -+ * -+ * mmap syscalls on the Mali device node will end up here. -+ * -+ * This function allocates Mali memory and maps it on CPU and Mali. -+ */ -+int mali_mmap(struct file *filp, struct vm_area_struct *vma); -+ -+/** @brief Start a new memory session -+ * -+ * Called when a process opens the Mali device node. -+ * -+ * @param session Pointer to session to initialize -+ */ -+_mali_osk_errcode_t mali_memory_session_begin(struct mali_session_data *session); -+ -+/** @brief Close a memory session -+ * -+ * Called when a process closes the Mali device node. -+ * -+ * Memory allocated by the session will be freed -+ * -+ * @param session Pointer to the session to terminate -+ */ -+void mali_memory_session_end(struct mali_session_data *session); -+ -+/** @brief Prepare Mali page tables for mapping -+ * -+ * This function will prepare the Mali page tables for mapping the memory -+ * described by \a descriptor. -+ * -+ * Page tables will be reference counted and allocated, if not yet present. -+ * -+ * @param descriptor Pointer to the memory descriptor to the mapping -+ */ -+_mali_osk_errcode_t mali_mem_mali_map_prepare(mali_mem_allocation *descriptor); -+ -+/** @brief Resize Mali page tables for mapping -+ * -+ * This function will Resize the Mali page tables for mapping the memory -+ * described by \a descriptor. -+ * -+ * Page tables will be reference counted and allocated, if not yet present. -+ * -+ * @param descriptor Pointer to the memory descriptor to the mapping -+ * @param new_size The new size of descriptor -+ */ -+_mali_osk_errcode_t mali_mem_mali_map_resize(mali_mem_allocation *descriptor, u32 new_size); -+ -+/** @brief Free Mali page tables for mapping -+ * -+ * This function will unmap pages from Mali memory and free the page tables -+ * that are now unused. -+ * -+ * The updated pages in the Mali L2 cache will be invalidated, and the MMU TLBs will be zapped if necessary. -+ * -+ * @param descriptor Pointer to the memory descriptor to unmap -+ */ -+void mali_mem_mali_map_free(struct mali_session_data *session, u32 size, mali_address_t vaddr, u32 flags); -+ -+/** @brief Parse resource and prepare the OS memory allocator -+ * -+ * @param size Maximum size to allocate for Mali GPU. -+ * @return _MALI_OSK_ERR_OK on success, otherwise failure. -+ */ -+_mali_osk_errcode_t mali_memory_core_resource_os_memory(u32 size); -+ -+/** @brief Parse resource and prepare the dedicated memory allocator -+ * -+ * @param start Physical start address of dedicated Mali GPU memory. -+ * @param size Size of dedicated Mali GPU memory. -+ * @return _MALI_OSK_ERR_OK on success, otherwise failure. -+ */ -+_mali_osk_errcode_t mali_memory_core_resource_dedicated_memory(u32 start, u32 size); -+ -+ -+struct mali_page_node *_mali_page_node_allocate(mali_page_node_type type); -+ -+void _mali_page_node_ref(struct mali_page_node *node); -+void _mali_page_node_unref(struct mali_page_node *node); -+void _mali_page_node_add_page(struct mali_page_node *node, struct page *page); -+ -+void _mali_page_node_add_block_item(struct mali_page_node *node, mali_block_item *item); -+ -+void _mali_page_node_add_swap_item(struct mali_page_node *node, struct mali_swap_item *item); -+ -+int _mali_page_node_get_ref_count(struct mali_page_node *node); -+dma_addr_t _mali_page_node_get_dma_addr(struct mali_page_node *node); -+unsigned long _mali_page_node_get_pfn(struct mali_page_node *node); -+ -+#endif /* __MALI_MEMORY_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_manager.c b/drivers/gpu/arm/mali400/linux/mali_memory_manager.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_manager.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_manager.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_manager.c b/drivers/gpu/arm/mali400/linux/mali_memory_manager.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_manager.c @@ -0,0 +1,993 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -47056,9 +48159,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_manager.c b/drivers/gpu + } + return _MALI_OSK_ERR_OK; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_manager.h b/drivers/gpu/arm/mali400/linux/mali_memory_manager.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_manager.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_manager.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_manager.h b/drivers/gpu/arm/mali400/linux/mali_memory_manager.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_manager.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -47111,9 +48216,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_manager.h b/drivers/gpu + +#endif + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.c b/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.c b/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.c @@ -0,0 +1,812 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -47927,9 +49034,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.c b/drivers/gp +{ + return atomic_read(&mali_mem_os_allocator.allocated_pages) * _MALI_OSK_MALI_PAGE_SIZE; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.h b/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.h b/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -47985,9 +49094,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_os_alloc.h b/drivers/gp +_mali_osk_errcode_t mali_mem_os_resize_cpu_map_locked(mali_mem_backend *mem_bkend, struct vm_area_struct *vma, unsigned long start_vaddr, u32 mappig_size); + +#endif /* __MALI_MEMORY_OS_ALLOC_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_secure.c b/drivers/gpu/arm/mali400/linux/mali_memory_secure.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_secure.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_secure.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_secure.c b/drivers/gpu/arm/mali400/linux/mali_memory_secure.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_secure.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -48158,9 +49269,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_secure.c b/drivers/gpu/ +} + + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_secure.h b/drivers/gpu/arm/mali400/linux/mali_memory_secure.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_secure.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_secure.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_secure.h b/drivers/gpu/arm/mali400/linux/mali_memory_secure.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_secure.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2010, 2013, 2015-2016 ARM Limited. All rights reserved. @@ -48192,9 +49305,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_secure.h b/drivers/gpu/ +u32 mali_mem_secure_release(mali_mem_backend *mem_bkend); + +#endif /* __MALI_MEMORY_SECURE_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.c b/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.c b/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.c @@ -0,0 +1,942 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -49138,9 +50253,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.c b/drivers/ + *unlock_size = mem_backend_swapped_unlock_size; +} +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.h b/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.h b/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -49263,9 +50380,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_swap_alloc.h b/drivers/ +#endif +#endif /* __MALI_MEMORY_SWAP_ALLOC_H__ */ + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_types.h b/drivers/gpu/arm/mali400/linux/mali_memory_types.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_types.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_types.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_types.h b/drivers/gpu/arm/mali400/linux/mali_memory_types.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_types.h @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -49486,9 +50605,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_types.h b/drivers/gpu/a +#define MALI_MEM_FLAG_DONT_CPU_MAP (1 << 1) +#define MALI_MEM_FLAG_CAN_RESIZE (_MALI_MEMORY_ALLOCATE_RESIZEABLE) +#endif /* __MALI_MEMORY_TYPES__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_ump.c b/drivers/gpu/arm/mali400/linux/mali_memory_ump.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_ump.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_ump.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_ump.c b/drivers/gpu/arm/mali400/linux/mali_memory_ump.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_ump.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -49644,9 +50765,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_ump.c b/drivers/gpu/arm + ump_dd_reference_release(ump_mem); +} + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_ump.h b/drivers/gpu/arm/mali400/linux/mali_memory_ump.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_ump.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_ump.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_ump.h b/drivers/gpu/arm/mali400/linux/mali_memory_ump.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_ump.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011-2016 ARM Limited. All rights reserved. @@ -49677,9 +50800,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_ump.h b/drivers/gpu/arm +#endif + +#endif /* __MALI_MEMORY_DMA_BUF_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_util.c b/drivers/gpu/arm/mali400/linux/mali_memory_util.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_util.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_util.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_util.c b/drivers/gpu/arm/mali400/linux/mali_memory_util.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_util.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -49839,9 +50964,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_util.c b/drivers/gpu/ar + mali_allocation_unref(&entry); + } +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_util.h b/drivers/gpu/arm/mali400/linux/mali_memory_util.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_util.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_util.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_util.h b/drivers/gpu/arm/mali400/linux/mali_memory_util.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_util.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -49863,9 +50990,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_util.h b/drivers/gpu/ar +void mali_free_session_allocations(struct mali_session_data *session); + +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_virtual.c b/drivers/gpu/arm/mali400/linux/mali_memory_virtual.c ---- a/drivers/gpu/arm/mali400/linux/mali_memory_virtual.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_virtual.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_virtual.c b/drivers/gpu/arm/mali400/linux/mali_memory_virtual.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_virtual.c @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2013-2016 ARM Limited. All rights reserved. @@ -49994,9 +51123,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_virtual.c b/drivers/gpu + return best; +} + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_virtual.h b/drivers/gpu/arm/mali400/linux/mali_memory_virtual.h ---- a/drivers/gpu/arm/mali400/linux/mali_memory_virtual.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_memory_virtual.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_memory_virtual.h b/drivers/gpu/arm/mali400/linux/mali_memory_virtual.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_memory_virtual.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013-2014, 2016 ARM Limited. All rights reserved. @@ -50033,9 +51164,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_memory_virtual.h b/drivers/gpu + unsigned long start, unsigned long pages); + +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_atomics.c b/drivers/gpu/arm/mali400/linux/mali_osk_atomics.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_atomics.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_atomics.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_atomics.c b/drivers/gpu/arm/mali400/linux/mali_osk_atomics.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_atomics.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010, 2013-2014, 2016 ARM Limited. All rights reserved. @@ -50096,9 +51229,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_atomics.c b/drivers/gpu/ar +{ + return atomic_xchg((atomic_t *)&atom->u.val, val); +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_bitmap.c b/drivers/gpu/arm/mali400/linux/mali_osk_bitmap.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_bitmap.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_bitmap.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_bitmap.c b/drivers/gpu/arm/mali400/linux/mali_osk_bitmap.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_bitmap.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2010, 2013-2016 ARM Limited. All rights reserved. @@ -50252,9 +51387,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_bitmap.c b/drivers/gpu/arm + } +} + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_irq.c b/drivers/gpu/arm/mali400/linux/mali_osk_irq.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_irq.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_irq.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_irq.c b/drivers/gpu/arm/mali400/linux/mali_osk_irq.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_irq.c @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -50456,9 +51593,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_irq.c b/drivers/gpu/arm/ma + + return ret; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_locks.c b/drivers/gpu/arm/mali400/linux/mali_osk_locks.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_locks.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_locks.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_locks.c b/drivers/gpu/arm/mali400/linux/mali_osk_locks.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_locks.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -50747,9 +51886,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_locks.c b/drivers/gpu/arm/ +} +#endif /* LOCK_ORDER_CHECKING */ +#endif /* DEBUG */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_locks.h b/drivers/gpu/arm/mali400/linux/mali_osk_locks.h ---- a/drivers/gpu/arm/mali400/linux/mali_osk_locks.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_locks.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_locks.h b/drivers/gpu/arm/mali400/linux/mali_osk_locks.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_locks.h @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -51077,9 +52218,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_locks.h b/drivers/gpu/arm/ +#endif + +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_low_level_mem.c b/drivers/gpu/arm/mali400/linux/mali_osk_low_level_mem.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_low_level_mem.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_low_level_mem.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_low_level_mem.c b/drivers/gpu/arm/mali400/linux/mali_osk_low_level_mem.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_low_level_mem.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -51227,9 +52370,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_low_level_mem.c b/drivers/ + args->size = _mali_osk_mem_write_safe(dst, src, args->size); + return _MALI_OSK_ERR_OK; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_mali.c b/drivers/gpu/arm/mali400/linux/mali_osk_mali.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_mali.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_mali.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_mali.c b/drivers/gpu/arm/mali400/linux/mali_osk_mali.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_mali.c @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -51722,9 +52867,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_mali.c b/drivers/gpu/arm/m +} + + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_math.c b/drivers/gpu/arm/mali400/linux/mali_osk_math.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_math.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_math.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_math.c b/drivers/gpu/arm/mali400/linux/mali_osk_math.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_math.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010, 2013-2014, 2016 ARM Limited. All rights reserved. @@ -51753,9 +52900,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_math.c b/drivers/gpu/arm/m +{ + return fls(input); +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_memory.c b/drivers/gpu/arm/mali400/linux/mali_osk_memory.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_memory.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_memory.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_memory.c b/drivers/gpu/arm/mali400/linux/mali_osk_memory.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_memory.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010-2011, 2013-2014, 2016 ARM Limited. All rights reserved. @@ -51818,9 +52967,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_memory.c b/drivers/gpu/arm + */ + return MALI_TRUE; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_misc.c b/drivers/gpu/arm/mali400/linux/mali_osk_misc.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_misc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_misc.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_misc.c b/drivers/gpu/arm/mali400/linux/mali_osk_misc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_misc.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -51903,9 +53054,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_misc.c b/drivers/gpu/arm/m + + return tid; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_notification.c b/drivers/gpu/arm/mali400/linux/mali_osk_notification.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_notification.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_notification.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_notification.c b/drivers/gpu/arm/mali400/linux/mali_osk_notification.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_notification.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -52089,9 +53242,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_notification.c b/drivers/g + + return _MALI_OSK_ERR_OK; /* all ok */ +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_pm.c b/drivers/gpu/arm/mali400/linux/mali_osk_pm.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_pm.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_pm.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_pm.c b/drivers/gpu/arm/mali400/linux/mali_osk_pm.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_pm.c @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -52176,9 +53331,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_pm.c b/drivers/gpu/arm/mal + pm_runtime_barrier(&(mali_platform_device->dev)); +#endif +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_profiling.c b/drivers/gpu/arm/mali400/linux/mali_osk_profiling.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_profiling.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_profiling.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_profiling.c b/drivers/gpu/arm/mali400/linux/mali_osk_profiling.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_profiling.c @@ -0,0 +1,1282 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -53462,9 +54619,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_profiling.c b/drivers/gpu/ +EXPORT_SYMBOL(_mali_profiling_control); +EXPORT_SYMBOL(_mali_profiling_get_api_version); +EXPORT_SYMBOL(_mali_profiling_get_mali_version); -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_specific.h b/drivers/gpu/arm/mali400/linux/mali_osk_specific.h ---- a/drivers/gpu/arm/mali400/linux/mali_osk_specific.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_specific.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_specific.h b/drivers/gpu/arm/mali400/linux/mali_osk_specific.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_specific.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010, 2012-2014, 2016 ARM Limited. All rights reserved. @@ -53538,9 +54697,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_specific.h b/drivers/gpu/a +#define _mali_osk_put_user(x, ptr) put_user(x, ptr) + +#endif /* __MALI_OSK_SPECIFIC_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_time.c b/drivers/gpu/arm/mali400/linux/mali_osk_time.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_time.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_time.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_time.c b/drivers/gpu/arm/mali400/linux/mali_osk_time.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_time.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010, 2013-2014, 2016 ARM Limited. All rights reserved. @@ -53601,9 +54762,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_time.c b/drivers/gpu/arm/m + get_monotonic_boottime(&tsval); + return (u64)timespec_to_ns(&tsval); +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_timers.c b/drivers/gpu/arm/mali400/linux/mali_osk_timers.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_timers.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_timers.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_timers.c b/drivers/gpu/arm/mali400/linux/mali_osk_timers.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_timers.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -53681,9 +54844,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_timers.c b/drivers/gpu/arm + MALI_DEBUG_ASSERT_POINTER(tim); + kfree(tim); +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_wait_queue.c b/drivers/gpu/arm/mali400/linux/mali_osk_wait_queue.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_wait_queue.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_wait_queue.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_wait_queue.c b/drivers/gpu/arm/mali400/linux/mali_osk_wait_queue.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_wait_queue.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012-2014, 2016 ARM Limited. All rights reserved. @@ -53763,9 +54928,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_wait_queue.c b/drivers/gpu + /* Linux requires no explicit termination of wait queues */ + kfree(queue); +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_wq.c b/drivers/gpu/arm/mali400/linux/mali_osk_wq.c ---- a/drivers/gpu/arm/mali400/linux/mali_osk_wq.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_osk_wq.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_osk_wq.c b/drivers/gpu/arm/mali400/linux/mali_osk_wq.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_osk_wq.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2010-2014, 2016 ARM Limited. All rights reserved. @@ -54007,9 +55174,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_osk_wq.c b/drivers/gpu/arm/mal +#endif + +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_pmu_power_up_down.c b/drivers/gpu/arm/mali400/linux/mali_pmu_power_up_down.c ---- a/drivers/gpu/arm/mali400/linux/mali_pmu_power_up_down.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_pmu_power_up_down.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_pmu_power_up_down.c b/drivers/gpu/arm/mali400/linux/mali_pmu_power_up_down.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_pmu_power_up_down.c @@ -0,0 +1,23 @@ +/** + * Copyright (C) 2010, 2012-2014, 2016 ARM Limited. All rights reserved. @@ -54034,9 +55203,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_pmu_power_up_down.c b/drivers/ +} + +EXPORT_SYMBOL(mali_perf_set_num_pp_cores); -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_profiling_events.h b/drivers/gpu/arm/mali400/linux/mali_profiling_events.h ---- a/drivers/gpu/arm/mali400/linux/mali_profiling_events.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_profiling_events.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_profiling_events.h b/drivers/gpu/arm/mali400/linux/mali_profiling_events.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_profiling_events.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2012, 2016 ARM Limited. All rights reserved. @@ -54055,9 +55226,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_profiling_events.h b/drivers/g +#include + +#endif /* __MALI_PROFILING_EVENTS_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_profiling_gator_api.h b/drivers/gpu/arm/mali400/linux/mali_profiling_gator_api.h ---- a/drivers/gpu/arm/mali400/linux/mali_profiling_gator_api.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_profiling_gator_api.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_profiling_gator_api.h b/drivers/gpu/arm/mali400/linux/mali_profiling_gator_api.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_profiling_gator_api.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2012-2013, 2016 ARM Limited. All rights reserved. @@ -54076,9 +55249,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_profiling_gator_api.h b/driver +#include + +#endif /* __MALI_PROFILING_GATOR_API_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_profiling_internal.c b/drivers/gpu/arm/mali400/linux/mali_profiling_internal.c ---- a/drivers/gpu/arm/mali400/linux/mali_profiling_internal.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_profiling_internal.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_profiling_internal.c b/drivers/gpu/arm/mali400/linux/mali_profiling_internal.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_profiling_internal.c @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -54355,9 +55530,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_profiling_internal.c b/drivers +{ + return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_profiling_internal.h b/drivers/gpu/arm/mali400/linux/mali_profiling_internal.h ---- a/drivers/gpu/arm/mali400/linux/mali_profiling_internal.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_profiling_internal.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_profiling_internal.h b/drivers/gpu/arm/mali400/linux/mali_profiling_internal.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_profiling_internal.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012-2014, 2016 ARM Limited. All rights reserved. @@ -54394,9 +55571,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_profiling_internal.h b/drivers +#endif + +#endif /* __MALI_PROFILING_INTERNAL_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_sync.c b/drivers/gpu/arm/mali400/linux/mali_sync.c ---- a/drivers/gpu/arm/mali400/linux/mali_sync.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_sync.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_sync.c b/drivers/gpu/arm/mali400/linux/mali_sync.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_sync.c @@ -0,0 +1,451 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -54849,9 +56028,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_sync.c b/drivers/gpu/arm/mali4 + + return sync_fence; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_sync.h b/drivers/gpu/arm/mali400/linux/mali_sync.h ---- a/drivers/gpu/arm/mali400/linux/mali_sync.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_sync.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_sync.h b/drivers/gpu/arm/mali400/linux/mali_sync.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_sync.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2012-2016 ARM Limited. All rights reserved. @@ -54964,9 +56145,34 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_sync.h b/drivers/gpu/arm/mali4 +#endif /* defined(CONFIG_SYNC) */ + +#endif /* _MALI_SYNC_H_ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_core.c b/drivers/gpu/arm/mali400/linux/mali_ukk_core.c ---- a/drivers/gpu/arm/mali400/linux/mali_ukk_core.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_ukk_core.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_uk_types.h b/drivers/gpu/arm/mali400/linux/mali_uk_types.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_uk_types.h +@@ -0,0 +1,17 @@ ++/* ++ * Copyright (C) 2012, 2016 ARM Limited. All rights reserved. ++ * ++ * 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 __MALI_UK_TYPES_H__ ++#define __MALI_UK_TYPES_H__ ++ ++/* Simple wrapper in order to find the OS specific location of this file */ ++#include ++ ++#endif /* __MALI_UK_TYPES_H__ */ +diff --git a/drivers/gpu/arm/mali400/linux/mali_ukk_core.c b/drivers/gpu/arm/mali400/linux/mali_ukk_core.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_ukk_core.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -55114,9 +56320,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_core.c b/drivers/gpu/arm/m + + return 0; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_gp.c b/drivers/gpu/arm/mali400/linux/mali_ukk_gp.c ---- a/drivers/gpu/arm/mali400/linux/mali_ukk_gp.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_ukk_gp.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_ukk_gp.c b/drivers/gpu/arm/mali400/linux/mali_ukk_gp.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_ukk_gp.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2010, 2012-2014, 2016 ARM Limited. All rights reserved. @@ -55209,9 +56417,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_gp.c b/drivers/gpu/arm/mal + + return 0; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_mem.c b/drivers/gpu/arm/mali400/linux/mali_ukk_mem.c ---- a/drivers/gpu/arm/mali400/linux/mali_ukk_mem.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_ukk_mem.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_ukk_mem.c b/drivers/gpu/arm/mali400/linux/mali_ukk_mem.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_ukk_mem.c @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -55546,9 +56756,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_mem.c b/drivers/gpu/arm/ma + return 0; +} + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_pp.c b/drivers/gpu/arm/mali400/linux/mali_ukk_pp.c ---- a/drivers/gpu/arm/mali400/linux/mali_ukk_pp.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_ukk_pp.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_ukk_pp.c b/drivers/gpu/arm/mali400/linux/mali_ukk_pp.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_ukk_pp.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2010, 2012-2014, 2016 ARM Limited. All rights reserved. @@ -55655,9 +56867,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_pp.c b/drivers/gpu/arm/mal + + return 0; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_profiling.c b/drivers/gpu/arm/mali400/linux/mali_ukk_profiling.c ---- a/drivers/gpu/arm/mali400/linux/mali_ukk_profiling.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_ukk_profiling.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_ukk_profiling.c b/drivers/gpu/arm/mali400/linux/mali_ukk_profiling.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_ukk_profiling.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -55842,9 +57056,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_profiling.c b/drivers/gpu/ + } + return 0; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_soft_job.c b/drivers/gpu/arm/mali400/linux/mali_ukk_soft_job.c ---- a/drivers/gpu/arm/mali400/linux/mali_ukk_soft_job.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_ukk_soft_job.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_ukk_soft_job.c b/drivers/gpu/arm/mali400/linux/mali_ukk_soft_job.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_ukk_soft_job.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2013-2014, 2016 ARM Limited. All rights reserved. @@ -55936,9 +57152,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_soft_job.c b/drivers/gpu/a + + return map_errcode(err); +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_timeline.c b/drivers/gpu/arm/mali400/linux/mali_ukk_timeline.c ---- a/drivers/gpu/arm/mali400/linux/mali_ukk_timeline.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_ukk_timeline.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_ukk_timeline.c b/drivers/gpu/arm/mali400/linux/mali_ukk_timeline.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_ukk_timeline.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2013, 2016 ARM Limited. All rights reserved. @@ -56028,9 +57246,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_timeline.c b/drivers/gpu/a + + return 0; +} -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_vsync.c b/drivers/gpu/arm/mali400/linux/mali_ukk_vsync.c ---- a/drivers/gpu/arm/mali400/linux/mali_ukk_vsync.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_ukk_vsync.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_ukk_vsync.c b/drivers/gpu/arm/mali400/linux/mali_ukk_vsync.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_ukk_vsync.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2011-2014, 2016 ARM Limited. All rights reserved. @@ -56071,9 +57291,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_vsync.c b/drivers/gpu/arm/ + return 0; +} + -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_wrappers.h b/drivers/gpu/arm/mali400/linux/mali_ukk_wrappers.h ---- a/drivers/gpu/arm/mali400/linux/mali_ukk_wrappers.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_ukk_wrappers.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/linux/mali_ukk_wrappers.h b/drivers/gpu/arm/mali400/linux/mali_ukk_wrappers.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/linux/mali_ukk_wrappers.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2010-2016 ARM Limited. All rights reserved. @@ -56150,240 +57372,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_ukk_wrappers.h b/drivers/gpu/a +#endif + +#endif /* __MALI_UKK_WRAPPERS_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/linux/mali_uk_types.h b/drivers/gpu/arm/mali400/linux/mali_uk_types.h ---- a/drivers/gpu/arm/mali400/linux/mali_uk_types.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/linux/mali_uk_types.h 2018-05-06 08:49:49.182695581 +0200 -@@ -0,0 +1,17 @@ -+/* -+ * Copyright (C) 2012, 2016 ARM Limited. All rights reserved. -+ * -+ * 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 __MALI_UK_TYPES_H__ -+#define __MALI_UK_TYPES_H__ -+ -+/* Simple wrapper in order to find the OS specific location of this file */ -+#include -+ -+#endif /* __MALI_UK_TYPES_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/Makefile b/drivers/gpu/arm/mali400/Makefile ---- a/drivers/gpu/arm/mali400/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/Makefile 2018-05-06 08:49:49.174695256 +0200 -@@ -0,0 +1,206 @@ -+# -+# Copyright (C) 2010-2016 ARM Limited. All rights reserved. -+# -+# 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. -+# -+ -+USE_UMPV2=0 -+USING_PROFILING ?= 1 -+USING_INTERNAL_PROFILING ?= 0 -+USING_DVFS ?= 1 -+USING_DMA_BUF_FENCE ?= 0 -+MALI_HEATMAPS_ENABLED ?= 0 -+MALI_DMA_BUF_MAP_ON_ATTACH ?= 1 -+MALI_PMU_PARALLEL_POWER_UP ?= 0 -+USING_DT ?= 0 -+MALI_MEM_SWAP_TRACKING ?= 0 -+USING_DEVFREQ ?= 0 -+ -+# The Makefile sets up "arch" based on the CONFIG, creates the version info -+# string and the __malidrv_build_info.c file, and then call the Linux build -+# system to actually build the driver. After that point the Kbuild file takes -+# over. -+ -+# set up defaults if not defined by the user -+ARCH ?= arm -+ -+OSKOS=linux -+FILES_PREFIX= -+ -+check_cc2 = \ -+ $(shell if $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \ -+ then \ -+ echo "$(2)"; \ -+ else \ -+ echo "$(3)"; \ -+ fi ;) -+ -+# This conditional makefile exports the global definition ARM_INTERNAL_BUILD. Customer releases will not include arm_internal.mak -+-include ../../../arm_internal.mak -+ -+# Give warning of old config parameters are used -+ifneq ($(CONFIG),) -+$(warning "You have specified the CONFIG variable which is no longer in used. Use TARGET_PLATFORM instead.") -+endif -+ -+ifneq ($(CPU),) -+$(warning "You have specified the CPU variable which is no longer in used. Use TARGET_PLATFORM instead.") -+endif -+ -+# Include the mapping between TARGET_PLATFORM and KDIR + MALI_PLATFORM -+-include MALI_CONFIGURATION -+export KDIR ?= $(KDIR-$(TARGET_PLATFORM)) -+export MALI_PLATFORM ?= $(MALI_PLATFORM-$(TARGET_PLATFORM)) -+ -+ifneq ($(TARGET_PLATFORM),) -+ifeq ($(MALI_PLATFORM),) -+$(error "Invalid TARGET_PLATFORM: $(TARGET_PLATFORM)") -+endif -+endif -+ -+# validate lookup result -+ifeq ($(KDIR),) -+$(error No KDIR found for platform $(TARGET_PLATFORM)) -+endif -+ -+ifeq ($(USING_GPU_UTILIZATION), 1) -+ ifeq ($(USING_DVFS), 1) -+ $(error USING_GPU_UTILIZATION conflict with USING_DVFS you can read the Integration Guide to choose which one do you need) -+ endif -+endif -+ -+ifeq ($(USING_UMP),1) -+export CONFIG_MALI400_UMP=y -+export EXTRA_DEFINES += -DCONFIG_MALI400_UMP=1 -+ifeq ($(USE_UMPV2),1) -+UMP_SYMVERS_FILE ?= ../umpv2/Module.symvers -+else -+UMP_SYMVERS_FILE ?= ../ump/Module.symvers -+endif -+KBUILD_EXTRA_SYMBOLS = $(realpath $(UMP_SYMVERS_FILE)) -+$(warning $(KBUILD_EXTRA_SYMBOLS)) -+endif -+ -+# Define host system directory -+KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build -+ -+include $(KDIR)/.config -+ -+ifeq ($(ARCH), arm) -+# when compiling for ARM we're cross compiling -+export CROSS_COMPILE ?= $(call check_cc2, arm-linux-gnueabi-gcc, arm-linux-gnueabi-, arm-none-linux-gnueabi-) -+endif -+ -+# report detected/selected settings -+ifdef ARM_INTERNAL_BUILD -+$(warning TARGET_PLATFORM $(TARGET_PLATFORM)) -+$(warning KDIR $(KDIR)) -+$(warning MALI_PLATFORM $(MALI_PLATFORM)) -+endif -+ -+# Set up build config -+export CONFIG_MALI400=m -+export CONFIG_MALI450=y -+export CONFIG_MALI470=y -+ -+export EXTRA_DEFINES += -DCONFIG_MALI400=1 -+export EXTRA_DEFINES += -DCONFIG_MALI450=1 -+export EXTRA_DEFINES += -DCONFIG_MALI470=1 -+ -+ifneq ($(MALI_PLATFORM),) -+export EXTRA_DEFINES += -DMALI_FAKE_PLATFORM_DEVICE=1 -+export MALI_PLATFORM_FILES = $(wildcard platform/$(MALI_PLATFORM)/*.c) -+endif -+ -+ifeq ($(USING_PROFILING),1) -+ifeq ($(CONFIG_TRACEPOINTS),) -+$(warning CONFIG_TRACEPOINTS required for profiling) -+else -+export CONFIG_MALI400_PROFILING=y -+export EXTRA_DEFINES += -DCONFIG_MALI400_PROFILING=1 -+ifeq ($(USING_INTERNAL_PROFILING),1) -+export CONFIG_MALI400_INTERNAL_PROFILING=y -+export EXTRA_DEFINES += -DCONFIG_MALI400_INTERNAL_PROFILING=1 -+endif -+ifeq ($(MALI_HEATMAPS_ENABLED),1) -+export MALI_HEATMAPS_ENABLED=y -+export EXTRA_DEFINES += -DCONFIG_MALI400_HEATMAPS_ENABLED -+endif -+endif -+endif -+ -+ifeq ($(MALI_DMA_BUF_MAP_ON_ATTACH),1) -+export CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH=y -+export EXTRA_DEFINES += -DCONFIG_MALI_DMA_BUF_MAP_ON_ATTACH -+endif -+ -+ifeq ($(MALI_SHARED_INTERRUPTS),1) -+export CONFIG_MALI_SHARED_INTERRUPTS=y -+export EXTRA_DEFINES += -DCONFIG_MALI_SHARED_INTERRUPTS -+endif -+ -+ifeq ($(USING_DVFS),1) -+export CONFIG_MALI_DVFS=y -+export EXTRA_DEFINES += -DCONFIG_MALI_DVFS -+endif -+ -+ifeq ($(USING_DMA_BUF_FENCE),1) -+export CONFIG_MALI_DMA_BUF_FENCE=y -+export EXTRA_DEFINES += -DCONFIG_MALI_DMA_BUF_FENCE -+endif -+ -+ifeq ($(MALI_PMU_PARALLEL_POWER_UP),1) -+export CONFIG_MALI_PMU_PARALLEL_POWER_UP=y -+export EXTRA_DEFINES += -DCONFIG_MALI_PMU_PARALLEL_POWER_UP -+endif -+ -+ifdef CONFIG_OF -+ifeq ($(USING_DT),1) -+export CONFIG_MALI_DT=y -+export EXTRA_DEFINES += -DCONFIG_MALI_DT -+endif -+endif -+ -+ifeq ($(USING_DEVFREQ), 1) -+ifdef CONFIG_PM_DEVFREQ -+export CONFIG_MALI_DEVFREQ=y -+export EXTRA_DEFINES += -DCONFIG_MALI_DEVFREQ=1 -+else -+$(warning "You want to support DEVFREQ but kernel didn't support DEVFREQ.") -+endif -+endif -+ -+ifneq ($(BUILD),release) -+# Debug -+export CONFIG_MALI400_DEBUG=y -+else -+# Release -+ifeq ($(MALI_QUIET),1) -+export CONFIG_MALI_QUIET=y -+export EXTRA_DEFINES += -DCONFIG_MALI_QUIET -+endif -+endif -+ -+ifeq ($(MALI_SKIP_JOBS),1) -+EXTRA_DEFINES += -DPROFILING_SKIP_PP_JOBS=1 -DPROFILING_SKIP_GP_JOBS=1 -+endif -+ -+ifeq ($(MALI_MEM_SWAP_TRACKING),1) -+EXTRA_DEFINES += -DMALI_MEM_SWAP_TRACKING=1 -+endif -+ -+all: $(UMP_SYMVERS_FILE) -+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) modules -+ @rm $(FILES_PREFIX)__malidrv_build_info.c $(FILES_PREFIX)__malidrv_build_info.o -+ -+clean: -+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean -+ -+kernelrelease: -+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) kernelrelease -+ -+export CONFIG KBUILD_EXTRA_SYMBOLS -diff -ENwbur a/drivers/gpu/arm/mali400/platform/arm/arm.c b/drivers/gpu/arm/mali400/platform/arm/arm.c ---- a/drivers/gpu/arm/mali400/platform/arm/arm.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/platform/arm/arm.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/platform/arm/arm.c b/drivers/gpu/arm/mali400/platform/arm/arm.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/platform/arm/arm.c @@ -0,0 +1,623 @@ +/* + * Copyright (C) 2010, 2012-2016 ARM Limited. All rights reserved. @@ -57008,9 +58001,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/platform/arm/arm.c b/drivers/gpu/arm/mali + mali_core_scaling_update(data); + } +} -diff -ENwbur a/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.c b/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.c ---- a/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.c b/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2013-2014, 2016 ARM Limited. All rights reserved. @@ -57134,9 +58129,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.c b/drivers + /* do nothing */ + } +} -diff -ENwbur a/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.h b/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.h ---- a/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.h b/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2013, 2016 ARM Limited. All rights reserved. @@ -57182,9 +58179,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/platform/arm/arm_core_scaling.h b/drivers +void mali_core_scaling_sync(int num_cores); + +#endif /* __ARM_CORE_SCALING_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/platform/arm/juno_opp.c b/drivers/gpu/arm/mali400/platform/arm/juno_opp.c ---- a/drivers/gpu/arm/mali400/platform/arm/juno_opp.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/platform/arm/juno_opp.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/platform/arm/juno_opp.c b/drivers/gpu/arm/mali400/platform/arm/juno_opp.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/platform/arm/juno_opp.c @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2010, 2012-2016 ARM Limited. All rights reserved. @@ -57313,9 +58312,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/platform/arm/juno_opp.c b/drivers/gpu/arm +#endif +#endif +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18.c b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18.c ---- a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18.c b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18.c @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2010, 2012-2016 ARM Limited. All rights reserved. @@ -57626,9 +58627,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18.c b/drivers/gpu/a + mali_core_scaling_update(data); + } +} -diff -ENwbur a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.c b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.c ---- a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.c 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.c b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2013-2014, 2016 ARM Limited. All rights reserved. @@ -57755,9 +58758,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.c b/ + /* do nothing */ + } +} -diff -ENwbur a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.h b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.h ---- a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.h 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.h b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2013, 2016 ARM Limited. All rights reserved. @@ -57803,9 +58808,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/platform/nexell/s5pxx18_core_scaling.h b/ +void mali_core_scaling_sync(int num_cores); + +#endif /* __ARM_CORE_SCALING_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/readme.txt b/drivers/gpu/arm/mali400/readme.txt ---- a/drivers/gpu/arm/mali400/readme.txt 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/readme.txt 2018-05-06 08:49:49.182695581 +0200 +diff --git a/drivers/gpu/arm/mali400/readme.txt b/drivers/gpu/arm/mali400/readme.txt +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/readme.txt @@ -0,0 +1,28 @@ +Building the Mali Device Driver for Linux +----------------------------------------- @@ -57835,9 +58842,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/readme.txt b/drivers/gpu/arm/mali400/read +The kernel needs to be provided with a platform_device struct for the Mali GPU +device. See the mali_utgard.h header file for how to set up the Mali GPU +resources. -diff -ENwbur a/drivers/gpu/arm/mali400/regs/mali_200_regs.h b/drivers/gpu/arm/mali400/regs/mali_200_regs.h ---- a/drivers/gpu/arm/mali400/regs/mali_200_regs.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/regs/mali_200_regs.h 2018-05-06 08:49:49.186695742 +0200 +diff --git a/drivers/gpu/arm/mali400/regs/mali_200_regs.h b/drivers/gpu/arm/mali400/regs/mali_200_regs.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/regs/mali_200_regs.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2010, 2012-2016 ARM Limited. All rights reserved. @@ -57970,9 +58979,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/regs/mali_200_regs.h b/drivers/gpu/arm/ma + + +#endif /* _MALI200_REGS_H_ */ -diff -ENwbur a/drivers/gpu/arm/mali400/regs/mali_gp_regs.h b/drivers/gpu/arm/mali400/regs/mali_gp_regs.h ---- a/drivers/gpu/arm/mali400/regs/mali_gp_regs.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/regs/mali_gp_regs.h 2018-05-06 08:49:49.186695742 +0200 +diff --git a/drivers/gpu/arm/mali400/regs/mali_gp_regs.h b/drivers/gpu/arm/mali400/regs/mali_gp_regs.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/regs/mali_gp_regs.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2010, 2012-2016 ARM Limited. All rights reserved. @@ -58146,9 +59157,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/regs/mali_gp_regs.h b/drivers/gpu/arm/mal +}; + +#endif -diff -ENwbur a/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.c b/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.c ---- a/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.c 2018-05-06 08:49:49.186695742 +0200 +diff --git a/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.c b/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.c @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2010-2011, 2013, 2016 ARM Limited. All rights reserved. @@ -58163,9 +59176,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.c b/dri +#include "mali_timestamp.h" + +/* This file is intentionally left empty, as all functions are inlined in mali_profiling_sampler.h */ -diff -ENwbur a/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.h b/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.h ---- a/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.h 2018-05-06 08:49:49.186695742 +0200 +diff --git a/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.h b/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010-2011, 2013-2014, 2016 ARM Limited. All rights reserved. @@ -58215,9 +59230,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/timestamp-arm11-cc/mali_timestamp.h b/dri +} + +#endif /* __MALI_TIMESTAMP_H__ */ -diff -ENwbur a/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.c b/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.c ---- a/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.c 2018-05-06 08:49:49.186695742 +0200 +diff --git a/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.c b/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.c @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2010-2011, 2013, 2016 ARM Limited. All rights reserved. @@ -58232,9 +59249,11 @@ diff -ENwbur a/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.c b/driv +#include "mali_timestamp.h" + +/* This file is intentionally left empty, as all functions are inlined in mali_profiling_sampler.h */ -diff -ENwbur a/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.h b/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.h ---- a/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.h 2018-05-06 08:49:49.186695742 +0200 +diff --git a/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.h b/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010-2011, 2013-2014, 2016 ARM Limited. All rights reserved. @@ -58262,29 +59281,33 @@ diff -ENwbur a/drivers/gpu/arm/mali400/timestamp-default/mali_timestamp.h b/driv +} + +#endif /* __MALI_TIMESTAMP_H__ */ -diff -ENwbur a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig ---- a/drivers/gpu/drm/Kconfig 2018-05-06 08:47:36.357304664 +0200 -+++ b/drivers/gpu/drm/Kconfig 2018-05-06 08:49:49.186695742 +0200 -@@ -278,6 +278,8 @@ - +diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/Kconfig ++++ b/drivers/gpu/drm/Kconfig +@@ -278,6 +278,8 @@ source "drivers/gpu/drm/tinydrm/Kconfig" + source "drivers/gpu/drm/pl111/Kconfig" - + +source "drivers/gpu/drm/nexell/Kconfig" + # Keep legacy drivers last - + menuconfig DRM_LEGACY -diff -ENwbur a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile ---- a/drivers/gpu/drm/Makefile 2018-05-06 08:47:36.357304664 +0200 -+++ b/drivers/gpu/drm/Makefile 2018-05-06 08:49:49.186695742 +0200 -@@ -101,3 +101,4 @@ +diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/Makefile ++++ b/drivers/gpu/drm/Makefile +@@ -101,3 +101,4 @@ obj-$(CONFIG_DRM_ZTE) += zte/ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ +obj-$(CONFIG_DRM_NX) += nexell/ -diff -ENwbur a/drivers/gpu/drm/nexell/Kconfig b/drivers/gpu/drm/nexell/Kconfig ---- a/drivers/gpu/drm/nexell/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/Kconfig 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/Kconfig b/drivers/gpu/drm/nexell/Kconfig +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/Kconfig @@ -0,0 +1,51 @@ +config DRM_NX + tristate "DRM Support for NEXELL Display Controller" @@ -58337,9 +59360,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/Kconfig b/drivers/gpu/drm/nexell/Kconfig + This selects support for HDMI display out. + If you want to enable HDMI display, + you should selet this option. -diff -ENwbur a/drivers/gpu/drm/nexell/Makefile b/drivers/gpu/drm/nexell/Makefile ---- a/drivers/gpu/drm/nexell/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/Makefile 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/Makefile b/drivers/gpu/drm/nexell/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for the drm device driver. This driver provides support for the @@ -58355,9 +59380,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/Makefile b/drivers/gpu/drm/nexell/Makefile +obj-$(CONFIG_DRM_NX_MIPI_DSI) += nx_drm_lcd.o +obj-$(CONFIG_DRM_NX_HDMI) += nx_drm_hdmi.o +obj-$(CONFIG_DRM_NX) += nx_drm.o -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_connector.c b/drivers/gpu/drm/nexell/nx_drm_connector.c ---- a/drivers/gpu/drm/nexell/nx_drm_connector.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_connector.c 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_connector.c b/drivers/gpu/drm/nexell/nx_drm_connector.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_connector.c @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -58613,9 +59640,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_connector.c b/drivers/gpu/drm/nexel +} +EXPORT_SYMBOL(nx_drm_connector_create_and_attach); + -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_connector.h b/drivers/gpu/drm/nexell/nx_drm_connector.h ---- a/drivers/gpu/drm/nexell/nx_drm_connector.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_connector.h 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_connector.h b/drivers/gpu/drm/nexell/nx_drm_connector.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_connector.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -58658,9 +59687,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_connector.h b/drivers/gpu/drm/nexel +void nx_drm_connector_destroy_and_detach(struct drm_connector *connector); + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_crtc.c b/drivers/gpu/drm/nexell/nx_drm_crtc.c ---- a/drivers/gpu/drm/nexell/nx_drm_crtc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_crtc.c 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_crtc.c b/drivers/gpu/drm/nexell/nx_drm_crtc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_crtc.c @@ -0,0 +1,674 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -59336,9 +60367,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_crtc.c b/drivers/gpu/drm/nexell/nx_ + return ret; +} + -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_crtc.h b/drivers/gpu/drm/nexell/nx_drm_crtc.h ---- a/drivers/gpu/drm/nexell/nx_drm_crtc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_crtc.h 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_crtc.h b/drivers/gpu/drm/nexell/nx_drm_crtc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_crtc.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -59384,9 +60417,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_crtc.h b/drivers/gpu/drm/nexell/nx_ +void nx_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe); + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_drv.c b/drivers/gpu/drm/nexell/nx_drm_drv.c ---- a/drivers/gpu/drm/nexell/nx_drm_drv.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_drv.c 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_drv.c b/drivers/gpu/drm/nexell/nx_drm_drv.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_drv.c @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -59830,9 +60865,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_drv.c b/drivers/gpu/drm/nexell/nx_d +MODULE_AUTHOR("jhkim "); +MODULE_DESCRIPTION("Nexell DRM Driver"); +MODULE_LICENSE("GPL"); -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_drv.h b/drivers/gpu/drm/nexell/nx_drm_drv.h ---- a/drivers/gpu/drm/nexell/nx_drm_drv.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_drv.h 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_drv.h b/drivers/gpu/drm/nexell/nx_drm_drv.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_drv.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -59873,9 +60910,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_drv.h b/drivers/gpu/drm/nexell/nx_d +}; + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_encoder.c b/drivers/gpu/drm/nexell/nx_drm_encoder.c ---- a/drivers/gpu/drm/nexell/nx_drm_encoder.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_encoder.c 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_encoder.c b/drivers/gpu/drm/nexell/nx_drm_encoder.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_encoder.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -60143,9 +61182,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_encoder.c b/drivers/gpu/drm/nexell/ +} +EXPORT_SYMBOL(nx_drm_encoder_create); + -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_encoder.h b/drivers/gpu/drm/nexell/nx_drm_encoder.h ---- a/drivers/gpu/drm/nexell/nx_drm_encoder.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_encoder.h 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_encoder.h b/drivers/gpu/drm/nexell/nx_drm_encoder.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_encoder.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -60186,9 +61227,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_encoder.h b/drivers/gpu/drm/nexell/ + int pipe, int possible_crtcs, void *context); + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_fb.c b/drivers/gpu/drm/nexell/nx_drm_fb.c ---- a/drivers/gpu/drm/nexell/nx_drm_fb.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_fb.c 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_fb.c b/drivers/gpu/drm/nexell/nx_drm_fb.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_fb.c @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -60658,9 +61701,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_fb.c b/drivers/gpu/drm/nexell/nx_dr + return nx_fb->obj[plane]; +} +EXPORT_SYMBOL_GPL(nx_drm_fb_get_gem_obj); -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_fb.h b/drivers/gpu/drm/nexell/nx_drm_fb.h ---- a/drivers/gpu/drm/nexell/nx_drm_fb.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_fb.h 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_fb.h b/drivers/gpu/drm/nexell/nx_drm_fb.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_fb.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -60724,9 +61769,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_fb.h b/drivers/gpu/drm/nexell/nx_dr +struct nx_gem_object *nx_drm_fb_get_gem_obj(struct drm_framebuffer *fb, + unsigned int plane); +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_gem.c b/drivers/gpu/drm/nexell/nx_drm_gem.c ---- a/drivers/gpu/drm/nexell/nx_drm_gem.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_gem.c 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_gem.c b/drivers/gpu/drm/nexell/nx_drm_gem.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_gem.c @@ -0,0 +1,1710 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -62438,9 +63485,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_gem.c b/drivers/gpu/drm/nexell/nx_d + return 0; +} + -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_gem.h b/drivers/gpu/drm/nexell/nx_drm_gem.h ---- a/drivers/gpu/drm/nexell/nx_drm_gem.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_gem.h 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_gem.h b/drivers/gpu/drm/nexell/nx_drm_gem.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_gem.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -62537,9 +63586,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_gem.h b/drivers/gpu/drm/nexell/nx_d +int nx_drm_gem_wait_fence(struct drm_gem_object *obj); + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_hdmi.c b/drivers/gpu/drm/nexell/nx_drm_hdmi.c ---- a/drivers/gpu/drm/nexell/nx_drm_hdmi.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_hdmi.c 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_hdmi.c b/drivers/gpu/drm/nexell/nx_drm_hdmi.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_hdmi.c @@ -0,0 +1,731 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -63272,9 +64323,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_hdmi.c b/drivers/gpu/drm/nexell/nx_ +MODULE_AUTHOR("jhkim "); +MODULE_DESCRIPTION("Nexell HDMI DRM Driver"); +MODULE_LICENSE("GPL"); -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_lcd.c b/drivers/gpu/drm/nexell/nx_drm_lcd.c ---- a/drivers/gpu/drm/nexell/nx_drm_lcd.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_lcd.c 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_lcd.c b/drivers/gpu/drm/nexell/nx_drm_lcd.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_lcd.c @@ -0,0 +1,680 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -63956,9 +65009,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_lcd.c b/drivers/gpu/drm/nexell/nx_d +MODULE_AUTHOR("jhkim "); +MODULE_DESCRIPTION("Nexell LCD DRM Driver"); +MODULE_LICENSE("GPL"); -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_plane.c b/drivers/gpu/drm/nexell/nx_drm_plane.c ---- a/drivers/gpu/drm/nexell/nx_drm_plane.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_plane.c 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_plane.c b/drivers/gpu/drm/nexell/nx_drm_plane.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_plane.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -64178,9 +65233,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_plane.c b/drivers/gpu/drm/nexell/nx + return (struct drm_plane *)plane; +} + -diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_plane.h b/drivers/gpu/drm/nexell/nx_drm_plane.h ---- a/drivers/gpu/drm/nexell/nx_drm_plane.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/nx_drm_plane.h 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/nx_drm_plane.h b/drivers/gpu/drm/nexell/nx_drm_plane.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/nx_drm_plane.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -64246,9 +65303,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/nx_drm_plane.h b/drivers/gpu/drm/nexell/nx + int plane_num); + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/soc/Makefile b/drivers/gpu/drm/nexell/soc/Makefile ---- a/drivers/gpu/drm/nexell/soc/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/Makefile 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/Makefile b/drivers/gpu/drm/nexell/soc/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for the drm device driver. This driver provides support for the @@ -64264,9 +65323,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/Makefile b/drivers/gpu/drm/nexell/soc/ +obj-$(CONFIG_DRM_NX_HDMI) += s5pxx18_hdmi_presets.o s5pxx18_reg_hdmi.o s5pxx18_dp_hdmi.o + + -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.c b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.c 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.c b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.c @@ -0,0 +1,891 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -65159,9 +66220,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.c b/drivers/gpu/drm/nex + nx_mlc_set_layer_priority(module, priority); + nx_mlc_set_top_dirty_flag(module); +} -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.h b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.h ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.h 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.h b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.h @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -65539,9 +66602,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_dev.h b/drivers/gpu/drm/nex +#endif + +#endif /* __S5PXX18_DP_DEV_H__ */ -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.c b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.c 2018-05-06 08:49:49.566711163 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.c b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.c @@ -0,0 +1,1001 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -66544,9 +67609,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.c b/drivers/gpu/drm/ne + return 0; +} + -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.h b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.h ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.h 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.h b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -66682,9 +67749,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_hdmi.h b/drivers/gpu/drm/ne +int nx_dp_hdmi_suspend(struct nx_drm_device *display); + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_lvds.c b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_lvds.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_lvds.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_lvds.c 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_lvds.c b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_lvds.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_lvds.c @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -66959,9 +68028,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_lvds.c b/drivers/gpu/drm/ne + + return 0; +} -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_mipi.c b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_mipi.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_mipi.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_mipi.c 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_mipi.c b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_mipi.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_mipi.c @@ -0,0 +1,519 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -67482,9 +68553,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_mipi.c b/drivers/gpu/drm/ne + + return 0; +} -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_rgb.c b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_rgb.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_rgb.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_rgb.c 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_rgb.c b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_rgb.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_dp_rgb.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -67534,9 +68607,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_dp_rgb.c b/drivers/gpu/drm/nex + + return 0; +} -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.c b/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.c 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.c b/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.c @@ -0,0 +1,1282 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -68820,9 +69895,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.c b/drivers/gpu/drm/nex + return 0; +} +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.h b/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.h ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.h 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.h b/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -68991,9 +70068,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_drm_dp.h b/drivers/gpu/drm/nex + struct nx_drm_device *display); + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_hdmi_presets.c b/drivers/gpu/drm/nexell/soc/s5pxx18_hdmi_presets.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_hdmi_presets.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_hdmi_presets.c 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_hdmi_presets.c b/drivers/gpu/drm/nexell/soc/s5pxx18_hdmi_presets.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_hdmi_presets.c @@ -0,0 +1,968 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -69963,9 +71042,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_hdmi_presets.c b/drivers/gpu/d +}; + +const int num_hdmi_presets = ARRAY_SIZE(hdmi_conf); -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.c b/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.c 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.c b/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -70038,9 +71119,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.c b/drivers/gpu/drm/n + buf[i] = readb(hdmi_io_base + reg + i * 4); +} + -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.h b/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.h ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.h 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.h b/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.h @@ -0,0 +1,1006 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -71048,9 +72131,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_reg_hdmi.h b/drivers/gpu/drm/n +void hdmi_read_bytes(u32 reg, u8 *buf, int bytes); + +#endif /* __ARCH_ARM_REGS_HDMI_H */ -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disp.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disp.h ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disp.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disp.h 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disp.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disp.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disp.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -71087,9 +72172,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disp.h b/drivers/gpu/drm/n +}; + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.c 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -71286,405 +72373,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.c b/drivers/gpu/dr + regvalue = regvalue | ((enb & 0x1) << 9); + writel(regvalue, &pregister->greg1); +} -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.c 2018-05-06 08:49:49.570711325 +0200 -@@ -0,0 +1,319 @@ -+/* -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * Author: junghyun, kim -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+#include -+#include -+ -+#include "s5pxx18_soc_disptop_clk.h" -+#include "s5pxx18_soc_disptop.h" -+ -+static struct { -+ struct nx_disptop_clkgen_register_set *__g_pregister; -+} __g_module_variables[NUMBER_OF_DISPTOP_CLKGEN_MODULE] = { -+ { NULL,}, -+}; -+ -+int nx_disp_top_clkgen_initialize(void) -+{ -+ static int binit; -+ u32 i; -+ -+ if (0 == binit) { -+ for (i = 0; i < NUMBER_OF_DISPTOP_CLKGEN_MODULE; i++) -+ __g_module_variables[i].__g_pregister = NULL; -+ binit = 1; -+ } -+ return 1; -+} -+ -+u32 nx_disp_top_clkgen_get_number_of_module(void) -+{ -+ return NUMBER_OF_DISPTOP_CLKGEN_MODULE; -+} -+ -+u32 nx_disp_top_clkgen_get_physical_address(u32 module_index) -+{ -+ static const u32 physical_addr[] = -+ PHY_BASEADDR_DISPTOP_CLKGEN_LIST; -+ -+ return (u32)physical_addr[module_index]; -+} -+ -+u32 nx_disp_top_clkgen_get_size_of_register_set(void) -+{ -+ return sizeof(struct nx_disptop_clkgen_register_set); -+} -+ -+void nx_disp_top_clkgen_set_base_address(u32 module_index, void *base_address) -+{ -+ __g_module_variables[module_index].__g_pregister = -+ (struct nx_disptop_clkgen_register_set *)base_address; -+} -+ -+void *nx_disp_top_clkgen_get_base_address(u32 module_index) -+{ -+ return (void *)__g_module_variables[module_index].__g_pregister; -+} -+ -+void nx_disp_top_clkgen_set_clock_bclk_mode(u32 module_index, -+ enum nx_bclkmode mode) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ register u32 regvalue; -+ u32 clkmode = 0; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ switch (mode) { -+ case nx_bclkmode_disable: -+ clkmode = 0; -+ case nx_bclkmode_dynamic: -+ clkmode = 2; -+ break; -+ case nx_bclkmode_always: -+ clkmode = 3; -+ break; -+ default: -+ break; -+ } -+ -+ regvalue = pregister->clkenb; -+ regvalue &= ~3ul; -+ regvalue |= (clkmode & 0x03); -+ -+ writel(regvalue, &pregister->clkenb); -+} -+ -+enum nx_bclkmode nx_disp_top_clkgen_get_clock_bclk_mode(u32 module_index) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ u32 mode = 0; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ mode = (pregister->clkenb & 3ul); -+ -+ switch (mode) { -+ case 0: -+ return nx_bclkmode_disable; -+ case 2: -+ return nx_bclkmode_dynamic; -+ case 3: -+ return nx_bclkmode_always; -+ default: -+ break; -+ } -+ return nx_bclkmode_disable; -+} -+ -+void nx_disp_top_clkgen_set_clock_pclk_mode(u32 module_index, -+ enum nx_pclkmode mode) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ register u32 regvalue; -+ const u32 pclkmode_pos = 3; -+ u32 clkmode = 0; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ switch (mode) { -+ case nx_pclkmode_dynamic: -+ clkmode = 0; -+ break; -+ case nx_pclkmode_always: -+ clkmode = 1; -+ break; -+ default: -+ break; -+ } -+ -+ regvalue = pregister->clkenb; -+ regvalue &= ~(1ul << pclkmode_pos); -+ regvalue |= (clkmode & 0x01) << pclkmode_pos; -+ -+ writel(regvalue, &pregister->clkenb); -+} -+ -+enum nx_pclkmode nx_disp_top_clkgen_get_clock_pclk_mode(u32 module_index) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ const u32 pclkmode_pos = 3; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ if (pregister->clkenb & (1ul << pclkmode_pos)) -+ return nx_pclkmode_always; -+ -+ return nx_pclkmode_dynamic; -+} -+ -+void nx_disp_top_clkgen_set_clock_source(u32 module_index, u32 index, -+ u32 clk_src) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ register u32 read_value; -+ -+ const u32 clksrcsel_pos = 2; -+ const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ read_value = pregister->CLKGEN[index << 1]; -+ read_value &= ~clksrcsel_mask; -+ read_value |= clk_src << clksrcsel_pos; -+ -+ writel(read_value, &pregister->CLKGEN[index << 1]); -+} -+ -+u32 nx_disp_top_clkgen_get_clock_source(u32 module_index, u32 index) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ const u32 clksrcsel_pos = 2; -+ const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ return (pregister->CLKGEN[index << 1] & -+ clksrcsel_mask) >> clksrcsel_pos; -+} -+ -+void nx_disp_top_clkgen_set_clock_divisor(u32 module_index, u32 index, -+ u32 divisor) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ const u32 clkdiv_pos = 5; -+ const u32 clkdiv_mask = 0xff << clkdiv_pos; -+ register u32 read_value; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ read_value = pregister->CLKGEN[index << 1]; -+ read_value &= ~clkdiv_mask; -+ read_value |= (divisor - 1) << clkdiv_pos; -+ writel(read_value, &pregister->CLKGEN[index << 1]); -+} -+ -+u32 nx_disp_top_clkgen_get_clock_divisor(u32 module_index, u32 index) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ const u32 clkdiv_pos = 5; -+ const u32 clkdiv_mask = 0xff << clkdiv_pos; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ return ((pregister->CLKGEN[index << 1] & -+ clkdiv_mask) >> clkdiv_pos) + 1; -+} -+ -+void nx_disp_top_clkgen_set_clock_divisor_enable(u32 module_index, int enable) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ register u32 read_value; -+ const u32 clkgenenb_pos = 2; -+ const u32 clkgenenb_mask = 1ul << clkgenenb_pos; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ read_value = pregister->clkenb; -+ read_value &= ~clkgenenb_mask; -+ read_value |= (u32)enable << clkgenenb_pos; -+ -+ writel(read_value, &pregister->clkenb); -+} -+ -+int nx_disp_top_clkgen_get_clock_divisor_enable(u32 module_index) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ const u32 clkgenenb_pos = 2; -+ const u32 clkgenenb_mask = 1ul << clkgenenb_pos; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ return (int)((pregister->clkenb & -+ clkgenenb_mask) >> clkgenenb_pos); -+} -+ -+void nx_disp_top_clkgen_set_clock_out_inv(u32 module_index, u32 index, -+ int out_clk_inv) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ register u32 read_value; -+ const u32 outclkinv_pos = 1; -+ const u32 outclkinv_mask = 1ul << outclkinv_pos; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ read_value = pregister->CLKGEN[index << 1]; -+ read_value &= ~outclkinv_mask; -+ read_value |= out_clk_inv << outclkinv_pos; -+ -+ writel(read_value, &pregister->CLKGEN[index << 1]); -+} -+ -+int nx_disp_top_clkgen_get_clock_out_inv(u32 module_index, u32 index) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ const u32 outclkinv_pos = 1; -+ const u32 outclkinv_mask = 1ul << outclkinv_pos; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ return (int)((pregister->CLKGEN[index << 1] & -+ outclkinv_mask) >> outclkinv_pos); -+} -+ -+int nx_disp_top_clkgen_set_input_inv(u32 module_index, -+ u32 index, int in_clk_inv) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ register u32 read_value; -+ const u32 inclkinv_pos = 4 + index; -+ const u32 inclkinv_mask = 1ul << inclkinv_pos; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ read_value = pregister->clkenb; -+ read_value &= ~inclkinv_mask; -+ read_value |= in_clk_inv << inclkinv_pos; -+ -+ writel(read_value, &pregister->clkenb); -+ return true; -+} -+ -+int nx_disp_top_clkgen_get_input_inv(u32 module_index, u32 index) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ const u32 inclkinv_pos = 4 + index; -+ const u32 inclkinv_mask = 1ul << inclkinv_pos; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ return (int)((pregister->clkenb & -+ inclkinv_mask) >> inclkinv_pos); -+} -+ -+void nx_disp_top_clkgen_set_clock_out_select(u32 module_index, u32 index, -+ int bbypass) -+{ -+ register struct nx_disptop_clkgen_register_set *pregister; -+ register u32 read_value; -+ -+ pregister = __g_module_variables[module_index].__g_pregister; -+ -+ read_value = pregister->CLKGEN[index << 1]; -+ read_value = read_value & (~0x01); -+ read_value = read_value | bbypass; -+ -+ writel(read_value, &pregister->CLKGEN[index << 1]); -+} -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.h ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.h 2018-05-06 08:49:49.570711325 +0200 -@@ -0,0 +1,69 @@ -+/* -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * Author: junghyun, kim -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+#ifndef _S5PXX18_SOC_DISPTOP_CLK_H_ -+#define _S5PXX18_SOC_DISPTOP_CLK_H_ -+ -+#include "s5pxx18_soc_disp.h" -+ -+#define PHY_BASEADDR_DISPTOP_CLKGEN_LIST \ -+ { PHY_BASEADDR_DISPTOP_CLKGEN0_MODULE, \ -+ PHY_BASEADDR_DISPTOP_CLKGEN1_MODULE, \ -+ PHY_BASEADDR_DISPTOP_CLKGEN2_MODULE, \ -+ PHY_BASEADDR_DISPTOP_CLKGEN3_MODULE, \ -+ PHY_BASEADDR_DISPTOP_CLKGEN4_MODULE, \ -+ } -+ -+struct nx_disptop_clkgen_register_set { -+ u32 clkenb; -+ u32 CLKGEN[4]; -+}; -+ -+int nx_disp_top_clkgen_initialize(void); -+u32 nx_disp_top_clkgen_get_number_of_module(void); -+u32 nx_disp_top_clkgen_get_physical_address(u32 module_index); -+u32 nx_disp_top_clkgen_get_size_of_register_set(void); -+void nx_disp_top_clkgen_set_base_address(u32 module_index, -+ void *base_address); -+void *nx_disp_top_clkgen_get_base_address(u32 module_index); -+void nx_disp_top_clkgen_set_clock_pclk_mode(u32 module_index, -+ enum nx_pclkmode mode); -+enum nx_pclkmode nx_disp_top_clkgen_get_clock_pclk_mode(u32 module_index); -+void nx_disp_top_clkgen_set_clock_source(u32 module_index, u32 index, -+ u32 clk_src); -+u32 nx_disp_top_clkgen_get_clock_source(u32 module_index, u32 index); -+void nx_disp_top_clkgen_set_clock_divisor(u32 module_index, u32 index, -+ u32 divisor); -+u32 nx_disp_top_clkgen_get_clock_divisor(u32 module_index, u32 index); -+void nx_disp_top_clkgen_set_clock_divisor_enable(u32 module_index, -+ int enable); -+int nx_disp_top_clkgen_get_clock_divisor_enable(u32 module_index); -+void nx_disp_top_clkgen_set_clock_bclk_mode(u32 module_index, -+ enum nx_bclkmode mode); -+enum nx_bclkmode nx_disp_top_clkgen_get_clock_bclk_mode(u32 module_index); -+ -+void nx_disp_top_clkgen_set_clock_out_inv(u32 module_index, u32 index, -+ int out_clk_inv); -+int nx_disp_top_clkgen_get_clock_out_inv(u32 module_index, u32 index); -+int nx_disp_top_clkgen_set_input_inv(u32 module_index, u32 index, -+ int out_clk_inv); -+int nx_disp_top_clkgen_get_input_inv(u32 module_index, u32 index); -+ -+void nx_disp_top_clkgen_set_clock_out_select(u32 module_index, u32 index, -+ int bbypass); -+ -+#endif -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.h ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.h 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.h @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -72077,9 +72770,411 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop.h b/drivers/gpu/dr + u32 field_use, u32 muxsel); + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.c 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.c +@@ -0,0 +1,319 @@ ++/* ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * Author: junghyun, kim ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++#include ++#include ++ ++#include "s5pxx18_soc_disptop_clk.h" ++#include "s5pxx18_soc_disptop.h" ++ ++static struct { ++ struct nx_disptop_clkgen_register_set *__g_pregister; ++} __g_module_variables[NUMBER_OF_DISPTOP_CLKGEN_MODULE] = { ++ { NULL,}, ++}; ++ ++int nx_disp_top_clkgen_initialize(void) ++{ ++ static int binit; ++ u32 i; ++ ++ if (0 == binit) { ++ for (i = 0; i < NUMBER_OF_DISPTOP_CLKGEN_MODULE; i++) ++ __g_module_variables[i].__g_pregister = NULL; ++ binit = 1; ++ } ++ return 1; ++} ++ ++u32 nx_disp_top_clkgen_get_number_of_module(void) ++{ ++ return NUMBER_OF_DISPTOP_CLKGEN_MODULE; ++} ++ ++u32 nx_disp_top_clkgen_get_physical_address(u32 module_index) ++{ ++ static const u32 physical_addr[] = ++ PHY_BASEADDR_DISPTOP_CLKGEN_LIST; ++ ++ return (u32)physical_addr[module_index]; ++} ++ ++u32 nx_disp_top_clkgen_get_size_of_register_set(void) ++{ ++ return sizeof(struct nx_disptop_clkgen_register_set); ++} ++ ++void nx_disp_top_clkgen_set_base_address(u32 module_index, void *base_address) ++{ ++ __g_module_variables[module_index].__g_pregister = ++ (struct nx_disptop_clkgen_register_set *)base_address; ++} ++ ++void *nx_disp_top_clkgen_get_base_address(u32 module_index) ++{ ++ return (void *)__g_module_variables[module_index].__g_pregister; ++} ++ ++void nx_disp_top_clkgen_set_clock_bclk_mode(u32 module_index, ++ enum nx_bclkmode mode) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ register u32 regvalue; ++ u32 clkmode = 0; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ switch (mode) { ++ case nx_bclkmode_disable: ++ clkmode = 0; ++ case nx_bclkmode_dynamic: ++ clkmode = 2; ++ break; ++ case nx_bclkmode_always: ++ clkmode = 3; ++ break; ++ default: ++ break; ++ } ++ ++ regvalue = pregister->clkenb; ++ regvalue &= ~3ul; ++ regvalue |= (clkmode & 0x03); ++ ++ writel(regvalue, &pregister->clkenb); ++} ++ ++enum nx_bclkmode nx_disp_top_clkgen_get_clock_bclk_mode(u32 module_index) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ u32 mode = 0; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ mode = (pregister->clkenb & 3ul); ++ ++ switch (mode) { ++ case 0: ++ return nx_bclkmode_disable; ++ case 2: ++ return nx_bclkmode_dynamic; ++ case 3: ++ return nx_bclkmode_always; ++ default: ++ break; ++ } ++ return nx_bclkmode_disable; ++} ++ ++void nx_disp_top_clkgen_set_clock_pclk_mode(u32 module_index, ++ enum nx_pclkmode mode) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ register u32 regvalue; ++ const u32 pclkmode_pos = 3; ++ u32 clkmode = 0; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ switch (mode) { ++ case nx_pclkmode_dynamic: ++ clkmode = 0; ++ break; ++ case nx_pclkmode_always: ++ clkmode = 1; ++ break; ++ default: ++ break; ++ } ++ ++ regvalue = pregister->clkenb; ++ regvalue &= ~(1ul << pclkmode_pos); ++ regvalue |= (clkmode & 0x01) << pclkmode_pos; ++ ++ writel(regvalue, &pregister->clkenb); ++} ++ ++enum nx_pclkmode nx_disp_top_clkgen_get_clock_pclk_mode(u32 module_index) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ const u32 pclkmode_pos = 3; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ if (pregister->clkenb & (1ul << pclkmode_pos)) ++ return nx_pclkmode_always; ++ ++ return nx_pclkmode_dynamic; ++} ++ ++void nx_disp_top_clkgen_set_clock_source(u32 module_index, u32 index, ++ u32 clk_src) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ register u32 read_value; ++ ++ const u32 clksrcsel_pos = 2; ++ const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ read_value = pregister->CLKGEN[index << 1]; ++ read_value &= ~clksrcsel_mask; ++ read_value |= clk_src << clksrcsel_pos; ++ ++ writel(read_value, &pregister->CLKGEN[index << 1]); ++} ++ ++u32 nx_disp_top_clkgen_get_clock_source(u32 module_index, u32 index) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ const u32 clksrcsel_pos = 2; ++ const u32 clksrcsel_mask = 0x07 << clksrcsel_pos; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ return (pregister->CLKGEN[index << 1] & ++ clksrcsel_mask) >> clksrcsel_pos; ++} ++ ++void nx_disp_top_clkgen_set_clock_divisor(u32 module_index, u32 index, ++ u32 divisor) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ const u32 clkdiv_pos = 5; ++ const u32 clkdiv_mask = 0xff << clkdiv_pos; ++ register u32 read_value; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ read_value = pregister->CLKGEN[index << 1]; ++ read_value &= ~clkdiv_mask; ++ read_value |= (divisor - 1) << clkdiv_pos; ++ writel(read_value, &pregister->CLKGEN[index << 1]); ++} ++ ++u32 nx_disp_top_clkgen_get_clock_divisor(u32 module_index, u32 index) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ const u32 clkdiv_pos = 5; ++ const u32 clkdiv_mask = 0xff << clkdiv_pos; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ return ((pregister->CLKGEN[index << 1] & ++ clkdiv_mask) >> clkdiv_pos) + 1; ++} ++ ++void nx_disp_top_clkgen_set_clock_divisor_enable(u32 module_index, int enable) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ register u32 read_value; ++ const u32 clkgenenb_pos = 2; ++ const u32 clkgenenb_mask = 1ul << clkgenenb_pos; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ read_value = pregister->clkenb; ++ read_value &= ~clkgenenb_mask; ++ read_value |= (u32)enable << clkgenenb_pos; ++ ++ writel(read_value, &pregister->clkenb); ++} ++ ++int nx_disp_top_clkgen_get_clock_divisor_enable(u32 module_index) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ const u32 clkgenenb_pos = 2; ++ const u32 clkgenenb_mask = 1ul << clkgenenb_pos; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ return (int)((pregister->clkenb & ++ clkgenenb_mask) >> clkgenenb_pos); ++} ++ ++void nx_disp_top_clkgen_set_clock_out_inv(u32 module_index, u32 index, ++ int out_clk_inv) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ register u32 read_value; ++ const u32 outclkinv_pos = 1; ++ const u32 outclkinv_mask = 1ul << outclkinv_pos; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ read_value = pregister->CLKGEN[index << 1]; ++ read_value &= ~outclkinv_mask; ++ read_value |= out_clk_inv << outclkinv_pos; ++ ++ writel(read_value, &pregister->CLKGEN[index << 1]); ++} ++ ++int nx_disp_top_clkgen_get_clock_out_inv(u32 module_index, u32 index) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ const u32 outclkinv_pos = 1; ++ const u32 outclkinv_mask = 1ul << outclkinv_pos; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ return (int)((pregister->CLKGEN[index << 1] & ++ outclkinv_mask) >> outclkinv_pos); ++} ++ ++int nx_disp_top_clkgen_set_input_inv(u32 module_index, ++ u32 index, int in_clk_inv) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ register u32 read_value; ++ const u32 inclkinv_pos = 4 + index; ++ const u32 inclkinv_mask = 1ul << inclkinv_pos; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ read_value = pregister->clkenb; ++ read_value &= ~inclkinv_mask; ++ read_value |= in_clk_inv << inclkinv_pos; ++ ++ writel(read_value, &pregister->clkenb); ++ return true; ++} ++ ++int nx_disp_top_clkgen_get_input_inv(u32 module_index, u32 index) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ const u32 inclkinv_pos = 4 + index; ++ const u32 inclkinv_mask = 1ul << inclkinv_pos; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ return (int)((pregister->clkenb & ++ inclkinv_mask) >> inclkinv_pos); ++} ++ ++void nx_disp_top_clkgen_set_clock_out_select(u32 module_index, u32 index, ++ int bbypass) ++{ ++ register struct nx_disptop_clkgen_register_set *pregister; ++ register u32 read_value; ++ ++ pregister = __g_module_variables[module_index].__g_pregister; ++ ++ read_value = pregister->CLKGEN[index << 1]; ++ read_value = read_value & (~0x01); ++ read_value = read_value | bbypass; ++ ++ writel(read_value, &pregister->CLKGEN[index << 1]); ++} +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_disptop_clk.h +@@ -0,0 +1,69 @@ ++/* ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * Author: junghyun, kim ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++#ifndef _S5PXX18_SOC_DISPTOP_CLK_H_ ++#define _S5PXX18_SOC_DISPTOP_CLK_H_ ++ ++#include "s5pxx18_soc_disp.h" ++ ++#define PHY_BASEADDR_DISPTOP_CLKGEN_LIST \ ++ { PHY_BASEADDR_DISPTOP_CLKGEN0_MODULE, \ ++ PHY_BASEADDR_DISPTOP_CLKGEN1_MODULE, \ ++ PHY_BASEADDR_DISPTOP_CLKGEN2_MODULE, \ ++ PHY_BASEADDR_DISPTOP_CLKGEN3_MODULE, \ ++ PHY_BASEADDR_DISPTOP_CLKGEN4_MODULE, \ ++ } ++ ++struct nx_disptop_clkgen_register_set { ++ u32 clkenb; ++ u32 CLKGEN[4]; ++}; ++ ++int nx_disp_top_clkgen_initialize(void); ++u32 nx_disp_top_clkgen_get_number_of_module(void); ++u32 nx_disp_top_clkgen_get_physical_address(u32 module_index); ++u32 nx_disp_top_clkgen_get_size_of_register_set(void); ++void nx_disp_top_clkgen_set_base_address(u32 module_index, ++ void *base_address); ++void *nx_disp_top_clkgen_get_base_address(u32 module_index); ++void nx_disp_top_clkgen_set_clock_pclk_mode(u32 module_index, ++ enum nx_pclkmode mode); ++enum nx_pclkmode nx_disp_top_clkgen_get_clock_pclk_mode(u32 module_index); ++void nx_disp_top_clkgen_set_clock_source(u32 module_index, u32 index, ++ u32 clk_src); ++u32 nx_disp_top_clkgen_get_clock_source(u32 module_index, u32 index); ++void nx_disp_top_clkgen_set_clock_divisor(u32 module_index, u32 index, ++ u32 divisor); ++u32 nx_disp_top_clkgen_get_clock_divisor(u32 module_index, u32 index); ++void nx_disp_top_clkgen_set_clock_divisor_enable(u32 module_index, ++ int enable); ++int nx_disp_top_clkgen_get_clock_divisor_enable(u32 module_index); ++void nx_disp_top_clkgen_set_clock_bclk_mode(u32 module_index, ++ enum nx_bclkmode mode); ++enum nx_bclkmode nx_disp_top_clkgen_get_clock_bclk_mode(u32 module_index); ++ ++void nx_disp_top_clkgen_set_clock_out_inv(u32 module_index, u32 index, ++ int out_clk_inv); ++int nx_disp_top_clkgen_get_clock_out_inv(u32 module_index, u32 index); ++int nx_disp_top_clkgen_set_input_inv(u32 module_index, u32 index, ++ int out_clk_inv); ++int nx_disp_top_clkgen_get_input_inv(u32 module_index, u32 index); ++ ++void nx_disp_top_clkgen_set_clock_out_select(u32 module_index, u32 index, ++ int bbypass); ++ ++#endif +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.c @@ -0,0 +1,1580 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -73661,9 +74756,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.c b/drivers/gpu/drm/ne + if (NULL != pvsoe) + *pvsoe = (u32) (readl(&pregister->ntsc_vsoe) & 0x1fu); +} -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.h ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.h 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.h @@ -0,0 +1,454 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -74119,9 +75216,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_dpc.h b/drivers/gpu/drm/ne +void nx_dpc_set_luma_gain(u32 module_index, u32 luma_gain); + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.c 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.c @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -74401,9 +75500,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.c b/drivers/gpu/drm/n + pregister = __g_pregister[module_index]; + return (u32) readl(&pregister->lvdsctrl4); +} -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.h ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.h 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -74498,9 +75599,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_lvds.h b/drivers/gpu/drm/n +u32 nx_lvds_get_lvdsdummy(u32 module_index); + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.c 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.c @@ -0,0 +1,675 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -75177,9 +76280,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.c b/drivers/gpu/drm/n + + return __readl(&pregister->dsim_fifoctrl); +} -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.h ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.h 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.h @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -75486,9 +76591,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mipi.h b/drivers/gpu/drm/n +int32_t nx_mipi_get_interrupt_pending_number(u32 module_index); + +#endif -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.c ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.c 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.c b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.c @@ -0,0 +1,1871 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -77361,9 +78468,11 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.c b/drivers/gpu/drm/ne + if (bottom) + *(int *)bottom = ((tb >> 0) & 0xFFUL); +} -diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.h ---- a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.h 2018-05-06 08:49:49.570711325 +0200 +diff --git a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.h b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.h @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -77804,13 +78913,14 @@ diff -ENwbur a/drivers/gpu/drm/nexell/soc/s5pxx18_soc_mlc.h b/drivers/gpu/drm/ne + int *right, int *bottom); + +#endif -diff -ENwbur a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig ---- a/drivers/gpu/drm/panel/Kconfig 2018-05-06 08:47:36.785322040 +0200 -+++ b/drivers/gpu/drm/panel/Kconfig 2018-05-06 08:49:49.626713598 +0200 -@@ -117,4 +117,11 @@ +diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/panel/Kconfig ++++ b/drivers/gpu/drm/panel/Kconfig +@@ -117,4 +117,11 @@ config DRM_PANEL_SITRONIX_ST7789V Say Y here if you want to enable support for the Sitronix ST7789V controller for 240x320 LCD panels - + +config DRM_PANEL_NANOPI + tristate "NanoPi M3 LVDS/RGB panel" + depends on OF && TOUCHSCREEN_1WIRE @@ -77819,17 +78929,20 @@ diff -ENwbur a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig + Say Y if you have display panel connected to one of these outputs. + endmenu -diff -ENwbur a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile ---- a/drivers/gpu/drm/panel/Makefile 2018-05-06 08:47:36.785322040 +0200 -+++ b/drivers/gpu/drm/panel/Makefile 2018-05-06 08:49:49.626713598 +0200 -@@ -11,3 +11,4 @@ +diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/panel/Makefile ++++ b/drivers/gpu/drm/panel/Makefile +@@ -11,3 +11,4 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o +obj-$(CONFIG_DRM_PANEL_NANOPI) += panel-nanopi.o -diff -ENwbur a/drivers/gpu/drm/panel/panel-nanopi.c b/drivers/gpu/drm/panel/panel-nanopi.c ---- a/drivers/gpu/drm/panel/panel-nanopi.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/gpu/drm/panel/panel-nanopi.c 2018-05-06 08:49:49.626713598 +0200 +diff --git a/drivers/gpu/drm/panel/panel-nanopi.c b/drivers/gpu/drm/panel/panel-nanopi.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panel/panel-nanopi.c @@ -0,0 +1,602 @@ +#include +#include @@ -78433,23 +79546,14 @@ diff -ENwbur a/drivers/gpu/drm/panel/panel-nanopi.c b/drivers/gpu/drm/panel/pane +MODULE_AUTHOR("Rafaello7 "); +MODULE_DESCRIPTION("DRM driver for NanoPi M3 panel"); +MODULE_LICENSE("GPL"); -diff -ENwbur a/drivers/gpu/Makefile b/drivers/gpu/Makefile ---- a/drivers/gpu/Makefile 2018-05-06 08:47:36.357304664 +0200 -+++ b/drivers/gpu/Makefile 2018-05-06 08:49:49.174695256 +0200 -@@ -2,5 +2,5 @@ - # taken to initialize them in the correct order. Link order is the only way - # to ensure this currently. - obj-$(CONFIG_TEGRA_HOST1X) += host1x/ --obj-y += drm/ vga/ -+obj-y += drm/ vga/ arm/ - obj-$(CONFIG_IMX_IPUV3_CORE) += ipu-v3/ -diff -ENwbur a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig ---- a/drivers/hwmon/Kconfig 2018-05-06 08:47:36.869325451 +0200 -+++ b/drivers/hwmon/Kconfig 2018-05-06 08:49:49.710717005 +0200 -@@ -1869,6 +1869,13 @@ +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -1869,6 +1869,13 @@ config SENSORS_XGENE If you say yes here you get support for the temperature and power sensors for APM X-Gene SoC. - + +config NANOPI_THERMISTOR + tristate "NanoPi M3 temperature from onboard thermistor" + depends on ARCH_S5P6818 @@ -78458,22 +79562,25 @@ diff -ENwbur a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig + ADC (analog to digital converter) of s5p6818 soc. + if ACPI - + comment "ACPI drivers" -diff -ENwbur a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile ---- a/drivers/hwmon/Makefile 2018-05-06 08:47:36.869325451 +0200 -+++ b/drivers/hwmon/Makefile 2018-05-06 08:49:49.710717005 +0200 -@@ -171,6 +171,7 @@ +diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -171,6 +171,7 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o obj-$(CONFIG_SENSORS_XGENE) += xgene-hwmon.o +obj-$(CONFIG_NANOPI_THERMISTOR) += nanopi-thermistor.o - + obj-$(CONFIG_PMBUS) += pmbus/ - -diff -ENwbur a/drivers/hwmon/nanopi-thermistor.c b/drivers/hwmon/nanopi-thermistor.c ---- a/drivers/hwmon/nanopi-thermistor.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/hwmon/nanopi-thermistor.c 2018-05-06 08:49:49.722717492 +0200 + +diff --git a/drivers/hwmon/nanopi-thermistor.c b/drivers/hwmon/nanopi-thermistor.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/hwmon/nanopi-thermistor.c @@ -0,0 +1,240 @@ +#include +#include @@ -78715,41 +79822,41 @@ diff -ENwbur a/drivers/hwmon/nanopi-thermistor.c b/drivers/hwmon/nanopi-thermist +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rafaello7 "); +MODULE_DESCRIPTION("NanoPi M3 temperature read from thermistor connected to s5p6818 ADC"); -diff -ENwbur a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c ---- a/drivers/i2c/busses/i2c-s3c2410.c 2018-05-06 08:47:36.901326750 +0200 -+++ b/drivers/i2c/busses/i2c-s3c2410.c 2018-05-06 08:49:49.742718303 +0200 +diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c +index 111111111111..222222222222 100644 +--- a/drivers/i2c/busses/i2c-s3c2410.c ++++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -38,10 +38,15 @@ #include #include - + +#ifdef CONFIG_ARM_S5Pxx18_DEVFREQ +#include +#include +#endif + #include - + #include - +#include /* see s3c2410x user guide, v1.1, section 9 (p447) for more info */ - + #define S3C2410_IICCON 0x00 -@@ -125,9 +130,12 @@ +@@ -125,8 +130,11 @@ struct s3c24xx_i2c { struct s3c2410_platform_i2c *pdata; int gpios[2]; struct pinctrl *pctrl; -#if defined(CONFIG_ARM_S3C24XX_CPUFREQ) +#if defined(CONFIG_ARM_S3C24XX_CPUFREQ) || defined(CONFIG_ARM_S5Pxx18_DEVFREQ) struct notifier_block freq_transition; - #endif ++#endif +#if defined(CONFIG_ARM_S5Pxx18_DEVFREQ) + unsigned long clk_in; -+#endif + #endif struct regmap *sysreg; unsigned int sys_i2c_cfg; - }; -@@ -158,6 +166,8 @@ +@@ -158,6 +166,8 @@ static const struct of_device_id s3c24xx_i2c_match[] = { .data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) }, { .compatible = "samsung,exynos5-sata-phy-i2c", .data = (void *)(QUIRK_S3C2440 | QUIRK_POLL | QUIRK_NO_GPIO) }, @@ -78758,10 +79865,10 @@ diff -ENwbur a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410 {}, }; MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); -@@ -948,6 +958,126 @@ +@@ -948,6 +958,126 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) CPUFREQ_TRANSITION_NOTIFIER); } - + +#elif defined(CONFIG_ARM_S5Pxx18_DEVFREQ) + +#define freq_to_i2c(_n) container_of(_n, struct s3c24xx_i2c, freq_transition) @@ -78885,10 +79992,10 @@ diff -ENwbur a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410 #else static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c) { -@@ -1164,6 +1294,22 @@ +@@ -1164,6 +1294,22 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) return ret; } - + + /* + * patch for s5p6818 + * s5p6818 i2c must be reset before enabled @@ -78908,7 +80015,7 @@ diff -ENwbur a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410 ret = s3c24xx_i2c_init(i2c); clk_disable(i2c->clk); if (ret != 0) { -@@ -1267,6 +1413,22 @@ +@@ -1267,6 +1413,22 @@ static int s3c24xx_i2c_resume_noirq(struct device *dev) ret = clk_enable(i2c->clk); if (ret) return ret; @@ -78931,13 +80038,14 @@ diff -ENwbur a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410 s3c24xx_i2c_init(i2c); clk_disable(i2c->clk); i2c->suspended = 0; -diff -ENwbur a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig ---- a/drivers/iio/adc/Kconfig 2018-05-06 08:47:36.921327562 +0200 -+++ b/drivers/iio/adc/Kconfig 2018-05-06 08:49:49.762719115 +0200 -@@ -890,4 +890,11 @@ +diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/iio/adc/Kconfig ++++ b/drivers/iio/adc/Kconfig +@@ -891,4 +891,11 @@ config XILINX_XADC The driver can also be build as a module. If so, the module will be called xilinx-xadc. - + +config NX_ADC + bool "Nexell ADC driver support" + depends on (ARCH_S5P6818 || ARCH_S5P4418) && OF @@ -78946,17 +80054,20 @@ diff -ENwbur a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig + of SoC for Analog Devices. + endmenu -diff -ENwbur a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile ---- a/drivers/iio/adc/Makefile 2018-05-06 08:47:36.921327562 +0200 -+++ b/drivers/iio/adc/Makefile 2018-05-06 08:49:49.762719115 +0200 -@@ -82,3 +82,4 @@ +diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/iio/adc/Makefile ++++ b/drivers/iio/adc/Makefile +@@ -82,3 +82,4 @@ obj-$(CONFIG_VF610_ADC) += vf610_adc.o obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o xilinx-xadc-y := xilinx-xadc-core.o xilinx-xadc-events.o obj-$(CONFIG_XILINX_XADC) += xilinx-xadc.o +obj-$(CONFIG_NX_ADC) += nexell_adc.o -diff -ENwbur a/drivers/iio/adc/nexell_adc.c b/drivers/iio/adc/nexell_adc.c ---- a/drivers/iio/adc/nexell_adc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/iio/adc/nexell_adc.c 2018-05-06 08:49:49.766719279 +0200 +diff --git a/drivers/iio/adc/nexell_adc.c b/drivers/iio/adc/nexell_adc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/iio/adc/nexell_adc.c @@ -0,0 +1,637 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -79595,9 +80706,79 @@ diff -ENwbur a/drivers/iio/adc/nexell_adc.c b/drivers/iio/adc/nexell_adc.c +MODULE_AUTHOR("Bon-gyu, KOO "); +MODULE_DESCRIPTION("ADC driver for the Nexell s5pxx18"); +MODULE_LICENSE("GPL v2"); -diff -ENwbur a/drivers/input/touchscreen/himax_ts.c b/drivers/input/touchscreen/himax_ts.c ---- a/drivers/input/touchscreen/himax_ts.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/input/touchscreen/himax_ts.c 2018-05-06 08:49:49.882723986 +0200 +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -1246,4 +1246,51 @@ config TOUCHSCREEN_ROHM_BU21023 + To compile this driver as a module, choose M here: the + module will be called bu21023_ts. + ++config TOUCHSCREEN_IT7260 ++ tristate "ITE it7260 TouchScreen driver" ++ depends on ARCH_S5P6818 ++ help ++ Say Y here to support ITE it7260 based touchscreen on ++ FriendlyARM NanoPi2 development board. ++ ++ If unsure, say N. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called it7260_mts.ko. ++ ++config TOUCHSCREEN_HIMAX ++ tristate "Himax touchscreen support" ++ depends on I2C ++ help ++ Say Y here if you have a Himax touchscreen and your ++ board-specific setup code includes that in its table ++ of I2C devices. ++ ++ If unsure, say N. ++ ++config TOUCHSCREEN_1WIRE ++ tristate "1-Wire host and Touch Screen Driver" ++ depends on ARCH_S5P6818 ++ help ++ Say Y here to enable the 1-Wire host and Touch Screen driver for ++ FriendlyARM NanoPi3 ++ ++ If unsure, say N. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called onewire. ++ ++config SENSOR_LOADER_1WIRE ++ tristate "Touch sensor loader for NanoPi M3" ++ depends on ARCH_S5P6818 ++ help ++ Loads appropriate touch sensor driver depend on panel ++ detected on onewire. ++ ++ If you have NanoPi and one of RGB panels from FriendlyArm ++ than say Y or M here. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called onewire-touch. ++ + endif +diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/input/touchscreen/Makefile ++++ b/drivers/input/touchscreen/Makefile +@@ -104,3 +104,7 @@ obj-$(CONFIG_TOUCHSCREEN_ZET6223) += zet6223.o + obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o + obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o + obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o ++obj-$(CONFIG_TOUCHSCREEN_IT7260) += it7260_mts.o ++obj-$(CONFIG_TOUCHSCREEN_HIMAX) += himax_ts.o ++obj-$(CONFIG_TOUCHSCREEN_1WIRE) += onewire.o ++obj-$(CONFIG_SENSOR_LOADER_1WIRE) += onewire-touch.o +diff --git a/drivers/input/touchscreen/himax_ts.c b/drivers/input/touchscreen/himax_ts.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/input/touchscreen/himax_ts.c @@ -0,0 +1,535 @@ +/* + * Touch Screen driver for Himax touchscreen controllers used in @@ -80134,9 +81315,11 @@ diff -ENwbur a/drivers/input/touchscreen/himax_ts.c b/drivers/input/touchscreen/ + +MODULE_DESCRIPTION("Himax Touchscreen driver"); +MODULE_LICENSE("GPL v2"); -diff -ENwbur a/drivers/input/touchscreen/it7260_mts.c b/drivers/input/touchscreen/it7260_mts.c ---- a/drivers/input/touchscreen/it7260_mts.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/input/touchscreen/it7260_mts.c 2018-05-06 08:49:49.882723986 +0200 +diff --git a/drivers/input/touchscreen/it7260_mts.c b/drivers/input/touchscreen/it7260_mts.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/input/touchscreen/it7260_mts.c @@ -0,0 +1,452 @@ +/* + * multi touch screen driver for it7260 @@ -80590,75 +81773,113 @@ diff -ENwbur a/drivers/input/touchscreen/it7260_mts.c b/drivers/input/touchscree +MODULE_AUTHOR("CJOK "); +MODULE_DESCRIPTION("it7260 touchscreen driver"); + -diff -ENwbur a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig ---- a/drivers/input/touchscreen/Kconfig 2018-05-06 08:47:37.033332109 +0200 -+++ b/drivers/input/touchscreen/Kconfig 2018-05-06 08:49:49.878723822 +0200 -@@ -1246,4 +1246,51 @@ - To compile this driver as a module, choose M here: the - module will be called bu21023_ts. - -+config TOUCHSCREEN_IT7260 -+ tristate "ITE it7260 TouchScreen driver" -+ depends on ARCH_S5P6818 -+ help -+ Say Y here to support ITE it7260 based touchscreen on -+ FriendlyARM NanoPi2 development board. +diff --git a/drivers/input/touchscreen/onewire-touch.c b/drivers/input/touchscreen/onewire-touch.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/input/touchscreen/onewire-touch.c +@@ -0,0 +1,96 @@ ++/* Registers appropriate touchscreen input device for NanoPi M3 ++ * based on LCD panel type connected to RGB connector. ++ * The panel type is reported by LCD panel on onewire channel. ++ */ + -+ If unsure, say N. ++#include ++#include ++#include ++#include ++#include + -+ To compile this driver as a module, choose M here: the -+ module will be called it7260_mts.ko. + -+config TOUCHSCREEN_HIMAX -+ tristate "Himax touchscreen support" -+ depends on I2C -+ help -+ Say Y here if you have a Himax touchscreen and your -+ board-specific setup code includes that in its table -+ of I2C devices. ++static int onewire_touch_probe(struct platform_device *pdev) ++{ ++ struct i2c_client *touchsensor; ++ struct i2c_board_info bdi; ++ struct i2c_adapter *adap; ++ struct device_node *i2c_bus_np; ++ const struct nanopi_panel_desc *panel_desc; + -+ If unsure, say N. ++ panel_desc = nanopi_panelrgb_get_connected(); ++ if( panel_desc == NULL || !panel_desc->i2c_touch_drv || ++ !strcmp(panel_desc->i2c_touch_drv, "onewire")) ++ return -ENODEV; ++ memset(&bdi, 0, sizeof(bdi)); ++ strlcpy(bdi.type, panel_desc->i2c_touch_drv, sizeof(bdi.type)); ++ bdi.addr = panel_desc->i2c_touch_reg; ++ bdi.irq = platform_get_irq(pdev, 0); ++ if( bdi.irq < 0 ) { ++ dev_err(&pdev->dev, "unable to get irq: %d\n", bdi.irq); ++ return bdi.irq; ++ } ++ i2c_bus_np = of_parse_phandle(pdev->dev.of_node, "i2c-bus", 0); ++ if( i2c_bus_np == NULL ) { ++ dev_err(&pdev->dev, "no i2c-bus property\n"); ++ return -EINVAL; ++ } ++ adap = of_find_i2c_adapter_by_node(i2c_bus_np); ++ of_node_put(i2c_bus_np); ++ if( adap == NULL ) { ++ dev_err(&pdev->dev, "i2c-bus for touch sensor not found\n"); ++ return -EPROBE_DEFER; ++ } ++ touchsensor = i2c_new_device(adap, &bdi); ++ put_device(&adap->dev); ++ if( touchsensor == NULL ) { ++ dev_err(&pdev->dev, "touch sensor registration error\n"); ++ return -ENXIO; ++ } ++ platform_set_drvdata(pdev, touchsensor); ++ dev_info(&pdev->dev, "probe success\n"); ++ return 0; ++} + -+config TOUCHSCREEN_1WIRE -+ tristate "1-Wire host and Touch Screen Driver" -+ depends on ARCH_S5P6818 -+ help -+ Say Y here to enable the 1-Wire host and Touch Screen driver for -+ FriendlyARM NanoPi3 ++static int onewire_touch_remove(struct platform_device *pdev) ++{ ++ struct i2c_client *touchsensor = platform_get_drvdata(pdev); + -+ If unsure, say N. ++ i2c_unregister_device(touchsensor); ++ dev_info(&pdev->dev, "removed\n"); ++ return 0; ++} + -+ To compile this driver as a module, choose M here: the -+ module will be called onewire. ++#ifdef CONFIG_OF ++static const struct of_device_id onewire_touch_of_match[] = { ++ { .compatible = "friendlyarm,onewire-touch" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, onewire_touch_of_match); ++#endif + -+config SENSOR_LOADER_1WIRE -+ tristate "Touch sensor loader for NanoPi M3" -+ depends on ARCH_S5P6818 -+ help -+ Loads appropriate touch sensor driver depend on panel -+ detected on onewire. ++struct platform_driver onewire_touch_platform_driver = { ++ .probe = onewire_touch_probe, ++ .remove = onewire_touch_remove, ++ .driver = { ++ .name = "onewire-touch", ++ .of_match_table = of_match_ptr(onewire_touch_of_match), ++ }, ++}; + -+ If you have NanoPi and one of RGB panels from FriendlyArm -+ than say Y or M here. ++static int __init onewire_touch_init(void) ++{ ++ return platform_driver_register(&onewire_touch_platform_driver); ++} + -+ To compile this driver as a module, choose M here: the -+ module will be called onewire-touch. ++static void __exit onewire_touch_exit(void) ++{ ++ platform_driver_unregister(&onewire_touch_platform_driver); ++} + - endif -diff -ENwbur a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile ---- a/drivers/input/touchscreen/Makefile 2018-05-06 08:47:37.033332109 +0200 -+++ b/drivers/input/touchscreen/Makefile 2018-05-06 08:49:49.878723822 +0200 -@@ -104,3 +104,7 @@ - obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o - obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o - obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o -+obj-$(CONFIG_TOUCHSCREEN_IT7260) += it7260_mts.o -+obj-$(CONFIG_TOUCHSCREEN_HIMAX) += himax_ts.o -+obj-$(CONFIG_TOUCHSCREEN_1WIRE) += onewire.o -+obj-$(CONFIG_SENSOR_LOADER_1WIRE) += onewire-touch.o -diff -ENwbur a/drivers/input/touchscreen/onewire.c b/drivers/input/touchscreen/onewire.c ---- a/drivers/input/touchscreen/onewire.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/input/touchscreen/onewire.c 2018-05-06 08:49:49.882723986 +0200 ++module_init(onewire_touch_init); ++module_exit(onewire_touch_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Rafaello7 "); ++MODULE_DESCRIPTION("FriendlyArm onewire touch sensor driver"); +diff --git a/drivers/input/touchscreen/onewire.c b/drivers/input/touchscreen/onewire.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/input/touchscreen/onewire.c @@ -0,0 +1,488 @@ +/* Onewire protocol support for touch panels from FriendlyARM + * Based on FriendlyARM driver for 3.x kernel. @@ -81148,112 +82369,13 @@ diff -ENwbur a/drivers/input/touchscreen/onewire.c b/drivers/input/touchscreen/o +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rafaello7 "); +MODULE_DESCRIPTION("FriendlyArm onewire protocol driver"); -diff -ENwbur a/drivers/input/touchscreen/onewire-touch.c b/drivers/input/touchscreen/onewire-touch.c ---- a/drivers/input/touchscreen/onewire-touch.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/input/touchscreen/onewire-touch.c 2018-05-06 08:49:49.882723986 +0200 -@@ -0,0 +1,96 @@ -+/* Registers appropriate touchscreen input device for NanoPi M3 -+ * based on LCD panel type connected to RGB connector. -+ * The panel type is reported by LCD panel on onewire channel. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+ -+static int onewire_touch_probe(struct platform_device *pdev) -+{ -+ struct i2c_client *touchsensor; -+ struct i2c_board_info bdi; -+ struct i2c_adapter *adap; -+ struct device_node *i2c_bus_np; -+ const struct nanopi_panel_desc *panel_desc; -+ -+ panel_desc = nanopi_panelrgb_get_connected(); -+ if( panel_desc == NULL || !panel_desc->i2c_touch_drv || -+ !strcmp(panel_desc->i2c_touch_drv, "onewire")) -+ return -ENODEV; -+ memset(&bdi, 0, sizeof(bdi)); -+ strlcpy(bdi.type, panel_desc->i2c_touch_drv, sizeof(bdi.type)); -+ bdi.addr = panel_desc->i2c_touch_reg; -+ bdi.irq = platform_get_irq(pdev, 0); -+ if( bdi.irq < 0 ) { -+ dev_err(&pdev->dev, "unable to get irq: %d\n", bdi.irq); -+ return bdi.irq; -+ } -+ i2c_bus_np = of_parse_phandle(pdev->dev.of_node, "i2c-bus", 0); -+ if( i2c_bus_np == NULL ) { -+ dev_err(&pdev->dev, "no i2c-bus property\n"); -+ return -EINVAL; -+ } -+ adap = of_find_i2c_adapter_by_node(i2c_bus_np); -+ of_node_put(i2c_bus_np); -+ if( adap == NULL ) { -+ dev_err(&pdev->dev, "i2c-bus for touch sensor not found\n"); -+ return -EPROBE_DEFER; -+ } -+ touchsensor = i2c_new_device(adap, &bdi); -+ put_device(&adap->dev); -+ if( touchsensor == NULL ) { -+ dev_err(&pdev->dev, "touch sensor registration error\n"); -+ return -ENXIO; -+ } -+ platform_set_drvdata(pdev, touchsensor); -+ dev_info(&pdev->dev, "probe success\n"); -+ return 0; -+} -+ -+static int onewire_touch_remove(struct platform_device *pdev) -+{ -+ struct i2c_client *touchsensor = platform_get_drvdata(pdev); -+ -+ i2c_unregister_device(touchsensor); -+ dev_info(&pdev->dev, "removed\n"); -+ return 0; -+} -+ -+#ifdef CONFIG_OF -+static const struct of_device_id onewire_touch_of_match[] = { -+ { .compatible = "friendlyarm,onewire-touch" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, onewire_touch_of_match); -+#endif -+ -+struct platform_driver onewire_touch_platform_driver = { -+ .probe = onewire_touch_probe, -+ .remove = onewire_touch_remove, -+ .driver = { -+ .name = "onewire-touch", -+ .of_match_table = of_match_ptr(onewire_touch_of_match), -+ }, -+}; -+ -+static int __init onewire_touch_init(void) -+{ -+ return platform_driver_register(&onewire_touch_platform_driver); -+} -+ -+static void __exit onewire_touch_exit(void) -+{ -+ platform_driver_unregister(&onewire_touch_platform_driver); -+} -+ -+module_init(onewire_touch_init); -+module_exit(onewire_touch_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Rafaello7 "); -+MODULE_DESCRIPTION("FriendlyArm onewire touch sensor driver"); -diff -ENwbur a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig ---- a/drivers/media/platform/Kconfig 2018-05-06 08:47:37.213339417 +0200 -+++ b/drivers/media/platform/Kconfig 2018-05-06 08:49:50.058731126 +0200 -@@ -615,3 +615,27 @@ +diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/media/platform/Kconfig ++++ b/drivers/media/platform/Kconfig +@@ -615,3 +615,27 @@ config VIDEO_RCAR_DRIF will be called rcar_drif. - + endif # SDR_PLATFORM_DRIVERS + +config VIDEO_NEXELL_CODEC @@ -81279,35 +82401,40 @@ diff -ENwbur a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig + Note that this layer is also available via drm, but it is unused + by X-window system. Using this layer by both drm and this device + may have unpredictable results. -diff -ENwbur a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile ---- a/drivers/media/platform/Makefile 2018-05-06 08:47:37.213339417 +0200 -+++ b/drivers/media/platform/Makefile 2018-05-06 08:49:50.058731126 +0200 -@@ -76,6 +76,8 @@ - +diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/media/platform/Makefile ++++ b/drivers/media/platform/Makefile +@@ -76,6 +76,8 @@ obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel/ + obj-$(CONFIG_VIDEO_STM32_DCMI) += stm32/ - + +obj-$(CONFIG_VIDEO_NEXELL_CODEC) += nxp-vpu/ + ccflags-y += -I$(srctree)/drivers/media/i2c - + obj-$(CONFIG_VIDEO_MEDIATEK_VPU) += mtk-vpu/ -@@ -90,4 +92,6 @@ - +@@ -90,4 +92,6 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss-8x16/ + obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/ - + +obj-$(CONFIG_NANO_VIDEODEV) += nano-videodev/ + obj-y += meson/ -diff -ENwbur a/drivers/media/platform/nano-videodev/Makefile b/drivers/media/platform/nano-videodev/Makefile ---- a/drivers/media/platform/nano-videodev/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nano-videodev/Makefile 2018-05-06 08:49:50.070731614 +0200 +diff --git a/drivers/media/platform/nano-videodev/Makefile b/drivers/media/platform/nano-videodev/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nano-videodev/Makefile @@ -0,0 +1,3 @@ +nano-videodev-objs := nano-videodev-v4l2.o s5pxx18_dp_dev.o s5pxx18_soc_mlc.o +obj-$(CONFIG_NANO_VIDEODEV) += nano-videodev.o + -diff -ENwbur a/drivers/media/platform/nano-videodev/nano-videodev-v4l2.c b/drivers/media/platform/nano-videodev/nano-videodev-v4l2.c ---- a/drivers/media/platform/nano-videodev/nano-videodev-v4l2.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nano-videodev/nano-videodev-v4l2.c 2018-05-06 08:49:50.070731614 +0200 +diff --git a/drivers/media/platform/nano-videodev/nano-videodev-v4l2.c b/drivers/media/platform/nano-videodev/nano-videodev-v4l2.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nano-videodev/nano-videodev-v4l2.c @@ -0,0 +1,1010 @@ +#include +#include @@ -82319,9 +83446,11 @@ diff -ENwbur a/drivers/media/platform/nano-videodev/nano-videodev-v4l2.c b/drive +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rafaello7 "); +MODULE_DESCRIPTION("Expose MLC video layer of s5p6818 as v4l2 device"); -diff -ENwbur a/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.c b/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.c ---- a/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.c 2018-05-06 08:49:50.070731614 +0200 +diff --git a/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.c b/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -82505,9 +83634,11 @@ diff -ENwbur a/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.c b/drivers/m + nx_mlc_set_layer_priority(module, priority); + nx_mlc_set_top_dirty_flag(module); +} -diff -ENwbur a/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.h b/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.h ---- a/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.h 2018-05-06 08:49:50.070731614 +0200 +diff --git a/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.h b/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -82565,9 +83696,11 @@ diff -ENwbur a/drivers/media/platform/nano-videodev/s5pxx18_dp_dev.h b/drivers/m +void nx_soc_dp_plane_video_set_dirty(int module); + +#endif /* __S5PXX18_DP_DEV_H__ */ -diff -ENwbur a/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.c b/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.c ---- a/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.c 2018-05-06 08:49:50.070731614 +0200 +diff --git a/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.c b/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.c @@ -0,0 +1,1818 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -84387,9 +85520,11 @@ diff -ENwbur a/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.c b/drivers/ + if (bottom) + *(int *)bottom = ((tb >> 0) & 0xFFUL); +} -diff -ENwbur a/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.h b/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.h ---- a/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.h 2018-05-06 08:49:50.070731614 +0200 +diff --git a/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.h b/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.h @@ -0,0 +1,431 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -84822,9 +85957,30 @@ diff -ENwbur a/drivers/media/platform/nano-videodev/s5pxx18_soc_mlc.h b/drivers/ + int *right, int *bottom); + +#endif -diff -ENwbur a/drivers/media/platform/nxp-vpu/blackbird_v2.3.10.h b/drivers/media/platform/nxp-vpu/blackbird_v2.3.10.h ---- a/drivers/media/platform/nxp-vpu/blackbird_v2.3.10.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/blackbird_v2.3.10.h 2018-05-06 08:49:50.074731776 +0200 +diff --git a/drivers/media/platform/nxp-vpu/Makefile b/drivers/media/platform/nxp-vpu/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/Makefile +@@ -0,0 +1,13 @@ ++ ++nxp-vpu-objs := nx_vpu_v4l2.o \ ++ nx_vpu_dec_v4l2.o \ ++ nx_vpu_enc_v4l2.o \ ++ nx_port_func.o \ ++ nx_vpu_api.o \ ++ nx_vpu_encoder.o \ ++ nx_vpu_decoder.o \ ++ nx_jpu_api.o \ ++ vpu_hw_interface.o \ ++ nx_vpu_gdi.o ++ ++obj-$(CONFIG_VIDEO_NEXELL_CODEC) += nxp-vpu.o +diff --git a/drivers/media/platform/nxp-vpu/blackbird_v2.3.10.h b/drivers/media/platform/nxp-vpu/blackbird_v2.3.10.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/blackbird_v2.3.10.h @@ -0,0 +1,15880 @@ +/*============================================================================== + * BIT ASSEMBLY CODE TABLE @@ -100706,26 +101862,11 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/blackbird_v2.3.10.h b/drivers/medi + 0xe190, 0xe190, 0xe190, 0xe190, 0xe190, 0xe190, 0xe190, 0xe190, + 0xe190, 0xe190, 0xe190, 0xe190, 0xe190, 0xe190, 0xe190, 0xe190, +}; -diff -ENwbur a/drivers/media/platform/nxp-vpu/Makefile b/drivers/media/platform/nxp-vpu/Makefile ---- a/drivers/media/platform/nxp-vpu/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/Makefile 2018-05-06 08:49:50.070731614 +0200 -@@ -0,0 +1,13 @@ -+ -+nxp-vpu-objs := nx_vpu_v4l2.o \ -+ nx_vpu_dec_v4l2.o \ -+ nx_vpu_enc_v4l2.o \ -+ nx_port_func.o \ -+ nx_vpu_api.o \ -+ nx_vpu_encoder.o \ -+ nx_vpu_decoder.o \ -+ nx_jpu_api.o \ -+ vpu_hw_interface.o \ -+ nx_vpu_gdi.o -+ -+obj-$(CONFIG_VIDEO_NEXELL_CODEC) += nxp-vpu.o -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_jpu_api.c b/drivers/media/platform/nxp-vpu/nx_jpu_api.c ---- a/drivers/media/platform/nxp-vpu/nx_jpu_api.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_jpu_api.c 2018-05-06 08:49:50.074731776 +0200 +diff --git a/drivers/media/platform/nxp-vpu/nx_jpu_api.c b/drivers/media/platform/nxp-vpu/nx_jpu_api.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_jpu_api.c @@ -0,0 +1,1787 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -102344,1160 +103485,182 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_jpu_api.c b/drivers/media/platf + int ecsPtr = pInfo->headerSize; + + pInfo->pagePtr = ecsPtr / 256; -+ pInfo->wordPtr = (ecsPtr % 256) / 4; -+ if (pInfo->pagePtr & 1) -+ pInfo->wordPtr += 64; -+ if (pInfo->wordPtr & 1) -+ pInfo->wordPtr -= 1; -+ -+ pInfo->bitPtr = (ecsPtr % 4) * 8; -+ if (((ecsPtr % 256) / 4) & 1) -+ pInfo->bitPtr += 32; -+ } -+ -+ /* Generate Huffman table information */ -+ for (i = 0; i < 4; i++) -+ GenerateJpegDecHuffmanTable(pInfo, i); -+ -+ pInfo->qIdx = (pInfo->infoTable[0][3] << 2) | -+ (pInfo->infoTable[1][3] << 1) | (pInfo->infoTable[2][3]); -+ pInfo->huffDcIdx = (pInfo->infoTable[0][4] << 2) | -+ (pInfo->infoTable[1][4] << 1) | (pInfo->infoTable[2][4]); -+ pInfo->huffAcIdx = (pInfo->infoTable[0][5] << 2) | -+ (pInfo->infoTable[1][5] << 1) | (pInfo->infoTable[2][5]); -+ -+ return 0; -+} -+ -+int JPU_DecRunFrame(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_frame_arg *pArg) -+{ -+ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; -+ unsigned int val, reason = 0; -+ int32_t i, idx; -+ const uint32_t *phyAddrs; -+ -+ for (i = 0 ; i <= pInfo->numFrameBuffer ; i++) { -+ idx = pInfo->decodeIdx + i; -+ -+ if (idx >= pInfo->numFrameBuffer) -+ idx -= pInfo->numFrameBuffer; -+ -+ if (pInfo->frmBufferValid[idx] == 0) { -+ pInfo->decodeIdx = idx; -+ phyAddrs = pInfo->phyAddrs.addr[idx]; -+ pArg->indexFrameDecoded = idx; -+ pArg->indexFrameDisplay = idx; -+ break; -+ } -+ } -+ -+ if (i > pInfo->numFrameBuffer) { -+ NX_ErrMsg(("Frame Buffer for Decoding is not sufficient!!!\n")); -+ return -1; -+ } -+ -+ VPU_SWReset(SW_RESET_SAFETY); -+ -+ VpuWriteReg(MJPEG_BBC_RD_PTR_REG, pInfo->strmBufPhyAddr); -+ VpuWriteReg(MJPEG_BBC_WR_PTR_REG, pInfo->writePos); -+ -+ VpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, pInfo->readPos); -+ VpuWriteReg(MJPEG_BBC_END_ADDR_REG, pInfo->writePos); -+ -+ VpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, 0); -+ -+ VpuWriteReg(MJPEG_GBU_TT_CNT_REG, 0); -+ VpuWriteReg(MJPEG_GBU_TT_CNT_REG+4, 0); -+ -+ VpuWriteReg(MJPEG_PIC_SIZE_REG, (pInfo->width << 16) | (pInfo->height)); -+ VpuWriteReg(MJPEG_PIC_CTRL_REG, (pInfo->huffAcIdx << 10) | -+ (pInfo->huffDcIdx << 7) | (pInfo->userHuffTable << 6) | -+ (1 << 2) | 0); -+ -+ VpuWriteReg(MJPEG_ROT_INFO_REG, 0); -+ -+ VpuWriteReg(MJPEG_MCU_INFO_REG, (pInfo->mcuBlockNum << 16) | -+ (pInfo->compNum << 12) | (pInfo->compInfo[0] << 8) | -+ (pInfo->compInfo[1] << 4) | (pInfo->compInfo[2])); -+ VpuWriteReg(MJPEG_OP_INFO_REG, pInfo->busReqNum); -+ -+ if (pArg->downScaleWidth || pArg->downScaleHeight) -+ VpuWriteReg(MJPEG_SCL_INFO_REG, (1 << 4) | -+ (pArg->downScaleWidth << 2) | (pArg->downScaleHeight)); -+ else -+ VpuWriteReg(MJPEG_SCL_INFO_REG, 0); -+ -+ VpuWriteReg(MJPEG_DPB_CONFIG_REG, VPU_FRAME_BUFFER_ENDIAN << 1 | -+ CBCR_INTERLEAVE); -+ VpuWriteReg(MJPEG_RST_INTVAL_REG, pInfo->rstInterval); -+ -+ SetJpegDecHuffmanTable(pInfo); -+ SetJpegDecQuantizationTable(pInfo); -+ -+ SetupJpegDecGram(pInfo); -+ -+ /* RST index at the beginning */ -+ VpuWriteReg(MJPEG_RST_INDEX_REG, 0); -+ VpuWriteReg(MJPEG_RST_COUNT_REG, 0); -+ -+ VpuWriteReg(MJPEG_DPCM_DIFF_Y_REG, 0); -+ VpuWriteReg(MJPEG_DPCM_DIFF_CB_REG, 0); -+ VpuWriteReg(MJPEG_DPCM_DIFF_CR_REG, 0); -+ -+ VpuWriteReg(MJPEG_GBU_FF_RPTR_REG, pInfo->bitPtr); -+ VpuWriteReg(MJPEG_GBU_CTRL_REG, 3); -+ -+ val = 0; /* gdi status */ -+ VpuWriteReg(GDI_CONTROL, 1); -+ while (!val) -+ val = VpuReadReg(GDI_STATUS); -+ -+ VpuWriteReg(GDI_INFO_CONTROL, (0 << 20) | (pInfo->imgFormat << 17) | -+ (CBCR_INTERLEAVE << 16) | (pInfo->strideY)); -+ -+ VpuWriteReg(GDI_INFO_PIC_SIZE, (pInfo->width << 16) | pInfo->height); -+ -+ VpuWriteReg(GDI_INFO_BASE_Y, phyAddrs[0]); -+ VpuWriteReg(GDI_INFO_BASE_CB, phyAddrs[1]); -+ VpuWriteReg(GDI_INFO_BASE_CR, phyAddrs[2]); -+ -+ VpuWriteReg(MJPEG_DPB_BASE00_REG, 0); -+ -+ VpuWriteReg(GDI_CONTROL, 0); -+ VpuWriteReg(GDI_PIC_INIT_HOST, 1); -+ -+ VpuWriteReg(MJPEG_PIC_START_REG, 1); -+ -+ reason = JPU_WaitInterrupt(pInst->devHandle, JPU_DEC_TIMEOUT); -+ if (!reason) { -+ NX_ErrMsg(("JPU_DecRunFrame() Failed. Timeout(%d)\n", -+ JPU_DEC_TIMEOUT)); -+ return VPU_RET_ERR_TIMEOUT; -+ } -+ -+ if (reason & (1 << INT_JPU_ERROR)) { -+ NX_ErrMsg(("JPU Decode Error(reason = 0x%08x)\n", reason)); -+ return VPU_RET_ERROR; -+ } -+ if (reason & (1 << INT_JPU_BBC_INTERRUPT)) { -+ NX_ErrMsg(("JPU BBC Interrupt Error(reason = 0x%08x)\n", -+ reason)); -+ return VPU_RET_ERROR; -+ } -+ if (reason & (1 << INT_JPU_BIT_BUF_FULL)) { -+ NX_ErrMsg(("JPU Overflow Error( reason = 0x%08x)\n", reason)); -+ return VPU_RET_ERR_STRM_FULL; -+ } -+ if (!(reason & (1 << INT_JPU_DONE))) -+ return VPU_RET_ERR_RUN; -+ -+ pArg->outWidth = pInfo->width >> pArg->downScaleWidth; -+ pArg->outHeight = pInfo->height >> pArg->downScaleHeight; -+ pArg->mcuWidth = pInfo->mcuWidth; -+ pArg->mcuHeight = pInfo->mcuHeight; -+ pArg->outRect.left = 0; -+ pArg->outRect.top = 0; -+ pArg->outRect.right = pArg->outWidth; -+ pArg->outRect.bottom = pArg->outHeight; -+ pArg->numOfErrMBs = VpuReadReg(MJPEG_PIC_ERRMB_REG); -+ -+ pInfo->readPos = VpuReadReg(pInfo->streamRdPtrRegAddr); -+ pArg->strmReadPos = pInfo->readPos - pInfo->strmBufPhyAddr; -+ pArg->strmWritePos = pInfo->writePos - pInfo->strmBufPhyAddr; -+ -+ pInfo->frmBufferValid[idx] = -1; -+ -+ VpuWriteReg(MJPEG_BBC_FLUSH_CMD_REG, 0); -+ -+ VPU_SWReset(SW_RESET_SAFETY); -+ -+ return VPU_RET_OK; -+} -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_port_func.c b/drivers/media/platform/nxp-vpu/nx_port_func.c ---- a/drivers/media/platform/nxp-vpu/nx_port_func.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_port_func.c 2018-05-06 08:49:50.074731776 +0200 -@@ -0,0 +1,201 @@ -+/* -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * Author: Seonghee, Kim -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "nx_port_func.h" -+ -+ -+struct nx_memory_info *nx_alloc_memory(void *drv, int32_t size, int32_t align) -+{ -+ struct nx_memory_info *handle; -+ -+ handle = devm_kzalloc(drv, sizeof(*handle), GFP_KERNEL); -+ if (NULL == handle) -+ goto Error_Exit; -+ -+#ifndef USE_ION_MEMORY -+ handle->virAddr = dma_alloc_coherent(drv, size, &handle->phyAddr, -+ GFP_KERNEL); -+ if (!handle->virAddr) { -+ handle->phyAddr = 0; -+ goto Error_Exit; -+ } -+#else -+ size = (size + 4095) & ~4095; -+ handle->phyAddr = cma_alloc(drv, "nxp-ion", size, align); -+ if (handle->phyAddr == (-EINVAL)) { -+ dev_err(drv, "nx_alloc_memory is error\n"); -+ handle->phyAddr = 0; -+ goto Error_Exit; -+ } -+ -+ handle->virAddr = (void *)cma_get_virt(handle->phyAddr, size, 1); -+ if (handle->virAddr == 0) { -+ dev_err(drv, "Failed to cma_get_virt(0x%08x)\n", -+ (int)handle->phyAddr); -+ goto Error_Exit; -+ } -+#endif -+ -+ NX_DrvMemset(handle->virAddr, 0, size); -+ -+ handle->fd = drv; -+ handle->size = size; -+ handle->align = align; -+ -+ return handle; -+ -+Error_Exit: -+ dev_err(drv, "nx_alloc_memory is failed\n"); -+ -+ if (handle) { -+ if (handle->phyAddr) { -+#ifndef USE_ION_MEMORY -+ dma_free_coherent(drv, handle->size, handle->virAddr, -+ handle->phyAddr); -+#else -+ cma_free(handle->phyAddr); -+#endif -+ } -+ } -+ -+ return NULL; -+} -+ -+void nx_free_memory(struct nx_memory_info *mem) -+{ -+ if (mem) { -+ if (0 != mem->phyAddr) { -+#ifndef USE_ION_MEMORY -+ dma_free_coherent(mem->fd, mem->size, mem->virAddr, -+ mem->phyAddr); -+#else -+ cma_free(mem->phyAddr); -+#endif -+ } -+ } -+} -+ -+struct nx_vid_memory_info *nx_alloc_frame_memory(void *drv, int32_t width, -+ int32_t height, int32_t planes, uint32_t format, int32_t align) -+{ -+ int32_t i, chroma_planes; -+ int32_t lWidth, lHeight; -+ int32_t cWidth, cHeight; -+ uint32_t lSize; /* Luminance plane size */ -+ uint32_t cSize; /* Chrominance plane size */ -+ struct nx_vid_memory_info *vid = NULL; -+ struct nx_memory_info *mem[NX_MAX_PLANES]; -+ -+ vid = devm_kzalloc(drv, sizeof(*vid), GFP_KERNEL); -+ if (NULL == vid) -+ goto Error_Exit; -+ -+ for (i = 0 ; i < NX_MAX_PLANES ; i++) -+ mem[i] = NULL; -+ -+ lWidth = ALIGN(width, 32); -+ lHeight = ALIGN(height, 16); -+ lSize = lWidth * lHeight; -+ -+ switch (format) { -+ case V4L2_PIX_FMT_YUV420M: -+ cWidth = ALIGN(width/2, 16); -+ cHeight = ALIGN(height/2, 16); -+ chroma_planes = 2; -+ break; -+ case V4L2_PIX_FMT_NV12M: -+ cWidth = lWidth; -+ cHeight = lHeight/2; -+ chroma_planes = 1; -+ break; -+ default: -+ NX_ErrMsg(("Unknown fourCC type.\n")); -+ goto Error_Exit; -+ } -+ cSize = cWidth * cHeight; -+ -+ mem[0] = nx_alloc_memory(drv, lSize, align); -+ for (i = 1 ; i <= chroma_planes ; i++) -+ mem[i] = nx_alloc_memory(drv, cSize, align); -+ -+ vid->width = width; -+ vid->height = height; -+ vid->align = align; -+ vid->planes = planes; -+ vid->format = format; -+ -+ for (i = 0 ; i <= chroma_planes ; i++) { -+ vid->fd[i] = mem[i]->fd; -+ vid->size[i] = mem[i]->size; -+ vid->strideY = lWidth; -+ vid->virAddr[i] = mem[i]->virAddr; -+ vid->phyAddr[i] = mem[i]->phyAddr; -+ } -+ -+ return vid; -+ -+Error_Exit: -+ if (vid) { -+ for (i = 0 ; i < planes ; i++) -+ nx_free_memory(mem[i]); -+ } -+ -+ return NULL; -+} -+ -+void nx_free_frame_memory(struct nx_vid_memory_info *vid) -+{ -+ if (vid) { -+ int32_t i; -+ -+ for (i = 0 ; i < vid->planes ; i++) { -+#ifndef USE_ION_MEMORY -+ dma_free_coherent(vid->fd[i], vid->size[i], -+ vid->virAddr[i], vid->phyAddr[i]); -+#else -+ cma_free(vid->phyAddr[i]); -+#endif -+ } -+ -+ } -+} -+ -+void NX_DrvMemset(void *ptr, int value, int size) -+{ -+ memset(ptr, value, size); -+} -+ -+void NX_DrvMemcpy(void *dst, void *src, int size) -+{ -+ memcpy(dst, src, size); -+} -+ -+void DrvMSleep(unsigned int mSeconds) -+{ -+ msleep(mSeconds); -+} -+ -+void DrvUSleep(unsigned int uSeconds) -+{ -+ udelay(uSeconds); -+} -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_port_func.h b/drivers/media/platform/nxp-vpu/nx_port_func.h ---- a/drivers/media/platform/nxp-vpu/nx_port_func.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_port_func.h 2018-05-06 08:49:50.074731776 +0200 -@@ -0,0 +1,106 @@ -+/* -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * Author: Seonghee, Kim -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef __NX_ALLOC_MEM_H__ -+#define __NX_ALLOC_MEM_H__ -+ -+#include -+#include -+ -+ -+/* #define USE_ION_MEMORY */ -+ -+#define FUNC_MSG 0 -+ -+ -+#ifndef NX_DTAG -+#define NX_DTAG "[DRV|VPU]" -+#endif -+ -+#define NX_DbgMsg(COND, MSG) do { \ -+ if (COND) { \ -+ printk(NX_DTAG); \ -+ pr_cont MSG; \ -+ } \ -+ } while (0) -+ -+#define NX_ErrMsg(MSG) do { \ -+ printk("%s%s(%d): ", NX_DTAG, __FILE__,\ -+ __LINE__); \ -+ pr_cont MSG; \ -+ } while (0) -+ -+#if FUNC_MSG -+ #define FUNC_IN() printk("%s() %d IN.\n", __func__, __LINE__) -+ #define FUNC_OUT() printk("%s() %d OUT.\n", __func__, __LINE__) -+#else -+ #define FUNC_IN() do {} while (0) -+ #define FUNC_OUT() do {} while (0) -+#endif -+ -+#define NX_MAX_PLANES 4 -+ -+ -+/* -+ * struct nx_memory_info - nexell private memory type -+ */ -+struct nx_memory_info { -+ void *fd; -+ int32_t size; -+ int32_t align; -+ void *virAddr; -+ dma_addr_t phyAddr; -+}; -+ -+/* -+ * struct nx_vid_memory_info - nexell private video memory type -+ */ -+struct nx_vid_memory_info { -+ int32_t width; -+ int32_t height; -+ int32_t align; -+ int32_t planes; -+ uint32_t format; /* Pixel Format(N/A) */ -+ int32_t strideY; /* Luma plane stride */ -+ -+ void *fd[NX_MAX_PLANES]; -+ int32_t size[NX_MAX_PLANES]; /* Each plane's size. */ -+ void *virAddr[NX_MAX_PLANES]; -+ uint32_t phyAddr[NX_MAX_PLANES]; -+}; -+ -+/* -+ * nexell private memory allocator -+ */ -+struct nx_memory_info *nx_alloc_memory(void *drv, int32_t size, int32_t align); -+void nx_free_memory(struct nx_memory_info *mem); -+ -+/* -+ * video specific allocator wrapper -+ */ -+struct nx_vid_memory_info *nx_alloc_frame_memory(void *drv, int32_t width, -+ int32_t height, int32_t planes, uint32_t format, int32_t align); -+void nx_free_frame_memory(struct nx_vid_memory_info *vid); -+ -+void NX_DrvMemset(void *ptr, int value, int size); -+void NX_DrvMemcpy(void *dst, void *src, int size); -+ -+void DrvMSleep(unsigned int mSeconds); -+void DrvUSleep(unsigned int uSeconds); -+ -+#endif /* __NX_ALLOC_MEM_H__ */ -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_api.c b/drivers/media/platform/nxp-vpu/nx_vpu_api.c ---- a/drivers/media/platform/nxp-vpu/nx_vpu_api.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_vpu_api.c 2018-05-06 08:49:50.074731776 +0200 -@@ -0,0 +1,661 @@ -+/* -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * Author: Seonghee, Kim -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef UNUSED -+#define UNUSED(p) ((void)(p)) -+#endif -+ -+#include -+#include -+ -+#include -+ -+#include "blackbird_v2.3.10.h" -+#include "vpu_hw_interface.h" /* Register Access */ -+#include "nx_vpu_api.h" -+ -+ -+#define DBG_POWER 0 -+#define DBG_CLOCK 0 -+#define INFO_MSG 0 -+ -+ -+/*--------------------------------------------------------------------------- */ -+/* Static Global Variables */ -+static int gstIsInitialized; -+static int gstIsVPUOn; -+static unsigned int gstVpuRegStore[64]; -+ -+static uint32_t *gstCodaClockEnRegVir; -+static uint32_t *gstIsolateBase; -+static uint32_t *gstAliveBase; -+ -+ -+static struct nx_vpu_codec_inst gstVpuInstance[NX_MAX_VPU_INSTANCE]; -+ -+ -+/*--------------------------------------------------------------------------- */ -+/* Define Static Functions */ -+static unsigned int VPU_IsBusy(void); -+ -+ -+/*---------------------------------------------------------------------------- -+ * Nexell Specific VPU Hardware On/Off Logic -+ *--------------------------------------------------------------------------- */ -+#define VPU_ALIVEGATE_REG 0xC0010800 -+#define VPU_NISOLATE_REG 0xC0010D00 -+#define CODA960CLKENB_REG 0xC00C7000 -+ -+#define POWER_PMU_VPU_MASK 0x00000002 -+ -+#if defined(CONFIG_ARCH_S5P6818) -+/* Async XUI Power Down -+ * -+ * Step 1. Waiting until CACTIVE to High -+ * Step 2. Set CSYSREQ to Low -+ * Step 3. Waiting until CSYSACK to Low -+ */ -+static void NX_ASYNCXUI_PowerDown(void) -+{ -+ int32_t tmpVal; -+ -+ FUNC_IN(); -+ -+ /* Apply To Async XUI 0 */ -+ -+ /* Step 1. Waiting until CACTIVE to High */ -+ do { -+ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU0_CACTIVE_S); -+ } while (!tmpVal); -+ -+ /* Step 2. Set CSYSREQ to Low */ -+ nx_tieoff_set(NX_TIEOFF_Inst_ASYNCXUI0_CSYSREQ, 0); -+ -+ /*Step 3. Waiting until CSYSACK to Low */ -+ do { -+ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU0_CSYSACK_S); -+ } while (tmpVal); -+ -+ /* Apply To Async XUI 1 */ -+ -+ /* Step 1. Waiting until CACTIVE to High */ -+ do { -+ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU1_CACTIVE_S); -+ } while (!tmpVal); -+ -+ /* Step 2. Set CSYSREQ to Low */ -+ nx_tieoff_set(NX_TIEOFF_Inst_ASYNCXUI1_CSYSREQ, 0); -+ -+ /* Step 3. Waiting until CSYSACK to Low */ -+ do { -+ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU1_CSYSACK_S); -+ } while (tmpVal); -+ -+ -+ FUNC_OUT(); -+} -+ -+/* Async XUI Power Up -+ * -+ * Step 1. Set CSYSREQ to High -+ * Step 2. Waiting until CSYSACK to High -+ */ -+static void NX_ASYNCXUI_PowerUp(void) -+{ -+ int32_t tmpVal; -+ -+ FUNC_IN(); -+ -+ /* Apply To Async XUI 0 */ -+ -+ /* Step 1. Set CSYSREQ to High */ -+ nx_tieoff_set(NX_TIEOFF_Inst_ASYNCXUI0_CSYSREQ, 1); -+ -+ /* Step 2. Waiting until CSYSACK to High */ -+ do { -+ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU0_CSYSACK_S); -+ } while (!tmpVal); -+ -+ /* Apply To Async XUI 1 */ -+ -+ /* Step 1. Set CSYSREQ to High */ -+ nx_tieoff_set(NX_TIEOFF_Inst_ASYNCXUI1_CSYSREQ, 1); -+ -+ /* Step 2. Waiting until CSYSACK to High */ -+ do { -+ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU1_CSYSACK_S); -+ } while (!tmpVal); -+ -+ FUNC_OUT(); -+} -+#endif -+ -+void NX_VPU_HwOn(void *dev, void *pVpuBaseAddr) -+{ -+ uint32_t tmpVal; -+ uint32_t *pNPreCharge, *pNPowerUp, *pNPowerAck; -+ -+ NX_DbgMsg(DBG_POWER, ("NX_VPU_HwOn() ++\n")); -+ -+ /* Already Power On */ -+ if (gstIsVPUOn) -+ return; -+ -+ vpu_soc_peri_reset_enter(dev); -+ -+ InitVpuRegister(pVpuBaseAddr); -+ -+ /* Initialize ISolate Register's */ -+ pNPreCharge = gstIsolateBase + 1; -+ pNPowerUp = gstIsolateBase + 2; -+ pNPowerAck = gstIsolateBase + 3; -+ -+ NX_DbgMsg(INFO_MSG, ("====================================\n")); -+ NX_DbgMsg(INFO_MSG, ("pVpuBaseAddr = %p\n", pVpuBaseAddr)); -+ NX_DbgMsg(INFO_MSG, ("pIsolateBase = %p\n", gstIsolateBase)); -+ NX_DbgMsg(INFO_MSG, ("pNPreCharge = %p\n", pNPreCharge)); -+ NX_DbgMsg(INFO_MSG, ("pNPowerUp = %p\n", pNPowerUp)); -+ NX_DbgMsg(INFO_MSG, ("pNPowerAck = %p\n", pNPowerAck)); -+ NX_DbgMsg(INFO_MSG, ("====================================\n")); -+ -+ WriteReg32(gstAliveBase, 0x3); -+ -+ /* Enable PreCharge */ -+ tmpVal = ReadReg32(pNPreCharge); -+ tmpVal &= (~POWER_PMU_VPU_MASK); -+ WriteReg32(pNPreCharge, tmpVal); -+ -+ /* Enable Power On */ -+ tmpVal = ReadReg32(pNPowerUp); -+ tmpVal &= (~POWER_PMU_VPU_MASK); -+ WriteReg32(pNPowerUp, tmpVal); -+ -+ /* Disable ISolate */ -+ tmpVal = ReadReg32(gstIsolateBase); -+ tmpVal |= (POWER_PMU_VPU_MASK); -+ WriteReg32(gstIsolateBase, tmpVal); -+ -+ mdelay(1); -+ -+ NX_VPU_Clock(1); -+ -+#if defined(CONFIG_ARCH_S5P6818) -+ NX_ASYNCXUI_PowerUp(); -+#endif -+ -+ vpu_soc_peri_reset_exit(dev); -+ -+ gstIsVPUOn = 1; -+ -+ -+ NX_DbgMsg(DBG_POWER, ("NX_VPU_HwOn() --\n")); -+} -+ -+void NX_VPU_HWOff(void *dev) -+{ -+ FUNC_IN(); -+ -+ if (gstIsVPUOn) { -+ unsigned int tmpVal; -+ uint32_t *pNPreCharge, *pNPowerUp, *pNPowerAck; -+ -+#if defined(CONFIG_ARCH_S5P6818) -+ NX_ASYNCXUI_PowerDown(); -+#endif -+ /* H/W Reset */ -+ vpu_soc_peri_reset_enter(dev); -+ -+ NX_DbgMsg(DBG_POWER, ("NX_VPU_HWOff() ++\n")); -+ -+ /* Initialize ISolate Register's */ -+ pNPreCharge = gstIsolateBase + 1; -+ pNPowerUp = gstIsolateBase + 2; -+ pNPowerAck = gstIsolateBase + 3; -+ -+ /* Enter Coda Reset State */ -+ WriteReg32(gstAliveBase, 0x3); -+ -+ /* Isolate VPU H/W */ -+ tmpVal = ReadReg32(gstIsolateBase); -+ tmpVal &= (~POWER_PMU_VPU_MASK); -+ WriteReg32(gstIsolateBase, tmpVal); -+ -+ /* Pre Charget Off */ -+ tmpVal = ReadReg32(pNPreCharge); -+ tmpVal |= POWER_PMU_VPU_MASK; -+ WriteReg32(pNPreCharge, tmpVal); -+ -+ /* Power Down */ -+ tmpVal = ReadReg32(pNPowerUp); -+ tmpVal |= POWER_PMU_VPU_MASK; -+ WriteReg32(pNPowerUp, tmpVal); -+ -+ /* Isolate VPU H/W */ -+ tmpVal = ReadReg32(gstIsolateBase); -+ tmpVal &= (~POWER_PMU_VPU_MASK); -+ WriteReg32(gstIsolateBase, tmpVal); -+ -+ gstIsVPUOn = 0; -+ -+ NX_DbgMsg(DBG_POWER, ("NX_VPU_HWOff() --\n")); -+ } -+ -+ FUNC_OUT(); -+} -+ -+int NX_VPU_GetCurPowerState(void) -+{ -+ return gstIsVPUOn; -+} -+ -+void NX_VPU_Clock(int on) -+{ -+ FUNC_IN(); -+ -+ if (on) { -+ WriteReg32(gstCodaClockEnRegVir, 0x0000000F); -+ NX_DbgMsg(DBG_CLOCK, ("NX_VPU_Clock() ON\n")); -+ } else { -+ WriteReg32(gstCodaClockEnRegVir, 0x00000000); -+ NX_DbgMsg(DBG_CLOCK, ("NX_VPU_Clock() OFF\n")); -+ } -+ -+ FUNC_OUT(); -+} -+ -+static unsigned int VPU_IsBusy(void) -+{ -+ unsigned int ret = ReadRegNoMsg(BIT_BUSY_FLAG); -+ -+ return ret != 0; -+} -+ -+static int VPU_WaitBusBusy(int mSeconds, unsigned int busyFlagReg) -+{ -+ while (mSeconds > 0) { -+ if (0x77 == VpuReadReg(busyFlagReg)) -+ return VPU_RET_OK; -+ DrvMSleep(1); -+ mSeconds--; -+ } -+ return VPU_RET_ERR_TIMEOUT; -+} -+ -+int VPU_WaitVpuBusy(int mSeconds, unsigned int busyFlagReg) -+{ -+ while (mSeconds > 0) { -+ if (ReadRegNoMsg(busyFlagReg) == 0) -+ return VPU_RET_OK; -+ -+ DrvMSleep(1); -+ mSeconds--; -+ } -+ return VPU_RET_ERR_TIMEOUT; -+} -+ -+void VPU_GetVersionInfo(unsigned int *versionInfo, unsigned int *revision, -+ unsigned int *productId) -+{ -+ unsigned int ver; -+ unsigned int rev; -+ unsigned int pid; -+ -+ if (versionInfo && revision) { -+ VpuWriteReg(RET_FW_VER_NUM, 0); -+ VpuWriteReg(BIT_WORK_BUF_ADDR, 0); -+ VpuWriteReg(BIT_BUSY_FLAG, 1); -+ VpuWriteReg(BIT_RUN_INDEX, 0); -+ VpuWriteReg(BIT_RUN_COD_STD, 0); -+ VpuWriteReg(BIT_RUN_AUX_STD, 0); -+ VpuWriteReg(BIT_RUN_COMMAND, FIRMWARE_GET); -+ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, -+ BIT_BUSY_FLAG)) { -+ NX_ErrMsg(("Version Read Failed!!!\n")); -+ return; -+ } -+ -+ ver = VpuReadReg(RET_FW_VER_NUM); -+ rev = VpuReadReg(RET_FW_CODE_REV); -+ -+ *versionInfo = ver; -+ *revision = rev; -+ } -+ -+ pid = VpuReadReg(DBG_CONFIG_REPORT_1); -+ if ((pid&0xff00) == 0x3200) -+ pid = 0x3200; -+ -+ if (productId) -+ *productId = pid; -+} -+ -+void CheckVersion(void) -+{ -+ unsigned int version; -+ unsigned int revision; -+ unsigned int productId; -+ -+ VPU_GetVersionInfo(&version, &revision, &productId); -+ -+ NX_DbgMsg(INFO_MSG, ("Firmware Version => projectId : %x | ", -+ (unsigned int)(version>>16))); -+ NX_DbgMsg(INFO_MSG, ("version : %04d.%04d.%08d | revision : r%d\n", -+ (unsigned int)((version>>(12))&0x0f), -+ (unsigned int)((version>>(8))&0x0f), -+ (unsigned int)((version)&0xff), -+ revision)); -+ NX_DbgMsg(INFO_MSG, ("Hardware Version => %04x\n", productId)); -+} -+ -+ -+/*--------------------------------------------------------------------------- */ -+ -+/* VPU_SWReset -+ * IN -+ * forcedReset : 1 if there is no need to waiting for BUS transaction, -+ * 0 for otherwise -+ * OUT -+ * RetCode : RETCODE_FAILURE if failed to reset, -+ * RETCODE_SUCCESS for otherwise -+ */ -+ -+/* SW Reset command */ -+#define VPU_SW_RESET_BPU_CORE 0x008 -+#define VPU_SW_RESET_BPU_BUS 0x010 -+#define VPU_SW_RESET_VCE_CORE 0x020 -+#define VPU_SW_RESET_VCE_BUS 0x040 -+#define VPU_SW_RESET_GDI_CORE 0x080 -+#define VPU_SW_RESET_GDI_BUS 0x100 -+ -+int VPU_SWReset(int resetMode) -+{ -+ unsigned int cmd; -+ -+ if (resetMode == SW_RESET_SAFETY || resetMode == SW_RESET_ON_BOOT) { -+ /* Waiting for completion of bus transaction */ -+ /* Step1 : No more request */ -+ /* no more request {3'b0,no_more_req_sec,3'b0,no_more_req} */ -+ VpuWriteReg(GDI_BUS_CTRL, 0x11); -+ -+ /* Step2 : Waiting for completion of bus transaction */ -+ /* while (VpuReadReg(coreIdx, GDI_BUS_STATUS) != 0x77) */ -+ if (VPU_WaitBusBusy(VPU_BUSY_CHECK_TIMEOUT, GDI_BUS_STATUS) == -+ VPU_RET_ERR_TIMEOUT) { -+ VpuWriteReg(GDI_BUS_CTRL, 0x00); -+ return VPU_RET_ERR_TIMEOUT; -+ } -+ -+ /* Step3 : clear GDI_BUS_CTRL */ -+ VpuWriteReg(GDI_BUS_CTRL, 0x00); -+ } -+ -+ cmd = 0; -+ /* Software Reset Trigger */ -+ if (resetMode != SW_RESET_ON_BOOT) -+ cmd = VPU_SW_RESET_BPU_CORE | VPU_SW_RESET_BPU_BUS; -+ cmd |= VPU_SW_RESET_VCE_CORE | VPU_SW_RESET_VCE_BUS; -+ if (resetMode == SW_RESET_ON_BOOT) -+ /* If you reset GDI, tiled map should be reconfigured */ -+ cmd |= VPU_SW_RESET_GDI_CORE | VPU_SW_RESET_GDI_BUS; -+ VpuWriteReg(BIT_SW_RESET, cmd); -+ -+ /* wait until reset is done */ -+ if (VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, BIT_SW_RESET_STATUS) == -+ VPU_RET_ERR_TIMEOUT) { -+ VpuWriteReg(BIT_SW_RESET, 0x00); -+ return VPU_RET_ERR_TIMEOUT; -+ } -+ -+ VpuWriteReg(BIT_SW_RESET, 0); -+ -+ return VPU_RET_OK; -+} -+ -+/*---------------------------------------------------------------------------- -+ * VPU Initialization. -+ *--------------------------------------------------------------------------- */ -+int NX_VpuInit(void *dev, void *baseAddr, void *firmVirAddr, -+ uint32_t firmPhyAddr) -+{ -+ enum nx_vpu_ret ret = VPU_RET_OK; -+ int32_t i; -+ uint32_t tmpData; -+ uint32_t codeBufAddr, tmpBufAddr, paramBufAddr; -+ -+ if (gstIsInitialized) -+ return VPU_RET_OK; -+ -+ codeBufAddr = firmPhyAddr; -+ tmpBufAddr = codeBufAddr + CODE_BUF_SIZE; -+ paramBufAddr = tmpBufAddr + TEMP_BUF_SIZE; -+ -+ NX_VPU_HwOn(dev, baseAddr); -+ -+ /* if BIT processor is not running. */ -+ if (VpuReadReg(BIT_CUR_PC) == 0) { -+ for (i = 0; i < 64; i++) -+ VpuWriteReg(BIT_BASE + 0x100 + (i*4), 0x0); -+ } -+ -+ VPU_SWReset(SW_RESET_ON_BOOT); -+ -+ { -+ unsigned char *dst = (unsigned char *)firmVirAddr; -+ -+ for (i = 0; i < ARRAY_SIZE(bit_code) ; i += 4) { -+ *dst++ = (unsigned char)(bit_code[i+3] >> 0); -+ *dst++ = (unsigned char)(bit_code[i+3] >> 8); -+ -+ *dst++ = (unsigned char)(bit_code[i+2] >> 0); -+ *dst++ = (unsigned char)(bit_code[i+2] >> 8); -+ -+ *dst++ = (unsigned char)(bit_code[i+1] >> 0); -+ *dst++ = (unsigned char)(bit_code[i+1] >> 8); -+ -+ *dst++ = (unsigned char)(bit_code[i+0] >> 0); -+ *dst++ = (unsigned char)(bit_code[i+0] >> 8); -+ } -+ } -+ -+ VpuWriteReg(BIT_INT_ENABLE, 0); -+ VpuWriteReg(BIT_CODE_RUN, 0); -+ -+ for (i = 0 ; i < 2048 ; i++) { -+ tmpData = bit_code[i]; -+ WriteRegNoMsg(BIT_CODE_DOWN, (i<<16)|tmpData); -+ } -+ -+ VpuWriteReg(BIT_PARA_BUF_ADDR, paramBufAddr); -+ VpuWriteReg(BIT_CODE_BUF_ADDR, codeBufAddr); -+ VpuWriteReg(BIT_TEMP_BUF_ADDR, tmpBufAddr); -+ -+ VpuWriteReg(BIT_BIT_STREAM_CTRL, VPU_STREAM_ENDIAN); -+ -+ /* Interleave bit position is modified */ -+ VpuWriteReg(BIT_FRAME_MEM_CTRL, CBCR_INTERLEAVE<<2|VPU_FRAME_ENDIAN); -+ -+ VpuWriteReg(BIT_BIT_STREAM_PARAM, 0); -+ -+ VpuWriteReg(BIT_AXI_SRAM_USE, 0); -+ VpuWriteReg(BIT_INT_ENABLE, 0); -+ VpuWriteReg(BIT_ROLLBACK_STATUS, 0); -+ -+ tmpData = (1<wordPtr = (ecsPtr % 256) / 4; ++ if (pInfo->pagePtr & 1) ++ pInfo->wordPtr += 64; ++ if (pInfo->wordPtr & 1) ++ pInfo->wordPtr -= 1; + -+ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, -+ BIT_BUSY_FLAG)) { -+ NX_ErrMsg(("NX_VpuInit() Failed. Timeout(%d)\n", -+ VPU_BUSY_CHECK_TIMEOUT)); -+ return ret; ++ pInfo->bitPtr = (ecsPtr % 4) * 8; ++ if (((ecsPtr % 256) / 4) & 1) ++ pInfo->bitPtr += 32; + } + -+ CheckVersion(); ++ /* Generate Huffman table information */ ++ for (i = 0; i < 4; i++) ++ GenerateJpegDecHuffmanTable(pInfo, i); + -+ for (i = 0 ; i < NX_MAX_VPU_INSTANCE ; i++) { -+ gstVpuInstance[i].inUse = 0; -+ gstVpuInstance[i].paramPhyAddr = paramBufAddr; -+ gstVpuInstance[i].paramVirAddr = firmVirAddr + -+ CODE_BUF_SIZE + TEMP_BUF_SIZE; -+ gstVpuInstance[i].paramBufSize = PARA_BUF_SIZE; -+ } -+ gstIsInitialized = 1; ++ pInfo->qIdx = (pInfo->infoTable[0][3] << 2) | ++ (pInfo->infoTable[1][3] << 1) | (pInfo->infoTable[2][3]); ++ pInfo->huffDcIdx = (pInfo->infoTable[0][4] << 2) | ++ (pInfo->infoTable[1][4] << 1) | (pInfo->infoTable[2][4]); ++ pInfo->huffAcIdx = (pInfo->infoTable[0][5] << 2) | ++ (pInfo->infoTable[1][5] << 1) | (pInfo->infoTable[2][5]); + -+ return ret; ++ return 0; +} + -+int NX_VpuDeInit(void *dev) ++int JPU_DecRunFrame(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_frame_arg *pArg) +{ -+ if (!gstIsInitialized) { -+ NX_ErrMsg(("VPU Already Denitialized!!!\n")); -+ return VPU_RET_ERR_INIT; ++ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; ++ unsigned int val, reason = 0; ++ int32_t i, idx; ++ const uint32_t *phyAddrs; ++ ++ for (i = 0 ; i <= pInfo->numFrameBuffer ; i++) { ++ idx = pInfo->decodeIdx + i; ++ ++ if (idx >= pInfo->numFrameBuffer) ++ idx -= pInfo->numFrameBuffer; ++ ++ if (pInfo->frmBufferValid[idx] == 0) { ++ pInfo->decodeIdx = idx; ++ phyAddrs = pInfo->phyAddrs.addr[idx]; ++ pArg->indexFrameDecoded = idx; ++ pArg->indexFrameDisplay = idx; ++ break; ++ } + } + -+ if (VPU_IsBusy()) { -+ NX_ErrMsg(("NX_VpuDeInit: VPU_IsBusy!!!\n")); ++ if (i > pInfo->numFrameBuffer) { ++ NX_ErrMsg(("Frame Buffer for Decoding is not sufficient!!!\n")); ++ return -1; + } + -+ NX_VPU_HWOff(dev); ++ VPU_SWReset(SW_RESET_SAFETY); + -+ gstIsInitialized = 0; -+ return VPU_RET_OK; -+} ++ VpuWriteReg(MJPEG_BBC_RD_PTR_REG, pInfo->strmBufPhyAddr); ++ VpuWriteReg(MJPEG_BBC_WR_PTR_REG, pInfo->writePos); + -+int NX_VpuSuspend(void *dev) -+{ -+ int i; ++ VpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, pInfo->readPos); ++ VpuWriteReg(MJPEG_BBC_END_ADDR_REG, pInfo->writePos); + -+ if (!gstIsInitialized) -+ return VPU_RET_ERR_INIT; ++ VpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, 0); + -+ if (VPU_IsBusy()) -+ return VPU_RET_BUSY; -+ for (i = 0 ; i < 64 ; i++) -+ gstVpuRegStore[i] = VpuReadReg(BIT_BASE+0x100 + (i * 4)); ++ VpuWriteReg(MJPEG_GBU_TT_CNT_REG, 0); ++ VpuWriteReg(MJPEG_GBU_TT_CNT_REG+4, 0); + -+ NX_VPU_HWOff(dev); ++ VpuWriteReg(MJPEG_PIC_SIZE_REG, (pInfo->width << 16) | (pInfo->height)); ++ VpuWriteReg(MJPEG_PIC_CTRL_REG, (pInfo->huffAcIdx << 10) | ++ (pInfo->huffDcIdx << 7) | (pInfo->userHuffTable << 6) | ++ (1 << 2) | 0); + -+ return VPU_RET_OK; -+} ++ VpuWriteReg(MJPEG_ROT_INFO_REG, 0); + -+int NX_VpuResume(void *dev, void *pVpuBaseAddr) -+{ -+ int i; -+ unsigned int value; ++ VpuWriteReg(MJPEG_MCU_INFO_REG, (pInfo->mcuBlockNum << 16) | ++ (pInfo->compNum << 12) | (pInfo->compInfo[0] << 8) | ++ (pInfo->compInfo[1] << 4) | (pInfo->compInfo[2])); ++ VpuWriteReg(MJPEG_OP_INFO_REG, pInfo->busReqNum); + -+ if (!gstIsInitialized) -+ return VPU_RET_ERR_INIT; ++ if (pArg->downScaleWidth || pArg->downScaleHeight) ++ VpuWriteReg(MJPEG_SCL_INFO_REG, (1 << 4) | ++ (pArg->downScaleWidth << 2) | (pArg->downScaleHeight)); ++ else ++ VpuWriteReg(MJPEG_SCL_INFO_REG, 0); + -+ NX_VPU_HwOn(dev, pVpuBaseAddr); ++ VpuWriteReg(MJPEG_DPB_CONFIG_REG, VPU_FRAME_BUFFER_ENDIAN << 1 | ++ CBCR_INTERLEAVE); ++ VpuWriteReg(MJPEG_RST_INTVAL_REG, pInfo->rstInterval); + -+ VPU_SWReset(SW_RESET_ON_BOOT); ++ SetJpegDecHuffmanTable(pInfo); ++ SetJpegDecQuantizationTable(pInfo); + -+ for (i = 0 ; i < 64 ; i++) -+ VpuWriteReg(BIT_BASE+0x100+(i * 4), gstVpuRegStore[i]); ++ SetupJpegDecGram(pInfo); + -+ VpuWriteReg(BIT_CODE_RUN, 0); -+ /* Bit Code */ -+ for (i = 0; i < 2048; i++) { -+ value = bit_code[i]; -+ VpuWriteReg(BIT_CODE_DOWN, ((i << 16) | value)); -+ } ++ /* RST index at the beginning */ ++ VpuWriteReg(MJPEG_RST_INDEX_REG, 0); ++ VpuWriteReg(MJPEG_RST_COUNT_REG, 0); + -+ VpuWriteReg(BIT_BUSY_FLAG, 1); -+ VpuWriteReg(BIT_CODE_RESET, 1); -+ VpuWriteReg(BIT_CODE_RUN, 1); ++ VpuWriteReg(MJPEG_DPCM_DIFF_Y_REG, 0); ++ VpuWriteReg(MJPEG_DPCM_DIFF_CB_REG, 0); ++ VpuWriteReg(MJPEG_DPCM_DIFF_CR_REG, 0); + -+ VpuWriteReg(BIT_USE_NX_EXPND, USE_NX_EXPND); ++ VpuWriteReg(MJPEG_GBU_FF_RPTR_REG, pInfo->bitPtr); ++ VpuWriteReg(MJPEG_GBU_CTRL_REG, 3); + -+ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, -+ BIT_BUSY_FLAG)) { -+ NX_ErrMsg(("NX_VpuResume() Failed. Timeout(%d)\n", -+ VPU_BUSY_CHECK_TIMEOUT)); -+ return VPU_RET_ERR_TIMEOUT; -+ } ++ val = 0; /* gdi status */ ++ VpuWriteReg(GDI_CONTROL, 1); ++ while (!val) ++ val = VpuReadReg(GDI_STATUS); + -+ return VPU_RET_OK; -+} ++ VpuWriteReg(GDI_INFO_CONTROL, (0 << 20) | (pInfo->imgFormat << 17) | ++ (CBCR_INTERLEAVE << 16) | (pInfo->strideY)); + -+struct nx_vpu_codec_inst *NX_VpuGetInstance(int index) -+{ -+ return &gstVpuInstance[index]; -+} ++ VpuWriteReg(GDI_INFO_PIC_SIZE, (pInfo->width << 16) | pInfo->height); + -+int NX_VpuIsInitialized(void) -+{ -+ return gstIsInitialized; -+} ++ VpuWriteReg(GDI_INFO_BASE_Y, phyAddrs[0]); ++ VpuWriteReg(GDI_INFO_BASE_CB, phyAddrs[1]); ++ VpuWriteReg(GDI_INFO_BASE_CR, phyAddrs[2]); + -+int swap_endian(unsigned char *data, int len) -+{ -+ unsigned int *p; -+ unsigned int v1, v2, v3; -+ int i; -+ int swap = 0; ++ VpuWriteReg(MJPEG_DPB_BASE00_REG, 0); + -+ p = (unsigned int *)data; ++ VpuWriteReg(GDI_CONTROL, 0); ++ VpuWriteReg(GDI_PIC_INIT_HOST, 1); + -+ for (i = 0; i < len/4; i += 2) { -+ v1 = p[i]; -+ v2 = (v1 >> 24) & 0xFF; -+ v2 |= ((v1 >> 16) & 0xFF) << 8; -+ v2 |= ((v1 >> 8) & 0xFF) << 16; -+ v2 |= ((v1 >> 0) & 0xFF) << 24; -+ v3 = v2; -+ v1 = p[i+1]; -+ v2 = (v1 >> 24) & 0xFF; -+ v2 |= ((v1 >> 16) & 0xFF) << 8; -+ v2 |= ((v1 >> 8) & 0xFF) << 16; -+ v2 |= ((v1 >> 0) & 0xFF) << 24; -+ p[i] = v2; -+ p[i+1] = v3; ++ VpuWriteReg(MJPEG_PIC_START_REG, 1); ++ ++ reason = JPU_WaitInterrupt(pInst->devHandle, JPU_DEC_TIMEOUT); ++ if (!reason) { ++ NX_ErrMsg(("JPU_DecRunFrame() Failed. Timeout(%d)\n", ++ JPU_DEC_TIMEOUT)); ++ return VPU_RET_ERR_TIMEOUT; + } + -+ return swap; -+} ++ if (reason & (1 << INT_JPU_ERROR)) { ++ NX_ErrMsg(("JPU Decode Error(reason = 0x%08x)\n", reason)); ++ return VPU_RET_ERROR; ++ } ++ if (reason & (1 << INT_JPU_BBC_INTERRUPT)) { ++ NX_ErrMsg(("JPU BBC Interrupt Error(reason = 0x%08x)\n", ++ reason)); ++ return VPU_RET_ERROR; ++ } ++ if (reason & (1 << INT_JPU_BIT_BUF_FULL)) { ++ NX_ErrMsg(("JPU Overflow Error( reason = 0x%08x)\n", reason)); ++ return VPU_RET_ERR_STRM_FULL; ++ } ++ if (!(reason & (1 << INT_JPU_DONE))) ++ return VPU_RET_ERR_RUN; + -+int NX_VpuParaInitialized(void *dev) -+{ -+ gstIsInitialized = 0; -+ gstIsVPUOn = 0; ++ pArg->outWidth = pInfo->width >> pArg->downScaleWidth; ++ pArg->outHeight = pInfo->height >> pArg->downScaleHeight; ++ pArg->mcuWidth = pInfo->mcuWidth; ++ pArg->mcuHeight = pInfo->mcuHeight; ++ pArg->outRect.left = 0; ++ pArg->outRect.top = 0; ++ pArg->outRect.right = pArg->outWidth; ++ pArg->outRect.bottom = pArg->outHeight; ++ pArg->numOfErrMBs = VpuReadReg(MJPEG_PIC_ERRMB_REG); + -+ gstCodaClockEnRegVir = (uint32_t *)devm_ioremap_nocache(dev, -+ CODA960CLKENB_REG, 4); -+ if (!gstCodaClockEnRegVir) -+ return -1; ++ pInfo->readPos = VpuReadReg(pInfo->streamRdPtrRegAddr); ++ pArg->strmReadPos = pInfo->readPos - pInfo->strmBufPhyAddr; ++ pArg->strmWritePos = pInfo->writePos - pInfo->strmBufPhyAddr; + -+ gstIsolateBase = (uint32_t *)devm_ioremap_nocache(dev, -+ VPU_NISOLATE_REG, 128); -+ gstAliveBase = (uint32_t *)devm_ioremap_nocache(dev, -+ VPU_ALIVEGATE_REG, 128); -+ if (!gstIsolateBase || !gstAliveBase) -+ return -1; ++ pInfo->frmBufferValid[idx] = -1; + -+ return 0; ++ VpuWriteReg(MJPEG_BBC_FLUSH_CMD_REG, 0); ++ ++ VPU_SWReset(SW_RESET_SAFETY); ++ ++ return VPU_RET_OK; +} -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_api.h b/drivers/media/platform/nxp-vpu/nx_vpu_api.h ---- a/drivers/media/platform/nxp-vpu/nx_vpu_api.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_vpu_api.h 2018-05-06 08:49:50.074731776 +0200 -@@ -0,0 +1,541 @@ +diff --git a/drivers/media/platform/nxp-vpu/nx_port_func.c b/drivers/media/platform/nxp-vpu/nx_port_func.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_port_func.c +@@ -0,0 +1,201 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * Author: Seonghee, Kim @@ -103516,1900 +103679,1637 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_api.h b/drivers/media/platf + * along with this program. If not, see . + */ + -+#ifndef __NX_VPU_API_H__ -+#define __NX_VPU_API_H__ -+ ++#include ++#include ++#include ++#include ++#include +#include "nx_port_func.h" -+#include "vpu_types.h" -+#include "nx_vpu_config.h" -+#include -+ -+/* Codec Mode */ -+enum { -+ AVC_DEC = 0, -+ VC1_DEC = 1, -+ MP2_DEC = 2, -+ MP4_DEC = 3, -+ DV3_DEC = 3, -+ RV_DEC = 4, -+ AVS_DEC = 5, -+ MJPG_DEC = 6, -+ VPX_DEC = 7, -+ -+ AVC_ENC = 8, -+ MP4_ENC = 11, -+ MJPG_ENC = 13 -+}; + -+/* MPEG4 Aux Mode */ -+enum { -+ MP4_AUX_MPEG4 = 0, -+ MP4_AUX_DIVX3 = 1 -+}; + -+/* VPX Aux Mode */ -+enum { -+ VPX_AUX_THO = 0, -+ VPX_AUX_VP6 = 1, -+ VPX_AUX_VP8 = 2 -+}; ++struct nx_memory_info *nx_alloc_memory(void *drv, int32_t size, int32_t align) ++{ ++ struct nx_memory_info *handle; + -+/* AVC Aux Mode */ -+enum { -+ AVC_AUX_AVC = 0, -+ AVC_AUX_MVC = 1 -+}; ++ handle = devm_kzalloc(drv, sizeof(*handle), GFP_KERNEL); ++ if (NULL == handle) ++ goto Error_Exit; + -+/* Interrupt Register Bit Enumerate */ -+enum { -+ VPU_INT_BIT_INIT = 0, -+ VPU_INT_BIT_SEQ_INIT = 1, -+ VPU_INT_BIT_SEQ_END = 2, -+ VPU_INT_BIT_PIC_RUN = 3, -+ VPU_INT_BIT_FRAMEBUF_SET = 4, -+ VPU_INT_BIT_ENC_HEADER = 5, -+ VPU_INT_BIT_DEC_PARA_SET = 7, -+ VPU_INT_BIT_DEC_BUF_FLUSH = 8, -+ VPU_INT_BIT_USERDATA = 9, -+ VPU_INT_BIT_DEC_FIELD = 10, -+ VPU_INT_BIT_DEC_MB_ROWS = 13, -+ VPU_INT_BIT_BIT_BUF_EMPTY = 14, -+ VPU_INT_BIT_BIT_BUF_FULL = 15 -+}; ++#ifndef USE_ION_MEMORY ++ handle->virAddr = dma_alloc_coherent(drv, size, &handle->phyAddr, ++ GFP_KERNEL); ++ if (!handle->virAddr) { ++ handle->phyAddr = 0; ++ goto Error_Exit; ++ } ++#else ++ size = (size + 4095) & ~4095; ++ handle->phyAddr = cma_alloc(drv, "nxp-ion", size, align); ++ if (handle->phyAddr == (-EINVAL)) { ++ dev_err(drv, "nx_alloc_memory is error\n"); ++ handle->phyAddr = 0; ++ goto Error_Exit; ++ } + -+enum { -+ SW_RESET_SAFETY, -+ SW_RESET_FORCE, -+ SW_RESET_ON_BOOT -+}; ++ handle->virAddr = (void *)cma_get_virt(handle->phyAddr, size, 1); ++ if (handle->virAddr == 0) { ++ dev_err(drv, "Failed to cma_get_virt(0x%08x)\n", ++ (int)handle->phyAddr); ++ goto Error_Exit; ++ } ++#endif + -+enum nx_vpu_bit_chg_para { -+ VPU_BIT_CHG_GOP = 1, /* GOP */ -+ VPU_BIT_CHG_INTRAQP = (1 << 1), /* Intra Qp */ -+ VPU_BIT_CHG_BITRATE = (1 << 2), /* Bit Rate */ -+ VPU_BIT_CHG_FRAMERATE = (1 << 3), /* Frame Rate */ -+ VPU_BIT_CHG_INTRARF = (1 << 4), /* Intra Refresh */ -+ VPU_BIT_CHG_SLICEMOD = (1 << 5), /* Slice Mode */ -+ VPU_BIT_CHG_HECMODE = (1 << 6), /* HEC Mode */ -+}; ++ NX_DrvMemset(handle->virAddr, 0, size); + -+enum bit_stream_mode { -+ BS_MODE_INTERRUPT, -+ BS_MODE_ROLLBACK, -+ BS_MODE_PIC_END -+}; ++ handle->fd = drv; ++ handle->size = size; ++ handle->align = align; + -+enum mp4_header_type { -+ VOL_HEADER, -+ VOS_HEADER, -+ VIS_HEADER -+}; ++ return handle; + -+enum avc_header_type { -+ SPS_RBSP, -+ PPS_RBSP, -+ END_SEQ_RBSP, -+ END_STREAM_RBSP, -+ SPS_RBSP_MVC, -+ PPS_RBSP_MVC, -+}; ++Error_Exit: ++ dev_err(drv, "nx_alloc_memory is failed\n"); + -+/* Define VPU Low-Level Return Value */ -+enum nx_vpu_ret { -+ VPU_RET_ERR_STRM_FULL = -24, /* Bitstream Full */ -+ VPU_RET_ERR_SRAM = -23, /* VPU SRAM Configruation Failed */ -+ VPU_RET_ERR_INST = -22, /* VPU Have No Instance Space */ -+ VPU_RET_BUSY = -21, /* VPU H/W Busy */ -+ VPU_RET_ERR_TIMEOUT = -20, /* VPU Wait Timeout */ -+ VPU_RET_ERR_MEM_ACCESS = -19, /* Memory Access Violation */ ++ if (handle) { ++ if (handle->phyAddr) { ++#ifndef USE_ION_MEMORY ++ dma_free_coherent(drv, handle->size, handle->virAddr, ++ handle->phyAddr); ++#else ++ cma_free(handle->phyAddr); ++#endif ++ } ++ } + -+ VPU_RET_ERR_CHG_PARAM = -6, /* VPU Not Changed */ -+ VPU_RET_ERR_WRONG_SEQ = -5, /* Wrong Sequence */ -+ VPU_RET_ERR_PARAM = -4, /* VPU Invalid Parameter */ -+ VPU_RET_ERR_RUN = -3, -+ VPU_RET_ERR_INIT = -2, /* VPU Not Initialized */ -+ VPU_RET_ERROR = -1, /* General operation failed */ -+ VPU_RET_OK = 0, -+ VPU_RET_NEED_STREAM = 1, /* Need More Stream */ -+}; ++ return NULL; ++} + ++void nx_free_memory(struct nx_memory_info *mem) ++{ ++ if (mem) { ++ if (0 != mem->phyAddr) { ++#ifndef USE_ION_MEMORY ++ dma_free_coherent(mem->fd, mem->size, mem->virAddr, ++ mem->phyAddr); ++#else ++ cma_free(mem->phyAddr); ++#endif ++ } ++ } ++} + -+/* Common Memory Information */ ++struct nx_vid_memory_info *nx_alloc_frame_memory(void *drv, int32_t width, ++ int32_t height, int32_t planes, uint32_t format, int32_t align) ++{ ++ int32_t i, chroma_planes; ++ int32_t lWidth, lHeight; ++ int32_t cWidth, cHeight; ++ uint32_t lSize; /* Luminance plane size */ ++ uint32_t cSize; /* Chrominance plane size */ ++ struct nx_vid_memory_info *vid = NULL; ++ struct nx_memory_info *mem[NX_MAX_PLANES]; + -+struct sec_axi_info { -+ int useBitEnable; -+ int useIpEnable; -+ int useDbkYEnable; -+ int useDbkCEnable; -+ int useOvlEnable; -+ int useBtpEnable; -+ unsigned int bufBitUse; -+ unsigned int bufIpAcDcUse; -+ unsigned int bufDbkYUse; -+ unsigned int bufDbkCUse; -+ unsigned int bufOvlUse; -+ unsigned int bufBtpUse; -+ int bufSize; -+}; ++ vid = devm_kzalloc(drv, sizeof(*vid), GFP_KERNEL); ++ if (NULL == vid) ++ goto Error_Exit; + -+struct enc_mp4_param { -+ int mp4DataPartitionEnable; -+ int mp4ReversibleVlcEnable; -+ int mp4IntraDcVlcThr; -+ int mp4HecEnable; -+ int mp4Verid; -+}; ++ for (i = 0 ; i < NX_MAX_PLANES ; i++) ++ mem[i] = NULL; + -+struct enc_h263_param { -+ int h263AnnexIEnable; -+ int h263AnnexJEnable; -+ int h263AnnexKEnable; -+ int h263AnnexTEnable; -+}; ++ lWidth = ALIGN(width, 32); ++ lHeight = ALIGN(height, 16); ++ lSize = lWidth * lHeight; + -+struct enc_avc_param { -+ /* CMD_ENC_SEQ_264_PARA Register (0x1A0) */ -+ int chromaQpOffset; /* bit [4:0] */ -+ int constrainedIntraPredFlag; /* bit [5] */ -+ int disableDeblk; /* bit [7:6] */ -+ int deblkFilterOffsetAlpha; /* bit [11:8] */ -+ int deblkFilterOffsetBeta; /* bit [15:12] */ ++ switch (format) { ++ case V4L2_PIX_FMT_YUV420M: ++ cWidth = ALIGN(width/2, 16); ++ cHeight = ALIGN(height/2, 16); ++ chroma_planes = 2; ++ break; ++ case V4L2_PIX_FMT_NV12M: ++ cWidth = lWidth; ++ cHeight = lHeight/2; ++ chroma_planes = 1; ++ break; ++ default: ++ NX_ErrMsg(("Unknown fourCC type.\n")); ++ goto Error_Exit; ++ } ++ cSize = cWidth * cHeight; + -+ /* CMD_ENC_SEQ_OPTION Register */ -+ int audEnable; /* bit[2] AUD(Access Unit Delimiter) */ ++ mem[0] = nx_alloc_memory(drv, lSize, align); ++ for (i = 1 ; i <= chroma_planes ; i++) ++ mem[i] = nx_alloc_memory(drv, cSize, align); + -+ /* Crop Info */ -+ int enableCrop; -+ int cropLeft; -+ int cropTop; -+ int cropRight; -+ int cropBottom; -+}; ++ vid->width = width; ++ vid->height = height; ++ vid->align = align; ++ vid->planes = planes; ++ vid->format = format; + -+struct enc_jpeg_info { -+ int picWidth; -+ int picHeight; -+ int alignedWidth; -+ int alignedHeight; -+ int frameIdx; -+ int format; ++ for (i = 0 ; i <= chroma_planes ; i++) { ++ vid->fd[i] = mem[i]->fd; ++ vid->size[i] = mem[i]->size; ++ vid->strideY = lWidth; ++ vid->virAddr[i] = mem[i]->virAddr; ++ vid->phyAddr[i] = mem[i]->phyAddr; ++ } + -+ int rotationEnable; -+ int rotationAngle; -+ int mirrorEnable; -+ int mirrorDirection; ++ return vid; + -+ int rstIntval; -+ int busReqNum; -+ int mcuBlockNum; -+ int compNum; -+ int compInfo[3]; ++Error_Exit: ++ if (vid) { ++ for (i = 0 ; i < planes ; i++) ++ nx_free_memory(mem[i]); ++ } + -+ unsigned int huffCode[4][256]; -+ unsigned int huffSize[4][256]; -+ unsigned char huffVal[4][162]; -+ unsigned char huffBits[4][256]; -+ unsigned char qMatTab[4][64]; -+ unsigned char cInfoTab[4][6]; ++ return NULL; ++} + -+ uint8_t jpegHeader[1024]; -+ int32_t headerSize; -+}; ++void nx_free_frame_memory(struct nx_vid_memory_info *vid) ++{ ++ if (vid) { ++ int32_t i; + -+struct vpu_enc_info { -+ int codecStd; ++ for (i = 0 ; i < vid->planes ; i++) { ++#ifndef USE_ION_MEMORY ++ dma_free_coherent(vid->fd[i], vid->size[i], ++ vid->virAddr[i], vid->phyAddr[i]); ++#else ++ cma_free(vid->phyAddr[i]); ++#endif ++ } + -+ /* input picture */ -+ int srcWidth; -+ int srcHeight; ++ } ++} + -+ /* encoding image size */ -+ int encWidth; -+ int encHeight; ++void NX_DrvMemset(void *ptr, int value, int size) ++{ ++ memset(ptr, value, size); ++} + -+ int gopSize; -+ int bitRate; -+ int frameRateNum; /* framerate */ -+ int frameRateDen; ++void NX_DrvMemcpy(void *dst, void *src, int size) ++{ ++ memcpy(dst, src, size); ++} + -+ int rotateAngle; /* 0/90/180/270 */ -+ int mirrorDirection; /* 0/1/2/3 */ ++void DrvMSleep(unsigned int mSeconds) ++{ ++ msleep(mSeconds); ++} + -+ int sliceMode; -+ int sliceSizeMode; -+ int sliceSize; ++void DrvUSleep(unsigned int uSeconds) ++{ ++ udelay(uSeconds); ++} +diff --git a/drivers/media/platform/nxp-vpu/nx_port_func.h b/drivers/media/platform/nxp-vpu/nx_port_func.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_port_func.h +@@ -0,0 +1,106 @@ ++/* ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * Author: Seonghee, Kim ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ + -+ int bwbEnable; -+ int cbcrInterleave; /* Input Frame's CbCrInterleave */ -+ int cbcrInterleaveRefFrame; /* Reference Frame's CbCrInterleave */ -+ int frameEndian; ++#ifndef __NX_ALLOC_MEM_H__ ++#define __NX_ALLOC_MEM_H__ + -+ int frameQp; -+ int jpegQuality; ++#include ++#include + -+ /* Frame Buffers */ -+ int minFrameBuffers; -+ int frameBufMapType; -+ struct nx_vid_memory_info frameBuffer[3]; -+ uint64_t subSampleAPhyAddr; -+ uint64_t subSampleBPhyAddr; -+ struct sec_axi_info sec_axi_info; -+ /* for CMD_SET_FRAME_CACHE_CONFIG register */ -+ unsigned int cacheConfig; + -+ /* Mpeg4 Encoder Only (for data partition) */ -+ uint64_t usbSampleDPPhyAddr; -+ uint32_t usbSampleDPSize; ++/* #define USE_ION_MEMORY */ + -+ int linear2TiledEnable; ++#define FUNC_MSG 0 + -+ /* Output Stream Buffer's Address & Size */ -+ uint64_t strmBufVirAddr; -+ uint64_t strmBufPhyAddr; -+ int strmBufSize; + -+ unsigned int ringBufferEnable; -+ unsigned int strmWritePrt; /* Bitstream Write Ptr */ -+ unsigned int strmReadPrt; /* Bitstream Read Ptr */ -+ unsigned int strmEndFlag; /* Bitstream End Flag */ ++#ifndef NX_DTAG ++#define NX_DTAG "[DRV|VPU]" ++#endif + -+ int userQpMax; /* User Max Quantization */ -+ int userGamma; /* User Gamma Factor */ ++#define NX_DbgMsg(COND, MSG) do { \ ++ if (COND) { \ ++ printk(NX_DTAG); \ ++ pr_cont MSG; \ ++ } \ ++ } while (0) + -+ /* Rate Control */ -+ int rcEnable; /* Rate Control Enable */ -+ int rcIntraQp; ++#define NX_ErrMsg(MSG) do { \ ++ printk("%s%s(%d): ", NX_DTAG, __FILE__,\ ++ __LINE__); \ ++ pr_cont MSG; \ ++ } while (0) + -+ /* (MB Mode(0), Frame Mode(1), Slice Mode(2), MB-NumMode(3) */ -+ int rcIntervalMode; -+ int mbInterval; -+ int rcIntraCostWeigth; -+ int enableAutoSkip; -+ int initialDelay; -+ int vbvBufSize; -+ int intraRefresh; ++#if FUNC_MSG ++ #define FUNC_IN() printk("%s() %d IN.\n", __func__, __LINE__) ++ #define FUNC_OUT() printk("%s() %d OUT.\n", __func__, __LINE__) ++#else ++ #define FUNC_IN() do {} while (0) ++ #define FUNC_OUT() do {} while (0) ++#endif + -+ union { -+ struct enc_avc_param avcEncParam; -+ struct enc_mp4_param mp4EncParam; -+ struct enc_h263_param h263EncParam; -+ struct enc_jpeg_info jpgEncInfo; -+ } enc_codec_para; ++#define NX_MAX_PLANES 4 + -+ /* Motion Estimation */ -+ int MEUseZeroPmv; -+ int MESearchRange; -+ int MEBlockMode; -+}; + -+struct low_delay_info { -+ int lowDelayEn; -+ int numRows; ++/* ++ * struct nx_memory_info - nexell private memory type ++ */ ++struct nx_memory_info { ++ void *fd; ++ int32_t size; ++ int32_t align; ++ void *virAddr; ++ dma_addr_t phyAddr; +}; + -+struct vpu_dec_info { -+ int codecStd; -+ -+ int width; -+ int height; -+ -+ /* Input Stream Buffer Address */ -+ uint64_t streamRdPtrRegAddr; /* BIT_RD_PTR or MJPEG_BBC_RD_PTR_REG */ -+ uint64_t streamWrPtrRegAddr; /* BIT_WR_PTR or MJPEG_BBC_WR_PTR_REG */ -+ uint64_t frameDisplayFlagRegAddr; -+ -+ uint64_t strmBufPhyAddr; -+ uint64_t strmBufVirAddr; -+ int needMoreFrame; -+ int strmBufSize; -+ int bitStreamMode; -+ -+ int bwbEnable; -+ int cbcrInterleave; -+ -+ int seqInitEscape; -+ -+ /* User Data */ -+ int userDataEnable; -+ int userDataReportMode; -+ uint64_t userDataBufPhyAddr; -+ uint64_t userDataBufVirAddr; -+ int userDataBufSize; -+ -+ /* Low Dealy Information */ -+ struct low_delay_info low_delay_info; -+ -+ unsigned int readPos; -+ unsigned int writePos; -+ -+ /* Frame Buffer Information (Instance Global) */ -+ int numFrameBuffer; -+ uint32_t strideY; -+ struct vpu_dec_phy_addr_info phyAddrs; -+ struct sec_axi_info sec_axi_info; -+ /* for CMD_SET_FRAME_CACHE_CONFIG register */ -+ int cacheConfig; ++/* ++ * struct nx_vid_memory_info - nexell private video memory type ++ */ ++struct nx_vid_memory_info { ++ int32_t width; ++ int32_t height; ++ int32_t align; ++ int32_t planes; ++ uint32_t format; /* Pixel Format(N/A) */ ++ int32_t strideY; /* Luma plane stride */ + -+ int bytePosFrameStart; -+ int bytePosFrameEnd; ++ void *fd[NX_MAX_PLANES]; ++ int32_t size[NX_MAX_PLANES]; /* Each plane's size. */ ++ void *virAddr[NX_MAX_PLANES]; ++ uint32_t phyAddr[NX_MAX_PLANES]; ++}; + -+ /* Options */ -+ int enableReordering; /* enable reordering */ -+ int enableMp4Deblock; /* Mpeg4 Deblocking Option */ ++/* ++ * nexell private memory allocator ++ */ ++struct nx_memory_info *nx_alloc_memory(void *drv, int32_t size, int32_t align); ++void nx_free_memory(struct nx_memory_info *mem); + -+ /* MPEG-4/Divx5.0 or Higher/XVID/Divx4.0/old XVID -+ (Compress Type --> class) */ -+ int mp4Class; ++/* ++ * video specific allocator wrapper ++ */ ++struct nx_vid_memory_info *nx_alloc_frame_memory(void *drv, int32_t width, ++ int32_t height, int32_t planes, uint32_t format, int32_t align); ++void nx_free_frame_memory(struct nx_vid_memory_info *vid); + -+ /* VC1 Specific Information */ -+ int vc1BframeDisplayValid; ++void NX_DrvMemset(void *ptr, int value, int size); ++void NX_DrvMemcpy(void *dst, void *src, int size); + -+ /* AVC Specific Information */ -+ int avcErrorConcealMode; ++void DrvMSleep(unsigned int mSeconds); ++void DrvUSleep(unsigned int uSeconds); + -+ int frameDelay; -+ int streamEndflag; -+ int streamEndian; -+ int frameDisplayFlag; -+ int clearDisplayIndexes; ++#endif /* __NX_ALLOC_MEM_H__ */ +diff --git a/drivers/media/platform/nxp-vpu/nx_vpu_api.c b/drivers/media/platform/nxp-vpu/nx_vpu_api.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_vpu_api.c +@@ -0,0 +1,661 @@ ++/* ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * Author: Seonghee, Kim ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ + -+ /* Jpeg Specific Information */ -+ int frmBufferValid[MAX_REG_FRAME]; ++#ifndef UNUSED ++#define UNUSED(p) ((void)(p)) ++#endif + -+ unsigned int headerSize; -+ int thumbnailMode; -+ int decodeIdx; ++#include ++#include + -+ int imgFormat; -+ int rstInterval; -+ int userHuffTable; ++#include + -+ unsigned char huffBits[4][256]; -+ unsigned char huffPtr[4][16]; -+ unsigned int huffMin[4][16]; -+ unsigned int huffMax[4][16]; ++#include "blackbird_v2.3.10.h" ++#include "vpu_hw_interface.h" /* Register Access */ ++#include "nx_vpu_api.h" + -+ unsigned char huffValue[4][162]; -+ unsigned char infoTable[4][6]; -+ unsigned char quantTable[4][64]; + -+ int huffDcIdx; -+ int huffAcIdx; -+ int qIdx; ++#define DBG_POWER 0 ++#define DBG_CLOCK 0 ++#define INFO_MSG 0 + -+ int busReqNum; -+ int mcuBlockNum; -+ int compNum; -+ int compInfo[3]; -+ int mcuWidth; -+ int mcuHeight; + -+ int pagePtr; -+ int wordPtr; -+ int bitPtr; ++/*--------------------------------------------------------------------------- */ ++/* Static Global Variables */ ++static int gstIsInitialized; ++static int gstIsVPUOn; ++static unsigned int gstVpuRegStore[64]; + -+ int validFlg; -+}; ++static uint32_t *gstCodaClockEnRegVir; ++static uint32_t *gstIsolateBase; ++static uint32_t *gstAliveBase; + -+struct nx_vpu_codec_inst { -+ void *devHandle; -+ int inUse; -+ int instIndex; -+ int isInitialized; -+ int codecMode; -+ int auxMode; -+ uint64_t paramPhyAddr; /* Common Area */ -+ char *paramVirAddr; -+ uint32_t paramBufSize; -+ uint64_t instBufPhyAddr; -+ union{ -+ struct vpu_dec_info decInfo; -+ struct vpu_enc_info encInfo; -+ } codecInfo; -+}; + -+/* BIT_RUN command */ -+enum nx_vpu_cmd { -+ SEQ_INIT = 1, -+ SEQ_END = 2, -+ PIC_RUN = 3, -+ SET_FRAME_BUF = 4, -+ ENCODE_HEADER = 5, -+ ENC_PARA_SET = 6, -+ DEC_PARA_SET = 7, -+ DEC_BUF_FLUSH = 8, -+ RC_CHANGE_PARAMETER = 9, -+ VPU_SLEEP = 10, -+ VPU_WAKE = 11, -+ ENC_ROI_INIT = 12, -+ FIRMWARE_GET = 0xf, ++static struct nx_vpu_codec_inst gstVpuInstance[NX_MAX_VPU_INSTANCE]; + -+ GET_ENC_INSTANCE = 0x100, -+ ENC_RUN = 0x101, + -+ GET_DEC_INSTANCE = 0x200, -+ DEC_RUN = 0x201, -+}; ++/*--------------------------------------------------------------------------- */ ++/* Define Static Functions */ ++static unsigned int VPU_IsBusy(void); + -+enum vpu_gdi_tiled_map_type { -+ VPU_LINEAR_FRAME_MAP = 0, -+ VPU_TILED_FRAME_V_MAP = 1, -+ VPU_TILED_FRAME_H_MAP = 2, -+ VPU_TILED_FIELD_V_MAP = 3, -+ VPU_TILED_MIXED_V_MAP = 4, -+ VPU_TILED_FRAME_MB_RASTER_MAP = 5, -+ VPU_TILED_FIELD_MB_RASTER_MAP = 6, -+ VPU_TILED_MAP_TYPE_MAX -+}; + ++/*---------------------------------------------------------------------------- ++ * Nexell Specific VPU Hardware On/Off Logic ++ *--------------------------------------------------------------------------- */ ++#define VPU_ALIVEGATE_REG 0xC0010800 ++#define VPU_NISOLATE_REG 0xC0010D00 ++#define CODA960CLKENB_REG 0xC00C7000 + -+/* H/W Level APIs */ -+void NX_VPU_HwOn(void *, void *); -+void NX_VPU_HWOff(void *); -+int NX_VPU_GetCurPowerState(void); -+void NX_VPU_Clock(int on); ++#define POWER_PMU_VPU_MASK 0x00000002 + -+int NX_VpuInit(void *pv, void *baseAddr, void *firmVirAddr, -+ uint32_t firmPhyAddr); -+int NX_VpuDeInit(void *); ++#if defined(CONFIG_ARCH_S5P6818) ++/* Async XUI Power Down ++ * ++ * Step 1. Waiting until CACTIVE to High ++ * Step 2. Set CSYSREQ to Low ++ * Step 3. Waiting until CSYSACK to Low ++ */ ++static void NX_ASYNCXUI_PowerDown(void) ++{ ++ int32_t tmpVal; + -+int NX_VpuSuspend(void *dev); -+int NX_VpuResume(void *dev, void *pVpuBaseAddr); ++ FUNC_IN(); + -+int VPU_WaitVpuBusy(int mSeconds, unsigned int busyFlagReg); ++ /* Apply To Async XUI 0 */ + -+int VPU_SWReset(int resetMode); ++ /* Step 1. Waiting until CACTIVE to High */ ++ do { ++ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU0_CACTIVE_S); ++ } while (!tmpVal); + -+struct nx_vpu_codec_inst *NX_VpuGetInstance(int index); -+int NX_VpuIsInitialized(void); -+int NX_VpuParaInitialized(void *dev); -+int swap_endian(unsigned char *data, int len); ++ /* Step 2. Set CSYSREQ to Low */ ++ nx_tieoff_set(NX_TIEOFF_Inst_ASYNCXUI0_CSYSREQ, 0); + -+/* Encoder Specific APIs */ -+int NX_VpuEncOpen(struct vpu_open_arg *pOpenArg, void *devHandle, -+ struct nx_vpu_codec_inst **ppInst); -+int NX_VpuEncClose(struct nx_vpu_codec_inst *pInst, -+ void *vpu_event_present); -+int NX_VpuEncSetSeqParam(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_seq_arg *pSeqArg); -+int NX_VpuEncSetFrame(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_set_frame_arg *pFrmArg); -+int NX_VpuEncGetHeader(struct nx_vpu_codec_inst *pInst, -+ union vpu_enc_get_header_arg *pHeader); -+int NX_VpuEncRunFrame(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_run_frame_arg *pRunArg); -+int NX_VpuEncChgParam(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_chg_para_arg *pChgArg); ++ /*Step 3. Waiting until CSYSACK to Low */ ++ do { ++ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU0_CSYSACK_S); ++ } while (tmpVal); + -+/* Decoder Specific APIs */ -+int NX_VpuDecOpen(struct vpu_open_arg *pOpenArg, void *devHandle, -+ struct nx_vpu_codec_inst **ppInst); -+int NX_VpuDecClose(struct nx_vpu_codec_inst *pInst, -+ void *vpu_event_present); -+int NX_VpuDecSetSeqInfo(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_seq_init_arg *pSeqArg); -+int NX_VpuDecRegFrameBuf(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_reg_frame_arg *pFrmArg); -+int NX_VpuFillStreamBuffer(struct nx_vpu_codec_inst*, -+ void *strmData, unsigned strmDataSize); -+int NX_VpuDecRunFrame(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_frame_arg *pRunArg); -+int NX_VpuDecFlush(struct nx_vpu_codec_inst *pInst); -+int NX_VpuDecClrDspFlag(struct nx_vpu_codec_inst *pInst, unsigned index); ++ /* Apply To Async XUI 1 */ + -+/* Jpeg Encoder Specific APIs */ -+int JPU_EncRunFrame(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_run_frame_arg *pRunArg); ++ /* Step 1. Waiting until CACTIVE to High */ ++ do { ++ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU1_CACTIVE_S); ++ } while (!tmpVal); + -+/* Jpeg Decoder Specific APIs */ -+int JPU_DecSetSeqInfo(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_seq_init_arg *pSeqArg); -+int JPU_DecParseHeader(struct vpu_dec_info *pInfo, uint8_t *pbyStream, -+ int32_t iSize); -+int JPU_DecRegFrameBuf(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_reg_frame_arg *pFrmArg); -+int JPU_DecRunFrame(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_frame_arg *pRunArg); ++ /* Step 2. Set CSYSREQ to Low */ ++ nx_tieoff_set(NX_TIEOFF_Inst_ASYNCXUI1_CSYSREQ, 0); + ++ /* Step 3. Waiting until CSYSACK to Low */ ++ do { ++ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU1_CSYSACK_S); ++ } while (tmpVal); + -+extern void vpu_soc_peri_reset_enter(void *pv); -+extern void vpu_soc_peri_reset_exit(void *pv); + -+extern int VPU_WaitBitInterrupt(void *devHandle, int mSeconds); -+extern int JPU_WaitInterrupt(void *devHandle, int timeOut); ++ FUNC_OUT(); ++} + -+#endif/* __NX_VPU_API_H__ */ -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_config.h b/drivers/media/platform/nxp-vpu/nx_vpu_config.h ---- a/drivers/media/platform/nxp-vpu/nx_vpu_config.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_vpu_config.h 2018-05-06 08:49:50.074731776 +0200 -@@ -0,0 +1,111 @@ -+/* -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * Author: Seonghee, Kim -+ * -+ * 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. ++/* Async XUI Power Up + * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . ++ * Step 1. Set CSYSREQ to High ++ * Step 2. Waiting until CSYSACK to High + */ ++static void NX_ASYNCXUI_PowerUp(void) ++{ ++ int32_t tmpVal; + -+#ifndef __NX_VPU_CONFIG_H__ -+#define __NX_VPU_CONFIG_H__ ++ FUNC_IN(); + ++ /* Apply To Async XUI 0 */ + -+#define NX_MAX_VPU_INSTANCE 16 ++ /* Step 1. Set CSYSREQ to High */ ++ nx_tieoff_set(NX_TIEOFF_Inst_ASYNCXUI0_CSYSREQ, 1); + -+/* VPU Clock Gating */ -+#define ENABLE_CLOCK_GATING -+/* #define ENABLE_POWER_SAVING */ ++ /* Step 2. Waiting until CSYSACK to High */ ++ do { ++ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU0_CSYSACK_S); ++ } while (!tmpVal); + -+#define NX_DBG_INFO 0 ++ /* Apply To Async XUI 1 */ + -+/* Debug Register Access */ -+#define NX_REG_ACC_DEBUG 0 /* Use Debug Function */ -+#define NX_REG_EN_MSG 0 /* Enable Debug Message */ ++ /* Step 1. Set CSYSREQ to High */ ++ nx_tieoff_set(NX_TIEOFF_Inst_ASYNCXUI1_CSYSREQ, 1); + ++ /* Step 2. Waiting until CSYSACK to High */ ++ do { ++ tmpVal = nx_tieoff_get(NX_TIEOFF_Inst_CODA960_ASYNCXIU1_CSYSACK_S); ++ } while (!tmpVal); + -+/* -+ * Memory Size Config -+ * -+ * ----------------------- High Address -+ * | Instance (1MB) | -+ * ----------------------- -+ * | Param Buffer (1MB) | -+ * ----------------------- -+ * | Temp Buf (1MB) | -+ * ----------------------- -+ * | Working Buffer (1MB) | -+ * ----------------------- -+ * | Code Buffer (1MB) | -+ * ----------------------- Low Address -+ */ ++ FUNC_OUT(); ++} ++#endif + ++void NX_VPU_HwOn(void *dev, void *pVpuBaseAddr) ++{ ++ uint32_t tmpVal; ++ uint32_t *pNPreCharge, *pNPowerUp, *pNPowerAck; + -+#define PARA_BUF_SIZE (12 * 1024) -+#define TEMP_BUF_SIZE (204 * 1024) -+#define CODE_BUF_SIZE (260 * 1024) ++ NX_DbgMsg(DBG_POWER, ("NX_VPU_HwOn() ++\n")); + -+#define COMMON_BUF_SIZE (CODE_BUF_SIZE+TEMP_BUF_SIZE+PARA_BUF_SIZE) ++ /* Already Power On */ ++ if (gstIsVPUOn) ++ return; + -+#define WORK_BUF_SIZE (80 * 1024) -+#define INST_BUF_SIZE (NX_MAX_VPU_INSTANCE*WORK_BUF_SIZE) ++ vpu_soc_peri_reset_enter(dev); + -+#define DEC_STREAM_SIZE (1 * 1024 * 1024) ++ InitVpuRegister(pVpuBaseAddr); + -+#define VPU_LITTLE_ENDIAN 0 -+#define VPU_BIG_ENDIAN 1 ++ /* Initialize ISolate Register's */ ++ pNPreCharge = gstIsolateBase + 1; ++ pNPowerUp = gstIsolateBase + 2; ++ pNPowerAck = gstIsolateBase + 3; + -+#define VPU_FRAME_ENDIAN VPU_LITTLE_ENDIAN -+#define VPU_FRAME_BUFFER_ENDIAN VPU_LITTLE_ENDIAN -+#define VPU_STREAM_ENDIAN VPU_LITTLE_ENDIAN ++ NX_DbgMsg(INFO_MSG, ("====================================\n")); ++ NX_DbgMsg(INFO_MSG, ("pVpuBaseAddr = %p\n", pVpuBaseAddr)); ++ NX_DbgMsg(INFO_MSG, ("pIsolateBase = %p\n", gstIsolateBase)); ++ NX_DbgMsg(INFO_MSG, ("pNPreCharge = %p\n", pNPreCharge)); ++ NX_DbgMsg(INFO_MSG, ("pNPowerUp = %p\n", pNPowerUp)); ++ NX_DbgMsg(INFO_MSG, ("pNPowerAck = %p\n", pNPowerAck)); ++ NX_DbgMsg(INFO_MSG, ("====================================\n")); + ++ WriteReg32(gstAliveBase, 0x3); + -+#define CBCR_INTERLEAVE 0 -+#define VPU_ENABLE_BWB 1 -+#define ENC_FRAME_BUF_CBCR_INTERLEAVE 1 ++ /* Enable PreCharge */ ++ tmpVal = ReadReg32(pNPreCharge); ++ tmpVal &= (~POWER_PMU_VPU_MASK); ++ WriteReg32(pNPreCharge, tmpVal); + ++ /* Enable Power On */ ++ tmpVal = ReadReg32(pNPowerUp); ++ tmpVal &= (~POWER_PMU_VPU_MASK); ++ WriteReg32(pNPowerUp, tmpVal); + -+/* AXI Expander Select */ -+#define USE_NX_EXPND 1 ++ /* Disable ISolate */ ++ tmpVal = ReadReg32(gstIsolateBase); ++ tmpVal |= (POWER_PMU_VPU_MASK); ++ WriteReg32(gstIsolateBase, tmpVal); + -+/* Timeout */ -+#define VPU_BUSY_CHECK_TIMEOUT 500 /* 500 msec */ -+#define VPU_ENC_TIMEOUT 1000 /* 1 sec */ -+#define VPU_DEC_TIMEOUT 300 /* 300 msec */ -+#define JPU_ENC_TIMEOUT 1000 /* 1 sec */ -+#define JPU_DEC_TIMEOUT 1000 /* 1 sec */ ++ mdelay(1); + ++ NX_VPU_Clock(1); + -+#define VPU_GBU_SIZE 1024 /* No modification required */ -+#define JPU_GBU_SIZE 512 /* No modification required */ ++#if defined(CONFIG_ARCH_S5P6818) ++ NX_ASYNCXUI_PowerUp(); ++#endif + ++ vpu_soc_peri_reset_exit(dev); + -+#define MAX_REG_FRAME 31 ++ gstIsVPUOn = 1; + + -+/*---------------------------------------------------------------------------- -+ * Encoder Configurations -+ */ -+#define VPU_ENC_MAX_FRAME_BUF 3 -+#define VPU_ME_LINEBUFFER_MODE 2 ++ NX_DbgMsg(DBG_POWER, ("NX_VPU_HwOn() --\n")); ++} + ++void NX_VPU_HWOff(void *dev) ++{ ++ FUNC_IN(); + -+/*---------------------------------------------------------------------------- -+ * Decoder Configurations -+ */ -+#define VPU_REORDER_ENABLE 1 -+#define VPU_GMC_PROCESS_METHOD 0 -+#define VPU_AVC_X264_SUPPORT 1 ++ if (gstIsVPUOn) { ++ unsigned int tmpVal; ++ uint32_t *pNPreCharge, *pNPowerUp, *pNPowerAck; + -+#define VPU_SPP_CHUNK_SIZE 1024 /* AVC SPP */ ++#if defined(CONFIG_ARCH_S5P6818) ++ NX_ASYNCXUI_PowerDown(); ++#endif ++ /* H/W Reset */ ++ vpu_soc_peri_reset_enter(dev); + -+#endif /* __NX_VPU_CONFIG_H__ */ -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_decoder.c b/drivers/media/platform/nxp-vpu/nx_vpu_decoder.c ---- a/drivers/media/platform/nxp-vpu/nx_vpu_decoder.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_vpu_decoder.c 2018-05-06 08:49:50.074731776 +0200 -@@ -0,0 +1,1249 @@ -+/* -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * Author: Seonghee, Kim -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ ++ NX_DbgMsg(DBG_POWER, ("NX_VPU_HWOff() ++\n")); + -+#ifndef UNUSED -+#define UNUSED(p) ((void)(p)) -+#endif ++ /* Initialize ISolate Register's */ ++ pNPreCharge = gstIsolateBase + 1; ++ pNPowerUp = gstIsolateBase + 2; ++ pNPowerAck = gstIsolateBase + 3; + -+#include ++ /* Enter Coda Reset State */ ++ WriteReg32(gstAliveBase, 0x3); + -+#include "vpu_hw_interface.h" /* Register Access */ -+#include "nx_vpu_api.h" -+#include "nx_vpu_gdi.h" ++ /* Isolate VPU H/W */ ++ tmpVal = ReadReg32(gstIsolateBase); ++ tmpVal &= (~POWER_PMU_VPU_MASK); ++ WriteReg32(gstIsolateBase, tmpVal); + ++ /* Pre Charget Off */ ++ tmpVal = ReadReg32(pNPreCharge); ++ tmpVal |= POWER_PMU_VPU_MASK; ++ WriteReg32(pNPreCharge, tmpVal); + -+#define DBG_USERDATA 0 -+#define DBG_REGISTER 0 -+#define DBG_ES_ADDR 0 -+#define INFO_MSG 0 ++ /* Power Down */ ++ tmpVal = ReadReg32(pNPowerUp); ++ tmpVal |= POWER_PMU_VPU_MASK; ++ WriteReg32(pNPowerUp, tmpVal); + ++ /* Isolate VPU H/W */ ++ tmpVal = ReadReg32(gstIsolateBase); ++ tmpVal &= (~POWER_PMU_VPU_MASK); ++ WriteReg32(gstIsolateBase, tmpVal); + -+/*--------------------------------------------------------------------------- */ -+/* Decoder Functions */ -+static int FillBuffer(struct nx_vpu_codec_inst *pInst, unsigned char *stream, -+ int size); -+static int VPU_DecSeqInitCommand(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_seq_init_arg *pArg); -+static int VPU_DecSeqComplete(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_seq_init_arg *pArg); -+static int VPU_DecRegisterFrameBufCommand(struct nx_vpu_codec_inst -+ *pInst, struct vpu_dec_reg_frame_arg *pArg); -+static int VPU_DecStartOneFrameCommand(struct nx_vpu_codec_inst -+ *pInst, struct vpu_dec_frame_arg *pArg); -+static int VPU_DecGetOutputInfo(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_frame_arg *pArg); -+static int VPU_DecCloseCommand(struct nx_vpu_codec_inst *pInst, -+ void *vpu_event_present); ++ gstIsVPUOn = 0; + ++ NX_DbgMsg(DBG_POWER, ("NX_VPU_HWOff() --\n")); ++ } + -+/*---------------------------------------------------------------------------- -+ * Decoder APIs -+ */ ++ FUNC_OUT(); ++} + -+int NX_VpuDecOpen(struct vpu_open_arg *pOpenArg, void *devHandle, -+ struct nx_vpu_codec_inst **ppInst) ++int NX_VPU_GetCurPowerState(void) +{ -+ int val; -+ struct vpu_dec_info *pDecInfo; -+ struct nx_vpu_codec_inst *hInst = 0; ++ return gstIsVPUOn; ++} + ++void NX_VPU_Clock(int on) ++{ + FUNC_IN(); + -+ *ppInst = 0; -+ if (!NX_VpuIsInitialized()) -+ return VPU_RET_ERR_INIT; -+ -+ hInst = NX_VpuGetInstance(pOpenArg->instIndex); -+ if (!hInst) -+ return VPU_RET_ERR_INST; -+ -+ if (pOpenArg->codecStd == CODEC_STD_MPEG4) { -+ hInst->codecMode = MP4_DEC; -+ hInst->auxMode = MP4_AUX_MPEG4; -+ } else if (pOpenArg->codecStd == CODEC_STD_AVC) { -+ hInst->codecMode = AVC_DEC; -+ hInst->auxMode = AVC_AUX_AVC; -+ } else if (pOpenArg->codecStd == CODEC_STD_VC1) { -+ hInst->codecMode = VC1_DEC; -+ } else if (pOpenArg->codecStd == CODEC_STD_MPEG2) { -+ hInst->codecMode = MP2_DEC; -+ hInst->auxMode = 0; -+ } else if (pOpenArg->codecStd == CODEC_STD_H263) { -+ hInst->codecMode = MP4_DEC; -+ hInst->auxMode = 0; -+ } else if (pOpenArg->codecStd == CODEC_STD_DIV3) { -+ hInst->codecMode = DV3_DEC; -+ hInst->auxMode = MP4_AUX_DIVX3; -+ } else if (pOpenArg->codecStd == CODEC_STD_RV) { -+ hInst->codecMode = RV_DEC; -+ } else if (pOpenArg->codecStd == CODEC_STD_AVS) { -+ hInst->codecMode = AVS_DEC; -+ } else if (pOpenArg->codecStd == CODEC_STD_MJPG) { -+ hInst->codecMode = MJPG_DEC; -+ } else if (pOpenArg->codecStd == CODEC_STD_THO) { -+ hInst->codecMode = VPX_DEC; -+ hInst->auxMode = VPX_AUX_THO; -+ } else if (pOpenArg->codecStd == CODEC_STD_VP3) { -+ hInst->codecMode = VPX_DEC; -+ hInst->auxMode = VPX_AUX_THO; -+ } else if (pOpenArg->codecStd == CODEC_STD_VP8) { -+ hInst->codecMode = VPX_DEC; -+ hInst->auxMode = VPX_AUX_VP8; ++ if (on) { ++ WriteReg32(gstCodaClockEnRegVir, 0x0000000F); ++ NX_DbgMsg(DBG_CLOCK, ("NX_VPU_Clock() ON\n")); + } else { -+ NX_ErrMsg(("NX_VpuDecOpen() failed!!!\n")); -+ NX_ErrMsg(("Cannot support codec standard (%d)\n", -+ pOpenArg->codecStd)); -+ return VPU_RET_ERR_PARAM; ++ WriteReg32(gstCodaClockEnRegVir, 0x00000000); ++ NX_DbgMsg(DBG_CLOCK, ("NX_VPU_Clock() OFF\n")); + } + -+ /* Set Base Information */ -+ hInst->inUse = 1; -+ hInst->instIndex = pOpenArg->instIndex; -+ hInst->devHandle = devHandle; ++ FUNC_OUT(); ++} + -+ hInst->instBufPhyAddr = (uint64_t)pOpenArg->instanceBuf.phyAddr; -+ pDecInfo = &hInst->codecInfo.decInfo; ++static unsigned int VPU_IsBusy(void) ++{ ++ unsigned int ret = ReadRegNoMsg(BIT_BUSY_FLAG); + -+ /* Clrear Instnace Information */ -+ NX_DrvMemset(&hInst->codecInfo, 0, sizeof(hInst->codecInfo)); -+ pDecInfo->codecStd = pOpenArg->codecStd; -+ pDecInfo->mp4Class = pOpenArg->mp4Class; ++ return ret != 0; ++} + -+ if (hInst->codecMode != MJPG_DEC) { -+ pDecInfo->streamRdPtrRegAddr = BIT_RD_PTR; -+ pDecInfo->streamWrPtrRegAddr = BIT_WR_PTR; -+ pDecInfo->frameDisplayFlagRegAddr = BIT_FRM_DIS_FLG; -+ } else { -+ pDecInfo->streamRdPtrRegAddr = MJPEG_BBC_RD_PTR_REG; -+ pDecInfo->streamWrPtrRegAddr = MJPEG_BBC_WR_PTR_REG; -+ pDecInfo->frameDisplayFlagRegAddr = 0; ++static int VPU_WaitBusBusy(int mSeconds, unsigned int busyFlagReg) ++{ ++ while (mSeconds > 0) { ++ if (0x77 == VpuReadReg(busyFlagReg)) ++ return VPU_RET_OK; ++ DrvMSleep(1); ++ mSeconds--; + } ++ return VPU_RET_ERR_TIMEOUT; ++} + -+ pDecInfo->strmBufPhyAddr = (uint64_t)pOpenArg->streamBuf.phyAddr; -+ pDecInfo->strmBufVirAddr = (unsigned long)pOpenArg->streamBuf.virAddr; -+ pDecInfo->strmBufSize = pOpenArg->streamBuf.size; -+ NX_DrvMemset((void *)(unsigned long)pDecInfo->strmBufVirAddr, 0, -+ pDecInfo->strmBufSize); -+ -+ /* Set Other Parameters */ -+ pDecInfo->frameDelay = -1; -+ pDecInfo->userDataEnable = 0; -+ pDecInfo->enableReordering = VPU_REORDER_ENABLE; -+ pDecInfo->vc1BframeDisplayValid = 0; -+ pDecInfo->avcErrorConcealMode = 0; -+ pDecInfo->enableMp4Deblock = 0; ++int VPU_WaitVpuBusy(int mSeconds, unsigned int busyFlagReg) ++{ ++ while (mSeconds > 0) { ++ if (ReadRegNoMsg(busyFlagReg) == 0) ++ return VPU_RET_OK; + -+ if (pDecInfo->codecStd == CODEC_STD_AVC || -+ pDecInfo->codecStd == CODEC_STD_MPEG2 ) { -+ pDecInfo->bitStreamMode = BS_MODE_PIC_END; -+ /*pDecInfo->bitStreamMode = BS_MODE_ROLLBACK; */ -+ } else if (pDecInfo->codecStd == CODEC_STD_H263 || -+ pDecInfo->codecStd == CODEC_STD_MPEG4) { -+ pDecInfo->bitStreamMode = BS_MODE_PIC_END; -+ } else { -+ pDecInfo->bitStreamMode = BS_MODE_ROLLBACK; ++ DrvMSleep(1); ++ mSeconds--; + } ++ return VPU_RET_ERR_TIMEOUT; ++} + -+ pDecInfo->streamEndflag = 0;/* Frame Unit Operation */ -+ pDecInfo->bwbEnable = VPU_ENABLE_BWB; -+ pDecInfo->seqInitEscape = 0; -+ pDecInfo->streamEndian = VPU_STREAM_ENDIAN; -+ -+ NX_DrvMemset(hInst->paramVirAddr, 0, PARA_BUF_SIZE); ++void VPU_GetVersionInfo(unsigned int *versionInfo, unsigned int *revision, ++ unsigned int *productId) ++{ ++ unsigned int ver; ++ unsigned int rev; ++ unsigned int pid; + -+ VpuWriteReg(pDecInfo->streamWrPtrRegAddr, pDecInfo->strmBufPhyAddr); -+ VpuWriteReg(pDecInfo->streamRdPtrRegAddr, pDecInfo->strmBufPhyAddr); ++ if (versionInfo && revision) { ++ VpuWriteReg(RET_FW_VER_NUM, 0); ++ VpuWriteReg(BIT_WORK_BUF_ADDR, 0); ++ VpuWriteReg(BIT_BUSY_FLAG, 1); ++ VpuWriteReg(BIT_RUN_INDEX, 0); ++ VpuWriteReg(BIT_RUN_COD_STD, 0); ++ VpuWriteReg(BIT_RUN_AUX_STD, 0); ++ VpuWriteReg(BIT_RUN_COMMAND, FIRMWARE_GET); ++ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, ++ BIT_BUSY_FLAG)) { ++ NX_ErrMsg(("Version Read Failed!!!\n")); ++ return; ++ } + -+ pDecInfo->readPos = pDecInfo->strmBufPhyAddr; -+ pDecInfo->writePos = pDecInfo->strmBufPhyAddr; ++ ver = VpuReadReg(RET_FW_VER_NUM); ++ rev = VpuReadReg(RET_FW_CODE_REV); + -+ if (hInst->codecMode != MJPG_DEC) { -+ val = VpuReadReg(BIT_BIT_STREAM_PARAM); -+ val &= ~(1 << 2); -+ /* clear stream end flag at start */ -+ VpuWriteReg(BIT_BIT_STREAM_PARAM, val); -+ pDecInfo->streamEndflag = val; -+ } else { -+ pDecInfo->streamEndflag = 0; -+ VpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, pDecInfo->strmBufPhyAddr); -+ VpuWriteReg(MJPEG_BBC_END_ADDR_REG, pDecInfo->strmBufPhyAddr + -+ pDecInfo->strmBufSize); -+ VpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, 0); ++ *versionInfo = ver; ++ *revision = rev; + } + -+ *ppInst = hInst; -+ -+ NX_DbgMsg(INFO_MSG, ("===================================\n")); -+ NX_DbgMsg(INFO_MSG, (" VPU Open Information:\n")); -+ NX_DbgMsg(INFO_MSG, (" Instance Index : %d\n", hInst->instIndex)); -+ NX_DbgMsg(INFO_MSG, (" BitStream Mode : %d\n", -+ pDecInfo->bitStreamMode)); -+ NX_DbgMsg(INFO_MSG, (" Codec Standard : %d\n", hInst->codecMode)); -+ NX_DbgMsg(INFO_MSG, (" Codec AUX Mode : %d\n", hInst->auxMode)); -+ NX_DbgMsg(INFO_MSG, ("===================================\n")); ++ pid = VpuReadReg(DBG_CONFIG_REPORT_1); ++ if ((pid&0xff00) == 0x3200) ++ pid = 0x3200; + -+ FUNC_OUT(); -+ return VPU_RET_OK; ++ if (productId) ++ *productId = pid; +} + -+int NX_VpuDecSetSeqInfo(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_seq_init_arg *pSeqArg) ++void CheckVersion(void) +{ -+ enum nx_vpu_ret ret; ++ unsigned int version; ++ unsigned int revision; ++ unsigned int productId; + -+ FUNC_IN(); ++ VPU_GetVersionInfo(&version, &revision, &productId); + -+ if (pInst->codecMode != MJPG_DEC) { -+ /* FillBuffer */ -+ if (0 > FillBuffer(pInst, -+ (unsigned char *)(unsigned long)pSeqArg->seqData, -+ pSeqArg->seqDataSize)) { -+ NX_ErrMsg(("FillBuffer Error!!!\n")); -+ return VPU_RET_ERROR; -+ } ++ NX_DbgMsg(INFO_MSG, ("Firmware Version => projectId : %x | ", ++ (unsigned int)(version>>16))); ++ NX_DbgMsg(INFO_MSG, ("version : %04d.%04d.%08d | revision : r%d\n", ++ (unsigned int)((version>>(12))&0x0f), ++ (unsigned int)((version>>(8))&0x0f), ++ (unsigned int)((version)&0xff), ++ revision)); ++ NX_DbgMsg(INFO_MSG, ("Hardware Version => %04x\n", productId)); ++} + -+#if 0 -+ if (pInfo->bitStreamMode != BS_MODE_PIC_END) { -+ int streamSize; + -+ if (pInfo->writePos > pInfo->readPos) -+ streamSize = pInfo->writePos - pInfo->readPos; -+ else -+ streamSize = pInfo->strmBufSize - -+ (pInfo->readPos - pInfo->writePos); ++/*--------------------------------------------------------------------------- */ + -+ if (streamSize < VPU_GBU_SIZE*2) -+ return VPU_RET_NEED_STREAM; -+ } -+#endif ++/* VPU_SWReset ++ * IN ++ * forcedReset : 1 if there is no need to waiting for BUS transaction, ++ * 0 for otherwise ++ * OUT ++ * RetCode : RETCODE_FAILURE if failed to reset, ++ * RETCODE_SUCCESS for otherwise ++ */ + -+ ret = VPU_DecSeqInitCommand(pInst, pSeqArg); -+ if (ret != VPU_RET_OK) -+ return ret; -+ ret = VPU_DecSeqComplete(pInst, pSeqArg); -+ } else { -+ ret = JPU_DecSetSeqInfo(pInst, pSeqArg); ++/* SW Reset command */ ++#define VPU_SW_RESET_BPU_CORE 0x008 ++#define VPU_SW_RESET_BPU_BUS 0x010 ++#define VPU_SW_RESET_VCE_CORE 0x020 ++#define VPU_SW_RESET_VCE_BUS 0x040 ++#define VPU_SW_RESET_GDI_CORE 0x080 ++#define VPU_SW_RESET_GDI_BUS 0x100 + -+ /* Fill Data */ -+ if (0 > FillBuffer(pInst, -+ (unsigned char *)(unsigned long)pSeqArg->seqData, -+ pSeqArg->seqDataSize)) { -+ NX_ErrMsg(("FillBuffer Failed.\n")); -+ return VPU_RET_ERROR; ++int VPU_SWReset(int resetMode) ++{ ++ unsigned int cmd; ++ ++ if (resetMode == SW_RESET_SAFETY || resetMode == SW_RESET_ON_BOOT) { ++ /* Waiting for completion of bus transaction */ ++ /* Step1 : No more request */ ++ /* no more request {3'b0,no_more_req_sec,3'b0,no_more_req} */ ++ VpuWriteReg(GDI_BUS_CTRL, 0x11); ++ ++ /* Step2 : Waiting for completion of bus transaction */ ++ /* while (VpuReadReg(coreIdx, GDI_BUS_STATUS) != 0x77) */ ++ if (VPU_WaitBusBusy(VPU_BUSY_CHECK_TIMEOUT, GDI_BUS_STATUS) == ++ VPU_RET_ERR_TIMEOUT) { ++ VpuWriteReg(GDI_BUS_CTRL, 0x00); ++ return VPU_RET_ERR_TIMEOUT; + } ++ ++ /* Step3 : clear GDI_BUS_CTRL */ ++ VpuWriteReg(GDI_BUS_CTRL, 0x00); + } + -+ FUNC_OUT(); -+ return ret; -+} ++ cmd = 0; ++ /* Software Reset Trigger */ ++ if (resetMode != SW_RESET_ON_BOOT) ++ cmd = VPU_SW_RESET_BPU_CORE | VPU_SW_RESET_BPU_BUS; ++ cmd |= VPU_SW_RESET_VCE_CORE | VPU_SW_RESET_VCE_BUS; ++ if (resetMode == SW_RESET_ON_BOOT) ++ /* If you reset GDI, tiled map should be reconfigured */ ++ cmd |= VPU_SW_RESET_GDI_CORE | VPU_SW_RESET_GDI_BUS; ++ VpuWriteReg(BIT_SW_RESET, cmd); + -+int NX_VpuDecRegFrameBuf(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_reg_frame_arg *pFrmArg) -+{ -+ if (pInst->codecMode != MJPG_DEC) -+ return VPU_DecRegisterFrameBufCommand(pInst, pFrmArg); -+ else -+ return JPU_DecRegFrameBuf(pInst, pFrmArg); ++ /* wait until reset is done */ ++ if (VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, BIT_SW_RESET_STATUS) == ++ VPU_RET_ERR_TIMEOUT) { ++ VpuWriteReg(BIT_SW_RESET, 0x00); ++ return VPU_RET_ERR_TIMEOUT; ++ } ++ ++ VpuWriteReg(BIT_SW_RESET, 0); ++ ++ return VPU_RET_OK; +} + -+int NX_VpuFillStreamBuffer(struct nx_vpu_codec_inst *pInst, -+ void *strmData, unsigned strmDataSize) ++/*---------------------------------------------------------------------------- ++ * VPU Initialization. ++ *--------------------------------------------------------------------------- */ ++int NX_VpuInit(void *dev, void *baseAddr, void *firmVirAddr, ++ uint32_t firmPhyAddr) +{ -+ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; -+ enum nx_vpu_ret ret; ++ enum nx_vpu_ret ret = VPU_RET_OK; ++ int32_t i; ++ uint32_t tmpData; ++ uint32_t codeBufAddr, tmpBufAddr, paramBufAddr; + -+ if (pInst->codecMode != MJPG_DEC) { -+ /* Fill Data */ -+ if (0 > FillBuffer(pInst, strmData, strmDataSize)) { -+ NX_ErrMsg(("FillBuffer Failed.\n")); -+ return VPU_RET_ERROR; -+ } ++ if (gstIsInitialized) ++ return VPU_RET_OK; + -+ } else { -+ if (pInfo->headerSize == 0) { -+ ret = JPU_DecParseHeader(pInfo, strmData, strmDataSize); -+ if (ret < 0) { -+ NX_ErrMsg(("JpgHeader is failed(Error = %d)!\n", ret)); -+ return -1; -+ } -+ } -+ /* Fill Data */ -+ if (0 > FillBuffer(pInst, strmData, strmDataSize)) { -+ NX_ErrMsg(("FillBuffer Failed.\n")); -+ return VPU_RET_ERROR; -+ } ++ codeBufAddr = firmPhyAddr; ++ tmpBufAddr = codeBufAddr + CODE_BUF_SIZE; ++ paramBufAddr = tmpBufAddr + TEMP_BUF_SIZE; ++ ++ NX_VPU_HwOn(dev, baseAddr); ++ ++ /* if BIT processor is not running. */ ++ if (VpuReadReg(BIT_CUR_PC) == 0) { ++ for (i = 0; i < 64; i++) ++ VpuWriteReg(BIT_BASE + 0x100 + (i*4), 0x0); + } -+ return VPU_RET_OK; -+} + -+int NX_VpuDecRunFrame(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_frame_arg *pRunArg) -+{ -+ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; -+ enum nx_vpu_ret ret; ++ VPU_SWReset(SW_RESET_ON_BOOT); + ++ { ++ unsigned char *dst = (unsigned char *)firmVirAddr; + -+ if (pInst->codecMode != MJPG_DEC) { -+#if 0 -+ if (pInfo->bitStreamMode != BS_MODE_PIC_END) { -+ int streamSize; ++ for (i = 0; i < ARRAY_SIZE(bit_code) ; i += 4) { ++ *dst++ = (unsigned char)(bit_code[i+3] >> 0); ++ *dst++ = (unsigned char)(bit_code[i+3] >> 8); + -+ if (pInfo->writePos > pInfo->readPos) -+ streamSize = pInfo->writePos - pInfo->readPos; -+ else -+ streamSize = pInfo->strmBufSize - -+ (pInfo->readPos - pInfo->writePos); ++ *dst++ = (unsigned char)(bit_code[i+2] >> 0); ++ *dst++ = (unsigned char)(bit_code[i+2] >> 8); + -+ if (streamSize < VPU_GBU_SIZE*2) { -+ pRunArg->indexFrameDecoded = -1; -+ pRunArg->indexFrameDisplay = -1; -+ return VPU_RET_NEED_STREAM; -+ } -+ } -+#endif ++ *dst++ = (unsigned char)(bit_code[i+1] >> 0); ++ *dst++ = (unsigned char)(bit_code[i+1] >> 8); + -+ ret = VPU_DecStartOneFrameCommand(pInst, pRunArg); -+ if (ret == VPU_RET_OK) -+ ret = VPU_DecGetOutputInfo(pInst, pRunArg); -+ } else { -+ if (pInfo->validFlg > 0) { -+ ret = JPU_DecRunFrame(pInst, pRunArg); -+ pInfo->validFlg -= 1; -+ } else { -+ ret = -1; ++ *dst++ = (unsigned char)(bit_code[i+0] >> 0); ++ *dst++ = (unsigned char)(bit_code[i+0] >> 8); + } + } + -+ return ret; -+} ++ VpuWriteReg(BIT_INT_ENABLE, 0); ++ VpuWriteReg(BIT_CODE_RUN, 0); + -+int NX_VpuDecFlush(struct nx_vpu_codec_inst *pInst) -+{ -+ unsigned int val; -+ struct vpu_dec_info *pDecInfo = &pInst->codecInfo.decInfo; ++ for (i = 0 ; i < 2048 ; i++) { ++ tmpData = bit_code[i]; ++ WriteRegNoMsg(BIT_CODE_DOWN, (i<<16)|tmpData); ++ } + -+ if (pInst->codecMode != MJPG_DEC) { -+ val = pDecInfo->frameDisplayFlag; -+ val &= ~pDecInfo->clearDisplayIndexes; -+ VpuWriteReg(pDecInfo->frameDisplayFlagRegAddr, val); -+ pDecInfo->clearDisplayIndexes = 0; -+ pDecInfo->writePos = pDecInfo->readPos; -+ VpuBitIssueCommand(pInst, DEC_BUF_FLUSH); ++ VpuWriteReg(BIT_PARA_BUF_ADDR, paramBufAddr); ++ VpuWriteReg(BIT_CODE_BUF_ADDR, codeBufAddr); ++ VpuWriteReg(BIT_TEMP_BUF_ADDR, tmpBufAddr); + -+ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, -+ BIT_BUSY_FLAG)) -+ return VPU_RET_ERR_TIMEOUT; ++ VpuWriteReg(BIT_BIT_STREAM_CTRL, VPU_STREAM_ENDIAN); + -+ pDecInfo->frameDisplayFlag = VpuReadReg( -+ pDecInfo->frameDisplayFlagRegAddr); -+ pDecInfo->frameDisplayFlag = 0; -+ /* Clear End of Stream */ -+ pDecInfo->streamEndflag &= ~(1 << 2); -+ pDecInfo->readPos = pDecInfo->strmBufPhyAddr; -+ pDecInfo->writePos = pDecInfo->strmBufPhyAddr; -+ NX_DrvMemset((void *)(unsigned long)pDecInfo->strmBufVirAddr, -+ 0, pDecInfo->strmBufSize); -+ } else { -+ int i; ++ /* Interleave bit position is modified */ ++ VpuWriteReg(BIT_FRAME_MEM_CTRL, CBCR_INTERLEAVE<<2|VPU_FRAME_ENDIAN); + -+ for (i = 0 ; i < pDecInfo->numFrameBuffer ; i++) -+ pDecInfo->frmBufferValid[i] = 0; ++ VpuWriteReg(BIT_BIT_STREAM_PARAM, 0); ++ ++ VpuWriteReg(BIT_AXI_SRAM_USE, 0); ++ VpuWriteReg(BIT_INT_ENABLE, 0); ++ VpuWriteReg(BIT_ROLLBACK_STATUS, 0); ++ ++ tmpData = (1<codecInfo.decInfo; ++ if (!gstIsInitialized) { ++ NX_ErrMsg(("VPU Already Denitialized!!!\n")); ++ return VPU_RET_ERR_INIT; ++ } + -+ if (pInst->codecMode != MJPG_DEC) -+ pInfo->clearDisplayIndexes |= 1 << indexFrameDisplay; -+ else -+ pInfo->frmBufferValid[indexFrameDisplay] = 0; ++ if (VPU_IsBusy()) { ++ NX_ErrMsg(("NX_VpuDeInit: VPU_IsBusy!!!\n")); ++ } ++ ++ NX_VPU_HWOff(dev); + ++ gstIsInitialized = 0; + return VPU_RET_OK; +} + -+int NX_VpuDecClose(struct nx_vpu_codec_inst *pInst, -+ void *vpu_event_present) ++int NX_VpuSuspend(void *dev) +{ -+ enum nx_vpu_ret ret; -+ -+ if (pInst->codecMode == MJPG_DEC) -+ return VPU_RET_OK; ++ int i; + -+ ret = VPU_DecCloseCommand(pInst, vpu_event_present); -+ if (ret != VPU_RET_OK) -+ NX_ErrMsg(("NX_VpuDecClose() failed.(%d)\n", ret)); ++ if (!gstIsInitialized) ++ return VPU_RET_ERR_INIT; + -+ return ret; -+} ++ if (VPU_IsBusy()) ++ return VPU_RET_BUSY; ++ for (i = 0 ; i < 64 ; i++) ++ gstVpuRegStore[i] = VpuReadReg(BIT_BASE+0x100 + (i * 4)); + ++ NX_VPU_HWOff(dev); + -+/*---------------------------------------------------------------------------- -+ * Decoder Specific Static Functions -+ */ ++ return VPU_RET_OK; ++} + -+static int FillBuffer(struct nx_vpu_codec_inst *pInst, unsigned char *stream, -+ int size) ++int NX_VpuResume(void *dev, void *pVpuBaseAddr) +{ -+ uint32_t vWriteOffset, vReadOffset;/* Virtual Read/Write Position */ -+ int32_t bufSize; -+ struct vpu_dec_info *pDecInfo = &pInst->codecInfo.decInfo; ++ int i; ++ unsigned int value; + -+ /* EOS */ -+ if (size == 0) -+ return 0; -+ if (!stream || size < 0) -+ return -1; ++ if (!gstIsInitialized) ++ return VPU_RET_ERR_INIT; + -+ if (pDecInfo->codecStd == CODEC_STD_MJPG) { -+ stream += pDecInfo->headerSize; -+ size -= pDecInfo->headerSize; ++ NX_VPU_HwOn(dev, pVpuBaseAddr); + -+ pDecInfo->writePos = pDecInfo->strmBufPhyAddr; -+ pDecInfo->readPos = pDecInfo->strmBufPhyAddr; ++ VPU_SWReset(SW_RESET_ON_BOOT); + -+ pDecInfo->validFlg += 1; ++ for (i = 0 ; i < 64 ; i++) ++ VpuWriteReg(BIT_BASE+0x100+(i * 4), gstVpuRegStore[i]); ++ ++ VpuWriteReg(BIT_CODE_RUN, 0); ++ /* Bit Code */ ++ for (i = 0; i < 2048; i++) { ++ value = bit_code[i]; ++ VpuWriteReg(BIT_CODE_DOWN, ((i << 16) | value)); + } + -+ vWriteOffset = pDecInfo->writePos - pDecInfo->strmBufPhyAddr; -+ vReadOffset = pDecInfo->readPos - pDecInfo->strmBufPhyAddr; -+ bufSize = pDecInfo->strmBufSize; ++ VpuWriteReg(BIT_BUSY_FLAG, 1); ++ VpuWriteReg(BIT_CODE_RESET, 1); ++ VpuWriteReg(BIT_CODE_RUN, 1); + -+ if (bufSize < vWriteOffset || bufSize < vReadOffset) { -+ NX_ErrMsg(("%s, stream_buffer(Addr=x0%08x, size=%d)\n", -+ __func__, (uint32_t)pDecInfo->strmBufVirAddr, -+ pDecInfo->strmBufSize)); -+ NX_ErrMsg(("InBuffer(Addr=%p, size=%d)", stream, size)); -+ NX_ErrMsg(("vWriteOffset = %d, vReadOffset = %d\n", -+ vWriteOffset, vReadOffset)); -+ return -1; -+ } ++ VpuWriteReg(BIT_USE_NX_EXPND, USE_NX_EXPND); + -+ if ((bufSize - vWriteOffset) > size) { -+ /* Just Memory Copy */ -+#if 1 -+ NX_DrvMemcpy((void *)(unsigned long)(pDecInfo->strmBufVirAddr + -+ vWriteOffset), stream, size); -+#else -+ if (copy_from_user((uint8_t *)(pDecInfo->strmBufVirAddr + -+ vWriteOffset), stream, size)) -+ return -1; -+#endif -+ vWriteOffset += size; -+ } else { -+ /* Memory Copy */ -+ int remain = bufSize - vWriteOffset; -+#if 1 -+ NX_DrvMemcpy((void *)(unsigned long)(pDecInfo->strmBufVirAddr + -+ vWriteOffset), stream, remain); -+ NX_DrvMemcpy((void *)(unsigned long)(pDecInfo->strmBufVirAddr), -+ stream + remain, size-remain); -+#else -+ if (copy_from_user( -+ (void *)(unsigned long)(pDecInfo->strmBufVirAddr + -+ vWriteOffset), stream, remain)) -+ return -1; -+ if (copy_from_user( -+ (void *)(unsigned long)(pDecInfo->strmBufVirAddr), -+ stream+remain, size-remain)) -+ return -1; -+#endif -+ vWriteOffset = size-remain; ++ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, ++ BIT_BUSY_FLAG)) { ++ NX_ErrMsg(("NX_VpuResume() Failed. Timeout(%d)\n", ++ VPU_BUSY_CHECK_TIMEOUT)); ++ return VPU_RET_ERR_TIMEOUT; + } + -+ pDecInfo->writePos = vWriteOffset + pDecInfo->strmBufPhyAddr; -+ return 0; ++ return VPU_RET_OK; +} + -+static int VPU_DecSeqComplete(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_seq_init_arg *pArg) ++struct nx_vpu_codec_inst *NX_VpuGetInstance(int index) +{ -+ unsigned int val, val2; -+ int errReason; -+ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; ++ return &gstVpuInstance[index]; ++} + -+ if (pInfo->bitStreamMode == BS_MODE_INTERRUPT && pInfo->seqInitEscape) { -+ pInfo->streamEndflag &= ~(3<<3); -+ VpuWriteReg(BIT_BIT_STREAM_PARAM, pInfo->streamEndflag); -+ pInfo->seqInitEscape = 0; -+ } ++int NX_VpuIsInitialized(void) ++{ ++ return gstIsInitialized; ++} + -+ pInfo->frameDisplayFlag = VpuReadReg(pInfo->frameDisplayFlagRegAddr); -+ pInfo->readPos = VpuReadReg(pInfo->streamRdPtrRegAddr); -+ pInfo->streamEndflag = VpuReadReg(BIT_BIT_STREAM_PARAM); ++int swap_endian(unsigned char *data, int len) ++{ ++ unsigned int *p; ++ unsigned int v1, v2, v3; ++ int i; ++ int swap = 0; + -+ errReason = 0; -+ val = VpuReadReg(RET_DEC_SEQ_SUCCESS); -+ if (val & (1<<31)) -+ return VPU_RET_ERR_MEM_ACCESS; ++ p = (unsigned int *)data; + -+ if (pInfo->bitStreamMode == BS_MODE_PIC_END || -+ pInfo->bitStreamMode == BS_MODE_ROLLBACK) { -+ if (val & (1<<4)) { -+ errReason = VpuReadReg(RET_DEC_SEQ_SEQ_ERR_REASON); -+ NX_ErrMsg(("VPU decoder error: status=0x%x reason=0x%x\n", val, -+ errReason)); -+ return VPU_RET_ERROR; -+ } ++ for (i = 0; i < len/4; i += 2) { ++ v1 = p[i]; ++ v2 = (v1 >> 24) & 0xFF; ++ v2 |= ((v1 >> 16) & 0xFF) << 8; ++ v2 |= ((v1 >> 8) & 0xFF) << 16; ++ v2 |= ((v1 >> 0) & 0xFF) << 24; ++ v3 = v2; ++ v1 = p[i+1]; ++ v2 = (v1 >> 24) & 0xFF; ++ v2 |= ((v1 >> 16) & 0xFF) << 8; ++ v2 |= ((v1 >> 8) & 0xFF) << 16; ++ v2 |= ((v1 >> 0) & 0xFF) << 24; ++ p[i] = v2; ++ p[i+1] = v3; + } + -+ if (val == 0) { -+ errReason = VpuReadReg(RET_DEC_SEQ_SEQ_ERR_REASON); -+ NX_ErrMsg(("VPU decoder error: status=0 reason=0x%x\n", errReason)); -+ return VPU_RET_ERROR; -+ } ++ return swap; ++} + -+ val = VpuReadReg(RET_DEC_SEQ_SRC_SIZE); -+ pArg->outWidth = ((val >> 16) & 0xffff); -+ pArg->outHeight = (val & 0xffff); ++int NX_VpuParaInitialized(void *dev) ++{ ++ gstIsInitialized = 0; ++ gstIsVPUOn = 0; + -+ pArg->frameRateNum = VpuReadReg(RET_DEC_SEQ_FRATE_NR); -+ pArg->frameRateDen = VpuReadReg(RET_DEC_SEQ_FRATE_DR); ++ gstCodaClockEnRegVir = (uint32_t *)devm_ioremap_nocache(dev, ++ CODA960CLKENB_REG, 4); ++ if (!gstCodaClockEnRegVir) ++ return -1; + -+ if (pInst->codecMode == AVC_DEC && pArg->frameRateDen > 0) -+ pArg->frameRateDen *= 2; ++ gstIsolateBase = (uint32_t *)devm_ioremap_nocache(dev, ++ VPU_NISOLATE_REG, 128); ++ gstAliveBase = (uint32_t *)devm_ioremap_nocache(dev, ++ VPU_ALIVEGATE_REG, 128); ++ if (!gstIsolateBase || !gstAliveBase) ++ return -1; + -+ if (pInst->codecMode == MP4_DEC) { -+ val = VpuReadReg(RET_DEC_SEQ_INFO); -+ pArg->mp4ShortHeader = (val >> 2) & 1; -+ pArg->mp4PartitionEnable = val & 1; -+ pArg->mp4ReversibleVlcEnable = -+ pArg->mp4PartitionEnable ? -+ ((val >> 1) & 1) : 0; -+ pArg->h263AnnexJEnable = (val >> 3) & 1; -+ } else if (pInst->codecMode == VPX_DEC && pInst->auxMode == -+ VPX_AUX_VP8) { -+ /* h_scale[31:30] v_scale[29:28] pic_width[27:14] -+ * pic_height[13:0] */ -+ val = VpuReadReg(RET_DEC_SEQ_VP8_SCALE_INFO); -+ pArg->vp8HScaleFactor = (val >> 30) & 0x03; -+ pArg->vp8VScaleFactor = (val >> 28) & 0x03; -+ pArg->vp8ScaleWidth = (val >> 14) & 0x3FFF; -+ pArg->vp8ScaleHeight = (val >> 0) & 0x3FFF; -+ } ++ return 0; ++} +diff --git a/drivers/media/platform/nxp-vpu/nx_vpu_api.h b/drivers/media/platform/nxp-vpu/nx_vpu_api.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_vpu_api.h +@@ -0,0 +1,541 @@ ++/* ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * Author: Seonghee, Kim ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ + -+ pArg->minFrameBufCnt = VpuReadReg(RET_DEC_SEQ_FRAME_NEED); -+ pArg->frameBufDelay = VpuReadReg(RET_DEC_SEQ_FRAME_DELAY); ++#ifndef __NX_VPU_API_H__ ++#define __NX_VPU_API_H__ + -+ if (pInst->codecMode == AVC_DEC || pInst->codecMode == MP2_DEC) { -+ val = VpuReadReg(RET_DEC_SEQ_CROP_LEFT_RIGHT); -+ val2 = VpuReadReg(RET_DEC_SEQ_CROP_TOP_BOTTOM); -+ if (val == 0 && val2 == 0) { -+ pArg->cropLeft = 0; -+ pArg->cropRight = pArg->outWidth; -+ pArg->cropTop = 0; -+ pArg->cropBottom = pArg->outHeight; -+ } else { -+ pArg->cropLeft = ((val>>16) & 0xFFFF); -+ pArg->cropRight = pArg->outWidth - ((val & 0xFFFF)); -+ pArg->cropTop = ((val2>>16) & 0xFFFF); -+ pArg->cropBottom = pArg->outHeight - ((val2 & 0xFFFF)); -+ } ++#include "nx_port_func.h" ++#include "vpu_types.h" ++#include "nx_vpu_config.h" ++#include ++ ++/* Codec Mode */ ++enum { ++ AVC_DEC = 0, ++ VC1_DEC = 1, ++ MP2_DEC = 2, ++ MP4_DEC = 3, ++ DV3_DEC = 3, ++ RV_DEC = 4, ++ AVS_DEC = 5, ++ MJPG_DEC = 6, ++ VPX_DEC = 7, ++ ++ AVC_ENC = 8, ++ MP4_ENC = 11, ++ MJPG_ENC = 13 ++}; ++ ++/* MPEG4 Aux Mode */ ++enum { ++ MP4_AUX_MPEG4 = 0, ++ MP4_AUX_DIVX3 = 1 ++}; ++ ++/* VPX Aux Mode */ ++enum { ++ VPX_AUX_THO = 0, ++ VPX_AUX_VP6 = 1, ++ VPX_AUX_VP8 = 2 ++}; ++ ++/* AVC Aux Mode */ ++enum { ++ AVC_AUX_AVC = 0, ++ AVC_AUX_MVC = 1 ++}; ++ ++/* Interrupt Register Bit Enumerate */ ++enum { ++ VPU_INT_BIT_INIT = 0, ++ VPU_INT_BIT_SEQ_INIT = 1, ++ VPU_INT_BIT_SEQ_END = 2, ++ VPU_INT_BIT_PIC_RUN = 3, ++ VPU_INT_BIT_FRAMEBUF_SET = 4, ++ VPU_INT_BIT_ENC_HEADER = 5, ++ VPU_INT_BIT_DEC_PARA_SET = 7, ++ VPU_INT_BIT_DEC_BUF_FLUSH = 8, ++ VPU_INT_BIT_USERDATA = 9, ++ VPU_INT_BIT_DEC_FIELD = 10, ++ VPU_INT_BIT_DEC_MB_ROWS = 13, ++ VPU_INT_BIT_BIT_BUF_EMPTY = 14, ++ VPU_INT_BIT_BIT_BUF_FULL = 15 ++}; ++ ++enum { ++ SW_RESET_SAFETY, ++ SW_RESET_FORCE, ++ SW_RESET_ON_BOOT ++}; ++ ++enum nx_vpu_bit_chg_para { ++ VPU_BIT_CHG_GOP = 1, /* GOP */ ++ VPU_BIT_CHG_INTRAQP = (1 << 1), /* Intra Qp */ ++ VPU_BIT_CHG_BITRATE = (1 << 2), /* Bit Rate */ ++ VPU_BIT_CHG_FRAMERATE = (1 << 3), /* Frame Rate */ ++ VPU_BIT_CHG_INTRARF = (1 << 4), /* Intra Refresh */ ++ VPU_BIT_CHG_SLICEMOD = (1 << 5), /* Slice Mode */ ++ VPU_BIT_CHG_HECMODE = (1 << 6), /* HEC Mode */ ++}; ++ ++enum bit_stream_mode { ++ BS_MODE_INTERRUPT, ++ BS_MODE_ROLLBACK, ++ BS_MODE_PIC_END ++}; + -+ val = (pArg->outWidth * pArg->outHeight * 3 / 2) / 1024; -+ pArg->numSliceSize = val / 4; -+ pArg->worstSliceSize = val / 2; -+ } else { -+ pArg->cropLeft = 0; -+ pArg->cropRight = pArg->outWidth; -+ pArg->cropTop = 0; -+ pArg->cropBottom = pArg->outHeight; -+ } ++enum mp4_header_type { ++ VOL_HEADER, ++ VOS_HEADER, ++ VIS_HEADER ++}; + -+ val = VpuReadReg(RET_DEC_SEQ_HEADER_REPORT); -+ pArg->profile = (val >> 0) & 0xFF; -+ pArg->level = (val >> 8) & 0xFF; -+ pArg->interlace = (val >> 16) & 0x01; -+ pArg->direct8x8Flag = (val >> 17) & 0x01; -+ pArg->vc1Psf = (val >> 18) & 0x01; -+ pArg->constraint_set_flag[0] = (val >> 19) & 0x01; -+ pArg->constraint_set_flag[1] = (val >> 20) & 0x01; -+ pArg->constraint_set_flag[2] = (val >> 21) & 0x01; -+ pArg->constraint_set_flag[3] = (val >> 22) & 0x01; -+ pArg->avcIsExtSAR = (val >> 25) & 0x01; -+ pArg->maxNumRefFrmFlag = (val >> 31) & 0x01; ++enum avc_header_type { ++ SPS_RBSP, ++ PPS_RBSP, ++ END_SEQ_RBSP, ++ END_STREAM_RBSP, ++ SPS_RBSP_MVC, ++ PPS_RBSP_MVC, ++}; + -+ pArg->aspectRateInfo = VpuReadReg(RET_DEC_SEQ_ASPECT); ++/* Define VPU Low-Level Return Value */ ++enum nx_vpu_ret { ++ VPU_RET_ERR_STRM_FULL = -24, /* Bitstream Full */ ++ VPU_RET_ERR_SRAM = -23, /* VPU SRAM Configruation Failed */ ++ VPU_RET_ERR_INST = -22, /* VPU Have No Instance Space */ ++ VPU_RET_BUSY = -21, /* VPU H/W Busy */ ++ VPU_RET_ERR_TIMEOUT = -20, /* VPU Wait Timeout */ ++ VPU_RET_ERR_MEM_ACCESS = -19, /* Memory Access Violation */ + -+ val = VpuReadReg(RET_DEC_SEQ_BIT_RATE); -+ pArg->bitrate = val; ++ VPU_RET_ERR_CHG_PARAM = -6, /* VPU Not Changed */ ++ VPU_RET_ERR_WRONG_SEQ = -5, /* Wrong Sequence */ ++ VPU_RET_ERR_PARAM = -4, /* VPU Invalid Parameter */ ++ VPU_RET_ERR_RUN = -3, ++ VPU_RET_ERR_INIT = -2, /* VPU Not Initialized */ ++ VPU_RET_ERROR = -1, /* General operation failed */ ++ VPU_RET_OK = 0, ++ VPU_RET_NEED_STREAM = 1, /* Need More Stream */ ++}; + -+ if (pInst->codecMode == AVC_DEC) { -+ val = VpuReadReg(RET_DEC_SEQ_VUI_INFO); -+ pArg->vui_info.fixedFrameRateFlag = val & 1; -+ pArg->vui_info.timingInfoPresent = (val>>1) & 0x01; -+ pArg->vui_info.chromaLocBotField = (val>>2) & 0x07; -+ pArg->vui_info.chromaLocTopField = (val>>5) & 0x07; -+ pArg->vui_info.chromaLocInfoPresent = (val>>8) & 0x01; -+ pArg->vui_info.colorPrimaries = (val>>16) & 0xff; -+ pArg->vui_info.colorDescPresent = (val>>24) & 0x01; -+ pArg->vui_info.isExtSAR = (val>>25) & 0x01; -+ pArg->vui_info.vidFullRange = (val>>26) & 0x01; -+ pArg->vui_info.vidFormat = (val>>27) & 0x07; -+ pArg->vui_info.vidSigTypePresent = (val>>30) & 0x01; -+ pArg->vui_info.vuiParamPresent = (val>>31) & 0x01; + -+ val = VpuReadReg(RET_DEC_SEQ_VUI_PIC_STRUCT); -+ pArg->vui_info.vuiPicStructPresent = (val & 0x1); -+ pArg->vui_info.vuiPicStruct = (val>>1); -+ } ++/* Common Memory Information */ + -+ if (pInst->codecMode == MP2_DEC) { -+ /* seq_ext info */ -+ val = VpuReadReg(RET_DEC_SEQ_EXT_INFO); -+ pArg->mp2LowDelay = val & 1; -+ pArg->mp2DispVerSize = (val>>1) & 0x3fff; -+ pArg->mp2DispHorSize = (val>>15) & 0x3fff; -+ } ++struct sec_axi_info { ++ int useBitEnable; ++ int useIpEnable; ++ int useDbkYEnable; ++ int useDbkCEnable; ++ int useOvlEnable; ++ int useBtpEnable; ++ unsigned int bufBitUse; ++ unsigned int bufIpAcDcUse; ++ unsigned int bufDbkYUse; ++ unsigned int bufDbkCUse; ++ unsigned int bufOvlUse; ++ unsigned int bufBtpUse; ++ int bufSize; ++}; + -+ pInfo->writePos = VpuReadReg(pInfo->streamWrPtrRegAddr); -+ pInfo->readPos = VpuReadReg(pInfo->streamRdPtrRegAddr); ++struct enc_mp4_param { ++ int mp4DataPartitionEnable; ++ int mp4ReversibleVlcEnable; ++ int mp4IntraDcVlcThr; ++ int mp4HecEnable; ++ int mp4Verid; ++}; + -+ pArg->strmWritePos = pInfo->writePos - pInfo->strmBufPhyAddr; -+ pArg->strmReadPos = pInfo->readPos - pInfo->strmBufPhyAddr; ++struct enc_h263_param { ++ int h263AnnexIEnable; ++ int h263AnnexJEnable; ++ int h263AnnexKEnable; ++ int h263AnnexTEnable; ++}; + -+ pInfo->width = pArg->outWidth; -+ pInfo->height = pArg->outHeight; ++struct enc_avc_param { ++ /* CMD_ENC_SEQ_264_PARA Register (0x1A0) */ ++ int chromaQpOffset; /* bit [4:0] */ ++ int constrainedIntraPredFlag; /* bit [5] */ ++ int disableDeblk; /* bit [7:6] */ ++ int deblkFilterOffsetAlpha; /* bit [11:8] */ ++ int deblkFilterOffsetBeta; /* bit [15:12] */ + -+ pInst->isInitialized = 1; ++ /* CMD_ENC_SEQ_OPTION Register */ ++ int audEnable; /* bit[2] AUD(Access Unit Delimiter) */ + -+ return VPU_RET_OK; -+} ++ /* Crop Info */ ++ int enableCrop; ++ int cropLeft; ++ int cropTop; ++ int cropRight; ++ int cropBottom; ++}; + -+static int VPU_DecSeqInitCommand(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_seq_init_arg *pArg) -+{ -+ unsigned int val, reason; -+ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; ++struct enc_jpeg_info { ++ int picWidth; ++ int picHeight; ++ int alignedWidth; ++ int alignedHeight; ++ int frameIdx; ++ int format; + -+ if (pArg->disableOutReorder) { -+ NX_DbgMsg(INFO_MSG, ("Disable Out Reordering!!!\n")); -+ pInfo->low_delay_info.lowDelayEn = 1; -+ pInfo->low_delay_info.numRows = 0; -+ } ++ int rotationEnable; ++ int rotationAngle; ++ int mirrorEnable; ++ int mirrorDirection; + -+ if (pInfo->needMoreFrame) { -+ pInfo->needMoreFrame = 0; -+ VpuWriteReg(pInfo->streamWrPtrRegAddr, pInfo->writePos); -+ NX_DbgMsg(INFO_MSG, ("Need More Buffer!!!!!\n")); -+ goto WAIT_INTERRUPT; -+ } ++ int rstIntval; ++ int busReqNum; ++ int mcuBlockNum; ++ int compNum; ++ int compInfo[3]; + -+ pInfo->enableMp4Deblock = pArg->enablePostFilter; ++ unsigned int huffCode[4][256]; ++ unsigned int huffSize[4][256]; ++ unsigned char huffVal[4][162]; ++ unsigned char huffBits[4][256]; ++ unsigned char qMatTab[4][64]; ++ unsigned char cInfoTab[4][6]; + -+ VpuWriteReg(CMD_DEC_SEQ_BB_START, pInfo->strmBufPhyAddr); -+ VpuWriteReg(CMD_DEC_SEQ_BB_SIZE, pInfo->strmBufSize / 1024); ++ uint8_t jpegHeader[1024]; ++ int32_t headerSize; ++}; + -+#if (DBG_REGISTER) -+ { -+ int i; ++struct vpu_enc_info { ++ int codecStd; + -+ VpuWriteReg(BIT_BIT_STREAM_PARAM, 0); ++ /* input picture */ ++ int srcWidth; ++ int srcHeight; + -+ /* Clear Stream end flag */ -+ i = (int)VpuReadReg(BIT_BIT_STREAM_PARAM); -+ if (i & (1 << (pInst->instIndex + 2))) -+ i -= 1 << (pInst->instIndex + 2); -+ VpuWriteReg(BIT_BIT_STREAM_PARAM, i); -+ } -+#endif ++ /* encoding image size */ ++ int encWidth; ++ int encHeight; + -+ if (pArg->enableUserData) { -+ pInfo->userDataBufPhyAddr = -+ (uint64_t)pArg->userDataBuffer.phyAddr; -+ pInfo->userDataBufVirAddr = -+ (unsigned long)pArg->userDataBuffer.virAddr; -+ pInfo->userDataBufSize = pArg->userDataBuffer.size; -+ pInfo->userDataEnable = 1; -+ pInfo->userDataReportMode = 1; ++ int gopSize; ++ int bitRate; ++ int frameRateNum; /* framerate */ ++ int frameRateDen; + -+ val = 0; -+ val |= (pInfo->userDataReportMode << 10); -+ /* val |= (pInfo->userDataEnable << 5); */ -+ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_OPTION, val); -+ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_BASE_ADDR, -+ pInfo->userDataBufPhyAddr); -+ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_BUF_SIZE, -+ pInfo->userDataBufSize); -+ } else { -+ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_OPTION, 0); -+ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_BASE_ADDR, 0); -+ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_BUF_SIZE, 0); -+ } -+ val = 0; ++ int rotateAngle; /* 0/90/180/270 */ ++ int mirrorDirection; /* 0/1/2/3 */ + -+ if (!pInfo->low_delay_info.lowDelayEn) -+ val |= (pInfo->enableReordering<<1) & 0x2; ++ int sliceMode; ++ int sliceSizeMode; ++ int sliceSize; + -+ val |= (pInfo->enableMp4Deblock & 0x1); ++ int bwbEnable; ++ int cbcrInterleave; /* Input Frame's CbCrInterleave */ ++ int cbcrInterleaveRefFrame; /* Reference Frame's CbCrInterleave */ ++ int frameEndian; + -+ /*Enable error conceal on missing reference in h.264/AVC */ -+ val |= (pInfo->avcErrorConcealMode << 2); ++ int frameQp; ++ int jpegQuality; + -+ VpuWriteReg(CMD_DEC_SEQ_OPTION, val); ++ /* Frame Buffers */ ++ int minFrameBuffers; ++ int frameBufMapType; ++ struct nx_vid_memory_info frameBuffer[3]; ++ uint64_t subSampleAPhyAddr; ++ uint64_t subSampleBPhyAddr; ++ struct sec_axi_info sec_axi_info; ++ /* for CMD_SET_FRAME_CACHE_CONFIG register */ ++ unsigned int cacheConfig; + -+ switch (pInst->codecMode) { -+ case VC1_DEC: -+ /* VpuWriteReg(CMD_DEC_SEQ_VC1_STREAM_FMT, 1); -+ VpuWriteReg(CMD_DEC_SEQ_VC1_STREAM_FMT, 2); */ -+ VpuWriteReg(CMD_DEC_SEQ_VC1_STREAM_FMT, (0 << 3) & 0x08); -+ break; -+ case MP4_DEC: -+ VpuWriteReg(CMD_DEC_SEQ_MP4_ASP_CLASS, -+ (VPU_GMC_PROCESS_METHOD<<3) | pInfo->mp4Class); -+ break; -+ case AVC_DEC: -+ VpuWriteReg(CMD_DEC_SEQ_X264_MV_EN, VPU_AVC_X264_SUPPORT); -+ break; -+ } ++ /* Mpeg4 Encoder Only (for data partition) */ ++ uint64_t usbSampleDPPhyAddr; ++ uint32_t usbSampleDPSize; + -+ if (pInst->codecMode == AVC_DEC) -+ VpuWriteReg(CMD_DEC_SEQ_SPP_CHUNK_SIZE, VPU_GBU_SIZE); ++ int linear2TiledEnable; + -+ VpuWriteReg(pInfo->streamWrPtrRegAddr, pInfo->writePos); -+ VpuWriteReg(pInfo->streamRdPtrRegAddr, pInfo->readPos); ++ /* Output Stream Buffer's Address & Size */ ++ uint64_t strmBufVirAddr; ++ uint64_t strmBufPhyAddr; ++ int strmBufSize; + -+ /* Clear Stream Flag */ -+ pInfo->streamEndflag &= ~(1<<2); /* Clear End of Stream */ -+ pInfo->streamEndflag &= ~(3<<3); /* Clear Bitstream Mode */ -+ if (pInfo->bitStreamMode == BS_MODE_ROLLBACK) /*rollback mode */ -+ pInfo->streamEndflag |= (1<<3); -+ else if (pInfo->bitStreamMode == BS_MODE_PIC_END) -+ pInfo->streamEndflag |= (2<<3); -+ else { /* Interrupt Mode */ -+ if (pInfo->seqInitEscape) -+ pInfo->streamEndflag |= (2<<3); -+ } ++ unsigned int ringBufferEnable; ++ unsigned int strmWritePrt; /* Bitstream Write Ptr */ ++ unsigned int strmReadPrt; /* Bitstream Read Ptr */ ++ unsigned int strmEndFlag; /* Bitstream End Flag */ + -+ VpuWriteReg(BIT_BIT_STREAM_PARAM, pInfo->streamEndflag); -+ VpuWriteReg(BIT_BIT_STREAM_CTRL, pInfo->streamEndian); ++ int userQpMax; /* User Max Quantization */ ++ int userGamma; /* User Gamma Factor */ + -+ val = 0; -+ val |= (pInfo->bwbEnable<<12); -+ val |= (pInfo->cbcrInterleave<<2); -+ VpuWriteReg(BIT_FRAME_MEM_CTRL, val); ++ /* Rate Control */ ++ int rcEnable; /* Rate Control Enable */ ++ int rcIntraQp; + -+ if (pInst->codecMode != MJPG_DEC) -+ VpuWriteReg(pInfo->frameDisplayFlagRegAddr, 0); ++ /* (MB Mode(0), Frame Mode(1), Slice Mode(2), MB-NumMode(3) */ ++ int rcIntervalMode; ++ int mbInterval; ++ int rcIntraCostWeigth; ++ int enableAutoSkip; ++ int initialDelay; ++ int vbvBufSize; ++ int intraRefresh; + -+#if (DBG_REGISTER) -+ { -+ int reg; ++ union { ++ struct enc_avc_param avcEncParam; ++ struct enc_mp4_param mp4EncParam; ++ struct enc_h263_param h263EncParam; ++ struct enc_jpeg_info jpgEncInfo; ++ } enc_codec_para; + -+ NX_DbgMsg(DBG_REGISTER, ("[DEC_SEQ_INIT]\n")); -+ NX_DbgMsg(DBG_REGISTER, ("[Strm_CTRL : 0x10C]%x\n", -+ VpuReadReg(BIT_BIT_STREAM_CTRL))); -+ for (reg = 0x180 ; reg < 0x200 ; reg += 16) { -+ NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", -+ reg, VpuReadReg(BIT_BASE + reg), -+ VpuReadReg(BIT_BASE + reg + 4), -+ VpuReadReg(BIT_BASE + reg + 8), -+ VpuReadReg(BIT_BASE + reg + 12))); -+ } -+ } -+#endif ++ /* Motion Estimation */ ++ int MEUseZeroPmv; ++ int MESearchRange; ++ int MEBlockMode; ++}; + -+ VpuBitIssueCommand(pInst, SEQ_INIT); ++struct low_delay_info { ++ int lowDelayEn; ++ int numRows; ++}; + -+WAIT_INTERRUPT: -+ reason = VPU_WaitBitInterrupt(pInst->devHandle, VPU_DEC_TIMEOUT); -+ if (!reason) { -+ NX_ErrMsg(("VPU_DecSeqInitCommand() Failed. Timeout(%d)\n", -+ VPU_BUSY_CHECK_TIMEOUT)); -+ NX_ErrMsg(("WritePos = 0x%.8x, ReadPos = 0x%.8x\n", -+ VpuReadReg(pInfo->streamWrPtrRegAddr), -+ VpuReadReg(pInfo->streamRdPtrRegAddr))); -+ return VPU_RET_ERR_TIMEOUT; -+ } ++struct vpu_dec_info { ++ int codecStd; + -+ if (reason & (1<needMoreFrame = 1; -+ return VPU_RET_NEED_STREAM; -+ } else { -+ return VPU_RET_ERROR; -+ } -+} ++ int width; ++ int height; + -+static void setBufAddr(char *paramVirAddr, unsigned idx, unsigned value) -+{ -+ ((uint32_t*)paramVirAddr)[idx ^ 1] = cpu_to_le32(value); -+} ++ /* Input Stream Buffer Address */ ++ uint64_t streamRdPtrRegAddr; /* BIT_RD_PTR or MJPEG_BBC_RD_PTR_REG */ ++ uint64_t streamWrPtrRegAddr; /* BIT_WR_PTR or MJPEG_BBC_WR_PTR_REG */ ++ uint64_t frameDisplayFlagRegAddr; + -+static int VPU_DecRegisterFrameBufCommand(struct nx_vpu_codec_inst -+ *pInst, struct vpu_dec_reg_frame_arg *pArg) -+{ -+ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; -+ unsigned i, val; ++ uint64_t strmBufPhyAddr; ++ uint64_t strmBufVirAddr; ++ int needMoreFrame; ++ int strmBufSize; ++ int bitStreamMode; + -+ pInfo->cbcrInterleave = pArg->chromaInterleave; -+ pInfo->cacheConfig = -+ MaverickCache2Config(1, pInfo->cbcrInterleave, 0, 0, 3, 0, 15); ++ int bwbEnable; ++ int cbcrInterleave; + -+ SetTiledMapType(VPU_LINEAR_FRAME_MAP, pArg->strideY, -+ pInfo->cbcrInterleave); ++ int seqInitEscape; + -+ for (i = 0; i < pArg->numFrameBuffer; i++) { -+ const uint32_t *phyAddr = pArg->phyAddrs->addr[i]; ++ /* User Data */ ++ int userDataEnable; ++ int userDataReportMode; ++ uint64_t userDataBufPhyAddr; ++ uint64_t userDataBufVirAddr; ++ int userDataBufSize; + -+ setBufAddr(pInst->paramVirAddr, 3 * i, phyAddr[0]); -+ setBufAddr(pInst->paramVirAddr, 3 * i + 1, phyAddr[1]); -+ if (pInfo->cbcrInterleave == 0) -+ setBufAddr(pInst->paramVirAddr, 3 * i + 2, phyAddr[2]); -+ } ++ /* Low Dealy Information */ ++ struct low_delay_info low_delay_info; + -+ pInfo->strideY = pArg->strideY; -+ pInfo->phyAddrs = *pArg->phyAddrs; ++ unsigned int readPos; ++ unsigned int writePos; + -+ /* MV allocation and registe */ -+ if (pInst->codecMode == AVC_DEC || pInst->codecMode == VC1_DEC || -+ pInst->codecMode == MP4_DEC || pInst->codecMode == RV_DEC || -+ pInst->codecMode == AVS_DEC) -+ { -+ unsigned mvStartAddr = pArg->colMvBuffer->phyAddr; -+ int size_mvcolbuf = ((pInfo->width+31)&~31) * -+ ((pInfo->height+31)&~31); ++ /* Frame Buffer Information (Instance Global) */ ++ int numFrameBuffer; ++ uint32_t strideY; ++ struct vpu_dec_phy_addr_info phyAddrs; ++ struct sec_axi_info sec_axi_info; ++ /* for CMD_SET_FRAME_CACHE_CONFIG register */ ++ int cacheConfig; + -+ size_mvcolbuf = (size_mvcolbuf*3) / 2; -+ size_mvcolbuf = (size_mvcolbuf+4) / 5; -+ size_mvcolbuf = ((size_mvcolbuf+7) / 8) * 8; ++ int bytePosFrameStart; ++ int bytePosFrameEnd; + -+ if (pInst->codecMode == AVC_DEC) { -+ for (i = 0; i < pArg->numFrameBuffer; i++) { -+ setBufAddr(pInst->paramVirAddr + 384, i, mvStartAddr); -+ mvStartAddr += size_mvcolbuf; -+ } -+ } else { -+ setBufAddr(pInst->paramVirAddr + 384, 0, mvStartAddr); -+ } -+ } ++ /* Options */ ++ int enableReordering; /* enable reordering */ ++ int enableMp4Deblock; /* Mpeg4 Deblocking Option */ + -+ if (!ConfigDecSecAXI(pInfo->codecStd, &pInfo->sec_axi_info, -+ pInfo->width, pInfo->height, pArg->sramAddr, pArg->sramSize)) { -+ NX_ErrMsg(("ConfigDecSecAXI() failed !!!\n")); -+ NX_ErrMsg(("Width = %d, Heigth = %d\n", -+ pInfo->width, pInfo->height)); -+ return VPU_RET_ERR_SRAM; -+ } ++ /* MPEG-4/Divx5.0 or Higher/XVID/Divx4.0/old XVID ++ (Compress Type --> class) */ ++ int mp4Class; + -+ /* Tell the decoder how much frame buffers were allocated. */ -+ VpuWriteReg(CMD_SET_FRAME_BUF_NUM, pArg->numFrameBuffer); -+ VpuWriteReg(CMD_SET_FRAME_BUF_STRIDE, pArg->strideY); -+ VpuWriteReg(CMD_SET_FRAME_AXI_BIT_ADDR, pInfo->sec_axi_info.bufBitUse); -+ VpuWriteReg(CMD_SET_FRAME_AXI_IPACDC_ADDR, -+ pInfo->sec_axi_info.bufIpAcDcUse); -+ VpuWriteReg(CMD_SET_FRAME_AXI_DBKY_ADDR, -+ pInfo->sec_axi_info.bufDbkYUse); -+ VpuWriteReg(CMD_SET_FRAME_AXI_DBKC_ADDR, -+ pInfo->sec_axi_info.bufDbkCUse); -+ VpuWriteReg(CMD_SET_FRAME_AXI_OVL_ADDR, pInfo->sec_axi_info.bufOvlUse); -+ VpuWriteReg(CMD_SET_FRAME_AXI_BTP_ADDR, pInfo->sec_axi_info.bufBtpUse); -+ VpuWriteReg(CMD_SET_FRAME_DELAY, pInfo->frameDelay); ++ /* VC1 Specific Information */ ++ int vc1BframeDisplayValid; + -+ /* Maverick Cache Configuration */ -+ VpuWriteReg(CMD_SET_FRAME_CACHE_CONFIG, pInfo->cacheConfig); ++ /* AVC Specific Information */ ++ int avcErrorConcealMode; + -+ if (pInst->codecMode == VPX_DEC) { -+ VpuWriteReg(CMD_SET_FRAME_MB_BUF_BASE, -+ pArg->pvbSliceBuffer->phyAddr); -+ } ++ int frameDelay; ++ int streamEndflag; ++ int streamEndian; ++ int frameDisplayFlag; ++ int clearDisplayIndexes; + -+ if (pInst->codecMode == AVC_DEC) { -+ VpuWriteReg(CMD_SET_FRAME_SLICE_BB_START, -+ pArg->sliceBuffer->phyAddr); -+ VpuWriteReg(CMD_SET_FRAME_SLICE_BB_SIZE, -+ pArg->sliceBuffer->size/1024); -+ } ++ /* Jpeg Specific Information */ ++ int frmBufferValid[MAX_REG_FRAME]; + -+ val = 0; -+ val |= (VPU_ENABLE_BWB<<12); -+ val |= (pInfo->cbcrInterleave<<2); -+ val |= VPU_FRAME_ENDIAN; -+ VpuWriteReg(BIT_FRAME_MEM_CTRL, val); -+ VpuWriteReg(CMD_SET_FRAME_MAX_DEC_SIZE, 0); ++ unsigned int headerSize; ++ int thumbnailMode; ++ int decodeIdx; + -+ VpuBitIssueCommand(pInst, SET_FRAME_BUF); ++ int imgFormat; ++ int rstInterval; ++ int userHuffTable; + -+#if (DBG_REGISTER) -+ { -+ int reg; ++ unsigned char huffBits[4][256]; ++ unsigned char huffPtr[4][16]; ++ unsigned int huffMin[4][16]; ++ unsigned int huffMax[4][16]; + -+ NX_DbgMsg(DBG_REGISTER, ("[DEC_SET_FRM_BUF_Reg]\n")); -+ for (reg = 0x180 ; reg < 0x200 ; reg += 16) { -+ NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", -+ reg, VpuReadReg(BIT_BASE + reg), -+ VpuReadReg(BIT_BASE + reg + 4), -+ VpuReadReg(BIT_BASE + reg + 8), -+ VpuReadReg(BIT_BASE + reg + 12))); -+ } -+ } -+#endif ++ unsigned char huffValue[4][162]; ++ unsigned char infoTable[4][6]; ++ unsigned char quantTable[4][64]; + -+ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, -+ BIT_BUSY_FLAG)) { -+ NX_ErrMsg(("Error VPU_DecRegisterFrameBufCommand failed!!!\n")); -+ return VPU_RET_ERR_INIT; -+ } ++ int huffDcIdx; ++ int huffAcIdx; ++ int qIdx; + -+ if (VpuReadReg(RET_SET_FRAME_SUCCESS) & (1<<31)) -+ return VPU_RET_ERR_MEM_ACCESS; ++ int busReqNum; ++ int mcuBlockNum; ++ int compNum; ++ int compInfo[3]; ++ int mcuWidth; ++ int mcuHeight; + -+ FUNC_OUT(); -+ return VPU_RET_OK; -+} ++ int pagePtr; ++ int wordPtr; ++ int bitPtr; + -+static int VPU_DecGetOutputInfo(struct nx_vpu_codec_inst *pInst, -+ struct vpu_dec_frame_arg *pArg) -+{ -+ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; -+ unsigned int val, val2; -+ struct vpu_rect rectInfo; ++ int validFlg; ++}; + -+ val = VpuReadReg(RET_DEC_PIC_SUCCESS); -+ if (val & (1<<31)) { -+ pArg->errReason = VpuReadReg(GDI_WPROT_ERR_RSN); -+ pArg->errAddress = VpuReadReg(GDI_WPROT_ERR_ADR); -+ return VPU_RET_ERR_MEM_ACCESS; -+ } ++struct nx_vpu_codec_inst { ++ void *devHandle; ++ int inUse; ++ int instIndex; ++ int isInitialized; ++ int codecMode; ++ int auxMode; ++ uint64_t paramPhyAddr; /* Common Area */ ++ char *paramVirAddr; ++ uint32_t paramBufSize; ++ uint64_t instBufPhyAddr; ++ union{ ++ struct vpu_dec_info decInfo; ++ struct vpu_enc_info encInfo; ++ } codecInfo; ++}; + -+ if (pInst->codecMode == AVC_DEC) { -+ pArg->notSufficientPsBuffer = (val >> 3) & 0x1; -+ pArg->notSufficientSliceBuffer = (val >> 2) & 0x1; -+ } ++/* BIT_RUN command */ ++enum nx_vpu_cmd { ++ SEQ_INIT = 1, ++ SEQ_END = 2, ++ PIC_RUN = 3, ++ SET_FRAME_BUF = 4, ++ ENCODE_HEADER = 5, ++ ENC_PARA_SET = 6, ++ DEC_PARA_SET = 7, ++ DEC_BUF_FLUSH = 8, ++ RC_CHANGE_PARAMETER = 9, ++ VPU_SLEEP = 10, ++ VPU_WAKE = 11, ++ ENC_ROI_INIT = 12, ++ FIRMWARE_GET = 0xf, + -+ pArg->indexFrameDecoded = VpuReadReg(RET_DEC_PIC_DECODED_IDX); -+ pArg->indexFrameDisplay = VpuReadReg(RET_DEC_PIC_DISPLAY_IDX); ++ GET_ENC_INSTANCE = 0x100, ++ ENC_RUN = 0x101, + -+ val = VpuReadReg(RET_DEC_PIC_SIZE);/* decoding picture size */ -+ pArg->outWidth = (val>>16) & 0xFFFF; -+ pArg->outHeight = (val) & 0xFFFF; ++ GET_DEC_INSTANCE = 0x200, ++ DEC_RUN = 0x201, ++}; + -+ /*if (pArg->indexFrameDecoded >= 0 && pArg->indexFrameDecoded < -+ MAX_REG_FRAME) */ -+ { -+ if ((pInst->codecMode == VPX_DEC) && (pInst->auxMode == -+ VPX_AUX_VP8)) { -+ /* VP8 specific header information -+ * h_scale[31:30] v_scale[29:28] pic_width[27:14] -+ * pic_height[13:0] */ -+ val = VpuReadReg(RET_DEC_PIC_VP8_SCALE_INFO); -+ pArg->scale_info.hScaleFactor = (val >> 30) & 0x03; -+ pArg->scale_info.vScaleFactor = (val >> 28) & 0x03; -+ pArg->scale_info.picWidth = (val >> 14) & 0x3FFF; -+ pArg->scale_info.picHeight = (val >> 0) & 0x3FFF; ++enum vpu_gdi_tiled_map_type { ++ VPU_LINEAR_FRAME_MAP = 0, ++ VPU_TILED_FRAME_V_MAP = 1, ++ VPU_TILED_FRAME_H_MAP = 2, ++ VPU_TILED_FIELD_V_MAP = 3, ++ VPU_TILED_MIXED_V_MAP = 4, ++ VPU_TILED_FRAME_MB_RASTER_MAP = 5, ++ VPU_TILED_FIELD_MB_RASTER_MAP = 6, ++ VPU_TILED_MAP_TYPE_MAX ++}; + -+ /* ref_idx_gold[31:24], ref_idx_altr[23:16], -+ * ref_idx_last[15: 8], -+ * version_number[3:1], show_frame[0] */ -+ val = VpuReadReg(RET_DEC_PIC_VP8_PIC_REPORT); -+ pArg->pic_info.refIdxGold = (val >> 24) & 0x0FF; -+ pArg->pic_info.refIdxAltr = (val >> 16) & 0x0FF; -+ pArg->pic_info.refIdxLast = (val >> 8) & 0x0FF; -+ pArg->pic_info.versionNumber = (val >> 1) & 0x07; -+ pArg->pic_info.showFrame = (val >> 0) & 0x01; -+ } + -+ /* default value */ -+ rectInfo.left = 0; -+ rectInfo.right = pArg->outWidth; -+ rectInfo.top = 0; -+ rectInfo.bottom = pArg->outHeight; ++/* H/W Level APIs */ ++void NX_VPU_HwOn(void *, void *); ++void NX_VPU_HWOff(void *); ++int NX_VPU_GetCurPowerState(void); ++void NX_VPU_Clock(int on); + -+ if (pInst->codecMode == AVC_DEC || -+ pInst->codecMode == MP2_DEC) { -+ val = VpuReadReg(RET_DEC_PIC_CROP_LEFT_RIGHT); -+ val2 = VpuReadReg(RET_DEC_PIC_CROP_TOP_BOTTOM); ++int NX_VpuInit(void *pv, void *baseAddr, void *firmVirAddr, ++ uint32_t firmPhyAddr); ++int NX_VpuDeInit(void *); + -+ if (val == (unsigned int)-1 || val == 0) { -+ rectInfo.left = 0; -+ rectInfo.right = pArg->outWidth; -+ } else { -+ rectInfo.left = ((val>>16) & 0xFFFF); -+ rectInfo.right = pArg->outWidth - (val&0xFFFF); -+ } ++int NX_VpuSuspend(void *dev); ++int NX_VpuResume(void *dev, void *pVpuBaseAddr); + -+ if (val2 == (unsigned int)-1 || val2 == 0) { -+ rectInfo.top = 0; -+ rectInfo.bottom = pArg->outHeight; -+ } else { -+ rectInfo.top = ((val2>>16) & 0xFFFF); -+ rectInfo.bottom = pArg->outHeight - -+ (val2&0xFFFF); -+ } -+ } ++int VPU_WaitVpuBusy(int mSeconds, unsigned int busyFlagReg); + -+ pArg->outRect.left = rectInfo.left; -+ pArg->outRect.top = rectInfo.top; -+ pArg->outRect.right = rectInfo.right; -+ pArg->outRect.bottom = rectInfo.bottom; -+ } ++int VPU_SWReset(int resetMode); + -+ val = VpuReadReg(RET_DEC_PIC_TYPE); -+ pArg->isInterace = (val >> 18) & 0x1; ++struct nx_vpu_codec_inst *NX_VpuGetInstance(int index); ++int NX_VpuIsInitialized(void); ++int NX_VpuParaInitialized(void *dev); ++int swap_endian(unsigned char *data, int len); + -+ if (pInst->codecMode == MP2_DEC) { -+ pArg->progressiveFrame = (val >> 23) & 0x0003; -+ pArg->isInterace = (pArg->progressiveFrame == 0) ? (1) : (0); -+ pArg->picStructure = (val >> 19) & 0x0003; -+ } ++/* Encoder Specific APIs */ ++int NX_VpuEncOpen(struct vpu_open_arg *pOpenArg, void *devHandle, ++ struct nx_vpu_codec_inst **ppInst); ++int NX_VpuEncClose(struct nx_vpu_codec_inst *pInst, ++ void *vpu_event_present); ++int NX_VpuEncSetSeqParam(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_seq_arg *pSeqArg); ++int NX_VpuEncSetFrame(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_set_frame_arg *pFrmArg); ++int NX_VpuEncGetHeader(struct nx_vpu_codec_inst *pInst, ++ union vpu_enc_get_header_arg *pHeader); ++int NX_VpuEncRunFrame(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_run_frame_arg *pRunArg); ++int NX_VpuEncChgParam(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_chg_para_arg *pChgArg); + -+ if (pArg->isInterace) { -+ pArg->topFieldFirst = (val >> 21) & 0x0001; -+ pArg->picTypeFirst = (val & 0x38) >> 3; -+ pArg->picType = val & 0x7; -+ pArg->npf = (val >> 15) & 1; -+ } else { -+ pArg->topFieldFirst = 0; -+ pArg->picTypeFirst = 6; -+ pArg->picType = val & 0x7; -+ } ++/* Decoder Specific APIs */ ++int NX_VpuDecOpen(struct vpu_open_arg *pOpenArg, void *devHandle, ++ struct nx_vpu_codec_inst **ppInst); ++int NX_VpuDecClose(struct nx_vpu_codec_inst *pInst, ++ void *vpu_event_present); ++int NX_VpuDecSetSeqInfo(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_seq_init_arg *pSeqArg); ++int NX_VpuDecRegFrameBuf(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_reg_frame_arg *pFrmArg); ++int NX_VpuFillStreamBuffer(struct nx_vpu_codec_inst*, ++ void *strmData, unsigned strmDataSize); ++int NX_VpuDecRunFrame(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_frame_arg *pRunArg); ++int NX_VpuDecFlush(struct nx_vpu_codec_inst *pInst); ++int NX_VpuDecClrDspFlag(struct nx_vpu_codec_inst *pInst, unsigned index); + -+ if (pInst->codecMode == AVC_DEC) { -+ if (val & 0x40) { -+ if (pArg->isInterace) { -+ pArg->picTypeFirst = 6; /* IDR */ -+ pArg->picType = 6; -+ } else { -+ pArg->picType = 6; /* IDR */ -+ } -+ } -+ } ++/* Jpeg Encoder Specific APIs */ ++int JPU_EncRunFrame(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_run_frame_arg *pRunArg); + -+ pArg->fRateNumerator = VpuReadReg(RET_DEC_PIC_FRATE_NR); -+ pArg->fRateDenominator = VpuReadReg(RET_DEC_PIC_FRATE_DR); -+ if (pInst->codecMode == AVC_DEC && pArg->fRateDenominator > 0) -+ pArg->fRateDenominator *= 2; -+ if (pInst->codecMode == MP4_DEC) { -+ pArg->mp4ModuloTimeBase = -+ VpuReadReg(RET_DEC_PIC_MODULO_TIME_BASE); -+ pArg->mp4TimeIncrement = -+ VpuReadReg(RET_DEC_PIC_VOP_TIME_INCREMENT); -+ } ++/* Jpeg Decoder Specific APIs */ ++int JPU_DecSetSeqInfo(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_seq_init_arg *pSeqArg); ++int JPU_DecParseHeader(struct vpu_dec_info *pInfo, uint8_t *pbyStream, ++ int32_t iSize); ++int JPU_DecRegFrameBuf(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_reg_frame_arg *pFrmArg); ++int JPU_DecRunFrame(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_frame_arg *pRunArg); + -+ if (pInst->codecMode == VPX_DEC) -+ pArg->aspectRateInfo = 0; -+ else -+ pArg->aspectRateInfo = VpuReadReg(RET_DEC_PIC_ASPECT); + -+ pArg->numOfErrMBs = VpuReadReg(RET_DEC_PIC_ERR_MB); -+ val = VpuReadReg(RET_DEC_PIC_SUCCESS); -+ pArg->isSuccess = val; -+ pArg->sequenceChanged = ((val>>20) & 0x1); ++extern void vpu_soc_peri_reset_enter(void *pv); ++extern void vpu_soc_peri_reset_exit(void *pv); + -+ if (pInst->codecMode == VC1_DEC && pArg->indexFrameDisplay != -3) { -+ if (pInfo->vc1BframeDisplayValid == 0) { -+ if (pArg->picType == 2) -+ pArg->indexFrameDisplay = -3; -+ else -+ pInfo->vc1BframeDisplayValid = 1; -+ } -+ } ++extern int VPU_WaitBitInterrupt(void *devHandle, int mSeconds); ++extern int JPU_WaitInterrupt(void *devHandle, int timeOut); + -+ if (pInfo->codecStd == CODEC_STD_VC1) -+ pArg->multiRes = (VpuReadReg(RET_DEC_PIC_POST) >> 1) & 3; ++#endif/* __NX_VPU_API_H__ */ +diff --git a/drivers/media/platform/nxp-vpu/nx_vpu_config.h b/drivers/media/platform/nxp-vpu/nx_vpu_config.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_vpu_config.h +@@ -0,0 +1,111 @@ ++/* ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * Author: Seonghee, Kim ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ + -+ pInfo->readPos = VpuReadReg(pInfo->streamRdPtrRegAddr); -+ pInfo->frameDisplayFlag = VpuReadReg(pInfo->frameDisplayFlagRegAddr); ++#ifndef __NX_VPU_CONFIG_H__ ++#define __NX_VPU_CONFIG_H__ + -+ pInfo->bytePosFrameStart = VpuReadReg(BIT_BYTE_POS_FRAME_START); -+ pInfo->bytePosFrameEnd = VpuReadReg(BIT_BYTE_POS_FRAME_END); + -+ pArg->strmReadPos = pInfo->readPos - pInfo->strmBufPhyAddr; -+ pArg->strmWritePos = pInfo->writePos - pInfo->strmBufPhyAddr; ++#define NX_MAX_VPU_INSTANCE 16 + -+ return VPU_RET_OK; -+} ++/* VPU Clock Gating */ ++#define ENABLE_CLOCK_GATING ++/* #define ENABLE_POWER_SAVING */ + -+static int VPU_DecStartOneFrameCommand(struct nx_vpu_codec_inst -+ *pInst, struct vpu_dec_frame_arg *pArg) -+{ -+ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; -+ unsigned int val, reason = 0; ++#define NX_DBG_INFO 0 + -+ if (pInfo->needMoreFrame) { -+ pInfo->needMoreFrame = 0; -+ VpuWriteReg(pInfo->streamWrPtrRegAddr, pInfo->writePos); -+ NX_DbgMsg(INFO_MSG, ("Need More Buffer!!!!!\n")); -+ goto WAIT_INTERRUPT; -+ } ++/* Debug Register Access */ ++#define NX_REG_ACC_DEBUG 0 /* Use Debug Function */ ++#define NX_REG_EN_MSG 0 /* Enable Debug Message */ + -+ VpuWriteReg(RET_DEC_PIC_CROP_LEFT_RIGHT, 0); -+ VpuWriteReg(RET_DEC_PIC_CROP_TOP_BOTTOM, 0); + -+ VpuWriteReg(GDI_TILEDBUF_BASE, 0); ++/* ++ * Memory Size Config ++ * ++ * ----------------------- High Address ++ * | Instance (1MB) | ++ * ----------------------- ++ * | Param Buffer (1MB) | ++ * ----------------------- ++ * | Temp Buf (1MB) | ++ * ----------------------- ++ * | Working Buffer (1MB) | ++ * ----------------------- ++ * | Code Buffer (1MB) | ++ * ----------------------- Low Address ++ */ + -+ if ((pInfo->enableMp4Deblock & 2) && -+ ((pInfo->codecStd == CODEC_STD_MPEG4) || -+ (pInfo->codecStd == CODEC_STD_MPEG2) || -+ (pInfo->codecStd == CODEC_STD_H263) || -+ (pInfo->codecStd == CODEC_STD_DIV3))) -+ VpuWriteReg(CMD_DEC_PIC_ROT_MODE, 1 << 5); -+ else -+ VpuWriteReg(CMD_DEC_PIC_ROT_MODE, 0); + -+ if (pInfo->userDataEnable) { -+ VpuWriteReg(CMD_DEC_PIC_USER_DATA_BASE_ADDR, -+ pInfo->userDataBufPhyAddr); -+ VpuWriteReg(CMD_DEC_PIC_USER_DATA_BUF_SIZE, -+ pInfo->userDataBufSize); -+ } else { -+ VpuWriteReg(CMD_DEC_PIC_USER_DATA_BASE_ADDR, 0); -+ VpuWriteReg(CMD_DEC_PIC_USER_DATA_BUF_SIZE, 0); -+ } ++#define PARA_BUF_SIZE (12 * 1024) ++#define TEMP_BUF_SIZE (204 * 1024) ++#define CODE_BUF_SIZE (260 * 1024) + -+ val = 0; -+ /* if iframeSearch is Enable, other bit is ignore; */ -+ if (pArg->iFrameSearchEnable != 0) { -+ val |= (pInfo->userDataReportMode << 10); -+ if (pInst->codecMode == AVC_DEC) { -+ if (pArg->iFrameSearchEnable == 1) -+ val |= (1 << 11) | (1 << 2); -+ else if (pArg->iFrameSearchEnable == 2) -+ val |= (1 << 2); -+ } else { -+ val |= ((pArg->iFrameSearchEnable & 0x1) << 2); -+ } -+ } else { -+ val |= (pInfo->userDataReportMode << 10); -+ if (!pArg->skipFrameMode) -+ val |= (pInfo->userDataEnable << 5); -+ val |= (pArg->skipFrameMode << 3); -+ } ++#define COMMON_BUF_SIZE (CODE_BUF_SIZE+TEMP_BUF_SIZE+PARA_BUF_SIZE) + -+ if (pInst->codecMode == AVC_DEC && pInfo->low_delay_info.lowDelayEn) -+ val |= (pInfo->low_delay_info.lowDelayEn << 18); ++#define WORK_BUF_SIZE (80 * 1024) ++#define INST_BUF_SIZE (NX_MAX_VPU_INSTANCE*WORK_BUF_SIZE) + -+ VpuWriteReg(CMD_DEC_PIC_OPTION, val); ++#define DEC_STREAM_SIZE (1 * 1024 * 1024) + -+ if (pInfo->low_delay_info.lowDelayEn) -+ VpuWriteReg(CMD_DEC_PIC_NUM_ROWS, -+ pInfo->low_delay_info.numRows); -+ else -+ VpuWriteReg(CMD_DEC_PIC_NUM_ROWS, 0); ++#define VPU_LITTLE_ENDIAN 0 ++#define VPU_BIG_ENDIAN 1 + -+ val = 0; -+ val = ( -+ (pInfo->sec_axi_info.useBitEnable&0x01)<<0 | -+ (pInfo->sec_axi_info.useIpEnable&0x01)<<1 | -+ (pInfo->sec_axi_info.useDbkYEnable&0x01)<<2 | -+ (pInfo->sec_axi_info.useDbkCEnable&0x01)<<3 | -+ (pInfo->sec_axi_info.useOvlEnable&0x01)<<4 | -+ (pInfo->sec_axi_info.useBtpEnable&0x01)<<5 | -+ (pInfo->sec_axi_info.useBitEnable&0x01)<<8 | -+ (pInfo->sec_axi_info.useIpEnable&0x01)<<9 | -+ (pInfo->sec_axi_info.useDbkYEnable&0x01)<<10 | -+ (pInfo->sec_axi_info.useDbkCEnable&0x01)<<11 | -+ (pInfo->sec_axi_info.useOvlEnable&0x01)<<12 | -+ (pInfo->sec_axi_info.useBtpEnable&0x01)<<13); ++#define VPU_FRAME_ENDIAN VPU_LITTLE_ENDIAN ++#define VPU_FRAME_BUFFER_ENDIAN VPU_LITTLE_ENDIAN ++#define VPU_STREAM_ENDIAN VPU_LITTLE_ENDIAN + -+ VpuWriteReg(BIT_AXI_SRAM_USE, val); + -+ VpuWriteReg(pInfo->streamWrPtrRegAddr, pInfo->writePos); -+ VpuWriteReg(pInfo->streamRdPtrRegAddr, pInfo->readPos); ++#define CBCR_INTERLEAVE 0 ++#define VPU_ENABLE_BWB 1 ++#define ENC_FRAME_BUF_CBCR_INTERLEAVE 1 + -+ val = pInfo->frameDisplayFlag; -+ val &= ~pInfo->clearDisplayIndexes; -+ VpuWriteReg(pInfo->frameDisplayFlagRegAddr, val); -+ pInfo->clearDisplayIndexes = 0; + -+ if (pArg->eos) -+ pInfo->streamEndflag |= 1<<2; -+ else -+ pInfo->streamEndflag &= ~(1<<2); ++/* AXI Expander Select */ ++#define USE_NX_EXPND 1 + -+ pInfo->streamEndflag &= ~(3<<3); -+ if (pInfo->bitStreamMode == BS_MODE_ROLLBACK) -+ pInfo->streamEndflag |= (1<<3); -+ else if (pInfo->bitStreamMode == BS_MODE_PIC_END) -+ pInfo->streamEndflag |= (2<<3); ++/* Timeout */ ++#define VPU_BUSY_CHECK_TIMEOUT 500 /* 500 msec */ ++#define VPU_ENC_TIMEOUT 1000 /* 1 sec */ ++#define VPU_DEC_TIMEOUT 300 /* 300 msec */ ++#define JPU_ENC_TIMEOUT 1000 /* 1 sec */ ++#define JPU_DEC_TIMEOUT 1000 /* 1 sec */ + -+ VpuWriteReg(BIT_BIT_STREAM_PARAM, pInfo->streamEndflag); + -+ val = 0; -+ val |= (pInfo->bwbEnable<<12); -+ val |= ((pInfo->cbcrInterleave)<<2); -+ /* val |= pInfo->frameEndian; */ -+ VpuWriteReg(BIT_FRAME_MEM_CTRL, val); ++#define VPU_GBU_SIZE 1024 /* No modification required */ ++#define JPU_GBU_SIZE 512 /* No modification required */ + -+ val = pInfo->streamEndian; -+ VpuWriteReg(BIT_BIT_STREAM_CTRL, val); + -+#if (DBG_REGISTER) -+ { -+ int reg; ++#define MAX_REG_FRAME 31 + -+ NX_DbgMsg(DBG_REGISTER, ("[DEC_FRAME]\n")); -+ for (reg = 0x180 ; reg < 0x200 ; reg += 16) { -+ NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", -+ reg, VpuReadReg(BIT_BASE + reg), -+ VpuReadReg(BIT_BASE + reg + 4), -+ VpuReadReg(BIT_BASE + reg + 8), -+ VpuReadReg(BIT_BASE + reg + 12))); -+ } -+ } -+#endif + -+ VpuBitIssueCommand(pInst, PIC_RUN); ++/*---------------------------------------------------------------------------- ++ * Encoder Configurations ++ */ ++#define VPU_ENC_MAX_FRAME_BUF 3 ++#define VPU_ME_LINEBUFFER_MODE 2 + -+WAIT_INTERRUPT: -+ reason = VPU_WaitBitInterrupt(pInst->devHandle, VPU_DEC_TIMEOUT); -+ if (!reason) { -+ NX_ErrMsg(("VPU_DecStartOneFrameCommand() Fail. Timeout(%d)\n", -+ VPU_BUSY_CHECK_TIMEOUT)); -+ return VPU_RET_ERR_TIMEOUT; -+ } + -+ if (reason & (1<needMoreFrame = 1; -+ return VPU_RET_NEED_STREAM; -+ } else { -+ return VPU_RET_ERROR; -+ } -+} ++/*---------------------------------------------------------------------------- ++ * Decoder Configurations ++ */ ++#define VPU_REORDER_ENABLE 1 ++#define VPU_GMC_PROCESS_METHOD 0 ++#define VPU_AVC_X264_SUPPORT 1 + -+static int VPU_DecCloseCommand(struct nx_vpu_codec_inst *pInst, -+ void *vpu_event_present) -+{ -+ FUNC_IN(); -+ if (pInst->isInitialized) { -+ VpuBitIssueCommand(pInst, SEQ_END); -+ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, -+ BIT_BUSY_FLAG)) { -+ VpuWriteReg(BIT_INT_CLEAR, 0x1); -+ atomic_set((atomic_t *)vpu_event_present, 0); -+ NX_ErrMsg(("VPU_DecCloseCommand() Failed!!!\n")); -+ NX_ErrMsg(("Timeout(%d)\n", VPU_BUSY_CHECK_TIMEOUT)); -+ VPU_SWReset(SW_RESET_SAFETY); -+ pInst->isInitialized = 0; -+ return VPU_RET_ERR_TIMEOUT; -+ } -+ pInst->isInitialized = 0; -+ } ++#define VPU_SPP_CHUNK_SIZE 1024 /* AVC SPP */ + -+ VpuWriteReg(BIT_INT_CLEAR, 0x1); -+ atomic_set((atomic_t *)vpu_event_present, 0); -+ FUNC_OUT(); -+ return VPU_RET_OK; -+} -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_dec_v4l2.c b/drivers/media/platform/nxp-vpu/nx_vpu_dec_v4l2.c ---- a/drivers/media/platform/nxp-vpu/nx_vpu_dec_v4l2.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_vpu_dec_v4l2.c 2018-05-06 08:49:50.074731776 +0200 ++#endif /* __NX_VPU_CONFIG_H__ */ +diff --git a/drivers/media/platform/nxp-vpu/nx_vpu_dec_v4l2.c b/drivers/media/platform/nxp-vpu/nx_vpu_dec_v4l2.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_vpu_dec_v4l2.c @@ -0,0 +1,1625 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -107036,10 +106936,12 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_dec_v4l2.c b/drivers/media/ + } +} + -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c b/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c ---- a/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c 2018-05-06 08:49:50.074731776 +0200 -@@ -0,0 +1,995 @@ +diff --git a/drivers/media/platform/nxp-vpu/nx_vpu_decoder.c b/drivers/media/platform/nxp-vpu/nx_vpu_decoder.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_vpu_decoder.c +@@ -0,0 +1,1249 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * Author: Seonghee, Kim @@ -107069,37 +106971,43 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c b/drivers/media/p +#include "nx_vpu_gdi.h" + + -+#define DBG_REGISTER 0 -+#define DBG_ES_ADDR 0 -+#define INFO_MSG 0 ++#define DBG_USERDATA 0 ++#define DBG_REGISTER 0 ++#define DBG_ES_ADDR 0 ++#define INFO_MSG 0 + + +/*--------------------------------------------------------------------------- */ -+/* Define Static Functions */ -+static void VPU_EncDefaultParam(struct vpu_enc_info *pInfo); -+static int VPU_EncSeqCommand(struct nx_vpu_codec_inst *pInst); -+static int VPU_EncSetFrameBufCommand(struct nx_vpu_codec_inst -+ *pInst, uint32_t sramAddr, uint32_t sramSize); -+static int VPU_EncOneFrameCommand(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_run_frame_arg *runArg); -+static int VPU_EncChangeParameterCommand(struct nx_vpu_codec_inst -+ *pInst, struct vpu_enc_chg_para_arg *chgArg); -+static int VPU_EncGetHeaderCommand(struct nx_vpu_codec_inst *pInst, -+ unsigned int headerType, void **ptr, int *size); -+static int VPU_EncCloseCommand(struct nx_vpu_codec_inst *pInst, ++/* Decoder Functions */ ++static int FillBuffer(struct nx_vpu_codec_inst *pInst, unsigned char *stream, ++ int size); ++static int VPU_DecSeqInitCommand(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_seq_init_arg *pArg); ++static int VPU_DecSeqComplete(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_seq_init_arg *pArg); ++static int VPU_DecRegisterFrameBufCommand(struct nx_vpu_codec_inst ++ *pInst, struct vpu_dec_reg_frame_arg *pArg); ++static int VPU_DecStartOneFrameCommand(struct nx_vpu_codec_inst ++ *pInst, struct vpu_dec_frame_arg *pArg); ++static int VPU_DecGetOutputInfo(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_frame_arg *pArg); ++static int VPU_DecCloseCommand(struct nx_vpu_codec_inst *pInst, + void *vpu_event_present); + + +/*---------------------------------------------------------------------------- -+ * Encoder APIs ++ * Decoder APIs + */ + -+int NX_VpuEncOpen(struct vpu_open_arg *pOpenArg, void *devHandle, ++int NX_VpuDecOpen(struct vpu_open_arg *pOpenArg, void *devHandle, + struct nx_vpu_codec_inst **ppInst) +{ -+ struct vpu_enc_info *pEncInfo; ++ int val; ++ struct vpu_dec_info *pDecInfo; + struct nx_vpu_codec_inst *hInst = 0; + ++ FUNC_IN(); ++ + *ppInst = 0; + if (!NX_VpuIsInitialized()) + return VPU_RET_ERR_INIT; @@ -107108,469 +107016,687 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c b/drivers/media/p + if (!hInst) + return VPU_RET_ERR_INST; + -+ if (CODEC_STD_AVC == pOpenArg->codecStd) { -+ hInst->codecMode = AVC_ENC; -+ hInst->auxMode = 0; -+ } else if (CODEC_STD_MPEG4 == pOpenArg->codecStd) { -+ hInst->codecMode = MP4_ENC; ++ if (pOpenArg->codecStd == CODEC_STD_MPEG4) { ++ hInst->codecMode = MP4_DEC; ++ hInst->auxMode = MP4_AUX_MPEG4; ++ } else if (pOpenArg->codecStd == CODEC_STD_AVC) { ++ hInst->codecMode = AVC_DEC; ++ hInst->auxMode = AVC_AUX_AVC; ++ } else if (pOpenArg->codecStd == CODEC_STD_VC1) { ++ hInst->codecMode = VC1_DEC; ++ } else if (pOpenArg->codecStd == CODEC_STD_MPEG2) { ++ hInst->codecMode = MP2_DEC; + hInst->auxMode = 0; -+ } else if (CODEC_STD_H263 == pOpenArg->codecStd) { -+ hInst->codecMode = MP4_ENC; -+ hInst->auxMode = 1; -+ } else if (CODEC_STD_MJPG == pOpenArg->codecStd) { -+ hInst->codecMode = MJPG_ENC; ++ } else if (pOpenArg->codecStd == CODEC_STD_H263) { ++ hInst->codecMode = MP4_DEC; + hInst->auxMode = 0; ++ } else if (pOpenArg->codecStd == CODEC_STD_DIV3) { ++ hInst->codecMode = DV3_DEC; ++ hInst->auxMode = MP4_AUX_DIVX3; ++ } else if (pOpenArg->codecStd == CODEC_STD_RV) { ++ hInst->codecMode = RV_DEC; ++ } else if (pOpenArg->codecStd == CODEC_STD_AVS) { ++ hInst->codecMode = AVS_DEC; ++ } else if (pOpenArg->codecStd == CODEC_STD_MJPG) { ++ hInst->codecMode = MJPG_DEC; ++ } else if (pOpenArg->codecStd == CODEC_STD_THO) { ++ hInst->codecMode = VPX_DEC; ++ hInst->auxMode = VPX_AUX_THO; ++ } else if (pOpenArg->codecStd == CODEC_STD_VP3) { ++ hInst->codecMode = VPX_DEC; ++ hInst->auxMode = VPX_AUX_THO; ++ } else if (pOpenArg->codecStd == CODEC_STD_VP8) { ++ hInst->codecMode = VPX_DEC; ++ hInst->auxMode = VPX_AUX_VP8; + } else { -+ NX_ErrMsg(("NX_VpuEncOpen() failed!!!\n")); -+ NX_ErrMsg(("Cannot support codec standard(%d)\n", ++ NX_ErrMsg(("NX_VpuDecOpen() failed!!!\n")); ++ NX_ErrMsg(("Cannot support codec standard (%d)\n", + pOpenArg->codecStd)); + return VPU_RET_ERR_PARAM; + } + -+ NX_DrvMemset(&hInst->codecInfo, 0, sizeof(hInst->codecInfo)); -+ ++ /* Set Base Information */ + hInst->inUse = 1; + hInst->instIndex = pOpenArg->instIndex; + hInst->devHandle = devHandle; + + hInst->instBufPhyAddr = (uint64_t)pOpenArg->instanceBuf.phyAddr; ++ pDecInfo = &hInst->codecInfo.decInfo; + -+ pEncInfo = &hInst->codecInfo.encInfo; -+ pEncInfo->codecStd = pOpenArg->codecStd; ++ /* Clrear Instnace Information */ ++ NX_DrvMemset(&hInst->codecInfo, 0, sizeof(hInst->codecInfo)); ++ pDecInfo->codecStd = pOpenArg->codecStd; ++ pDecInfo->mp4Class = pOpenArg->mp4Class; + -+ VPU_EncDefaultParam(pEncInfo); ++ if (hInst->codecMode != MJPG_DEC) { ++ pDecInfo->streamRdPtrRegAddr = BIT_RD_PTR; ++ pDecInfo->streamWrPtrRegAddr = BIT_WR_PTR; ++ pDecInfo->frameDisplayFlagRegAddr = BIT_FRM_DIS_FLG; ++ } else { ++ pDecInfo->streamRdPtrRegAddr = MJPEG_BBC_RD_PTR_REG; ++ pDecInfo->streamWrPtrRegAddr = MJPEG_BBC_WR_PTR_REG; ++ pDecInfo->frameDisplayFlagRegAddr = 0; ++ } ++ ++ pDecInfo->strmBufPhyAddr = (uint64_t)pOpenArg->streamBuf.phyAddr; ++ pDecInfo->strmBufVirAddr = (unsigned long)pOpenArg->streamBuf.virAddr; ++ pDecInfo->strmBufSize = pOpenArg->streamBuf.size; ++ NX_DrvMemset((void *)(unsigned long)pDecInfo->strmBufVirAddr, 0, ++ pDecInfo->strmBufSize); ++ ++ /* Set Other Parameters */ ++ pDecInfo->frameDelay = -1; ++ pDecInfo->userDataEnable = 0; ++ pDecInfo->enableReordering = VPU_REORDER_ENABLE; ++ pDecInfo->vc1BframeDisplayValid = 0; ++ pDecInfo->avcErrorConcealMode = 0; ++ pDecInfo->enableMp4Deblock = 0; ++ ++ if (pDecInfo->codecStd == CODEC_STD_AVC || ++ pDecInfo->codecStd == CODEC_STD_MPEG2 ) { ++ pDecInfo->bitStreamMode = BS_MODE_PIC_END; ++ /*pDecInfo->bitStreamMode = BS_MODE_ROLLBACK; */ ++ } else if (pDecInfo->codecStd == CODEC_STD_H263 || ++ pDecInfo->codecStd == CODEC_STD_MPEG4) { ++ pDecInfo->bitStreamMode = BS_MODE_PIC_END; ++ } else { ++ pDecInfo->bitStreamMode = BS_MODE_ROLLBACK; ++ } ++ ++ pDecInfo->streamEndflag = 0;/* Frame Unit Operation */ ++ pDecInfo->bwbEnable = VPU_ENABLE_BWB; ++ pDecInfo->seqInitEscape = 0; ++ pDecInfo->streamEndian = VPU_STREAM_ENDIAN; ++ ++ NX_DrvMemset(hInst->paramVirAddr, 0, PARA_BUF_SIZE); ++ ++ VpuWriteReg(pDecInfo->streamWrPtrRegAddr, pDecInfo->strmBufPhyAddr); ++ VpuWriteReg(pDecInfo->streamRdPtrRegAddr, pDecInfo->strmBufPhyAddr); ++ ++ pDecInfo->readPos = pDecInfo->strmBufPhyAddr; ++ pDecInfo->writePos = pDecInfo->strmBufPhyAddr; ++ ++ if (hInst->codecMode != MJPG_DEC) { ++ val = VpuReadReg(BIT_BIT_STREAM_PARAM); ++ val &= ~(1 << 2); ++ /* clear stream end flag at start */ ++ VpuWriteReg(BIT_BIT_STREAM_PARAM, val); ++ pDecInfo->streamEndflag = val; ++ } else { ++ pDecInfo->streamEndflag = 0; ++ VpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, pDecInfo->strmBufPhyAddr); ++ VpuWriteReg(MJPEG_BBC_END_ADDR_REG, pDecInfo->strmBufPhyAddr + ++ pDecInfo->strmBufSize); ++ VpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, 0); ++ } + + *ppInst = hInst; ++ ++ NX_DbgMsg(INFO_MSG, ("===================================\n")); ++ NX_DbgMsg(INFO_MSG, (" VPU Open Information:\n")); ++ NX_DbgMsg(INFO_MSG, (" Instance Index : %d\n", hInst->instIndex)); ++ NX_DbgMsg(INFO_MSG, (" BitStream Mode : %d\n", ++ pDecInfo->bitStreamMode)); ++ NX_DbgMsg(INFO_MSG, (" Codec Standard : %d\n", hInst->codecMode)); ++ NX_DbgMsg(INFO_MSG, (" Codec AUX Mode : %d\n", hInst->auxMode)); ++ NX_DbgMsg(INFO_MSG, ("===================================\n")); ++ ++ FUNC_OUT(); + return VPU_RET_OK; +} + -+int NX_VpuEncClose(struct nx_vpu_codec_inst *pInst, void *vpu_event_present) ++int NX_VpuDecSetSeqInfo(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_seq_init_arg *pSeqArg) +{ + enum nx_vpu_ret ret; + -+ if (MJPG_ENC == pInst->codecMode) -+ return VPU_RET_OK; ++ FUNC_IN(); + -+ ret = VPU_EncCloseCommand(pInst, vpu_event_present); -+ if (ret != VPU_RET_OK) -+ NX_ErrMsg(("NX_VpuEncClose() failed.(%d)\n", ret)); ++ if (pInst->codecMode != MJPG_DEC) { ++ /* FillBuffer */ ++ if (0 > FillBuffer(pInst, ++ (unsigned char *)(unsigned long)pSeqArg->seqData, ++ pSeqArg->seqDataSize)) { ++ NX_ErrMsg(("FillBuffer Error!!!\n")); ++ return VPU_RET_ERROR; ++ } + -+ return ret; -+} ++#if 0 ++ if (pInfo->bitStreamMode != BS_MODE_PIC_END) { ++ int streamSize; + -+int NX_VpuEncSetSeqParam(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_seq_arg *pSeqArg) -+{ -+ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; ++ if (pInfo->writePos > pInfo->readPos) ++ streamSize = pInfo->writePos - pInfo->readPos; ++ else ++ streamSize = pInfo->strmBufSize - ++ (pInfo->readPos - pInfo->writePos); + -+ pEncInfo->srcWidth = pSeqArg->srcWidth; -+ pEncInfo->srcHeight = pSeqArg->srcHeight; -+ pEncInfo->encWidth = pSeqArg->srcWidth; -+ pEncInfo->encHeight = pSeqArg->srcHeight; -+ pEncInfo->gopSize = pSeqArg->gopSize; -+ pEncInfo->frameRateNum = pSeqArg->frameRateNum; -+ pEncInfo->frameRateDen = pSeqArg->frameRateDen; ++ if (streamSize < VPU_GBU_SIZE*2) ++ return VPU_RET_NEED_STREAM; ++ } ++#endif + -+ pEncInfo->rcEnable = (pSeqArg->bitrate) ? (1) : (0); -+ pEncInfo->bitRate = (pSeqArg->bitrate/1024)&0x7FFF; -+ pEncInfo->userQpMax = pSeqArg->maxQP; -+ pEncInfo->enableAutoSkip = !pSeqArg->disableSkip; -+ pEncInfo->initialDelay = pSeqArg->initialDelay; -+ pEncInfo->vbvBufSize = pSeqArg->vbvBufferSize; -+ pEncInfo->userGamma = pSeqArg->gammaFactor; -+ pEncInfo->frameQp = pSeqArg->initQP; ++ ret = VPU_DecSeqInitCommand(pInst, pSeqArg); ++ if (ret != VPU_RET_OK) ++ return ret; ++ ret = VPU_DecSeqComplete(pInst, pSeqArg); ++ } else { ++ ret = JPU_DecSetSeqInfo(pInst, pSeqArg); + -+ pEncInfo->MESearchRange = pSeqArg->searchRange; -+ pEncInfo->intraRefresh = pSeqArg->intraRefreshMbs; ++ /* Fill Data */ ++ if (0 > FillBuffer(pInst, ++ (unsigned char *)(unsigned long)pSeqArg->seqData, ++ pSeqArg->seqDataSize)) { ++ NX_ErrMsg(("FillBuffer Failed.\n")); ++ return VPU_RET_ERROR; ++ } ++ } + -+ pEncInfo->cbcrInterleave = pSeqArg->chromaInterleave; -+ pEncInfo->cbcrInterleaveRefFrame = pSeqArg->refChromaInterleave; ++ FUNC_OUT(); ++ return ret; ++} + -+ pEncInfo->rotateAngle = pSeqArg->rotAngle / 90; -+ pEncInfo->mirrorDirection = pSeqArg->mirDirection; ++int NX_VpuDecRegFrameBuf(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_reg_frame_arg *pFrmArg) ++{ ++ if (pInst->codecMode != MJPG_DEC) ++ return VPU_DecRegisterFrameBufCommand(pInst, pFrmArg); ++ else ++ return JPU_DecRegFrameBuf(pInst, pFrmArg); ++} + -+ pEncInfo->strmBufVirAddr = pSeqArg->strmBufVirAddr; -+ pEncInfo->strmBufPhyAddr = pSeqArg->strmBufPhyAddr; -+ pEncInfo->strmBufSize = pSeqArg->strmBufSize; ++int NX_VpuFillStreamBuffer(struct nx_vpu_codec_inst *pInst, ++ void *strmData, unsigned strmDataSize) ++{ ++ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; ++ enum nx_vpu_ret ret; + -+ pEncInfo->jpegQuality = pSeqArg->quality; ++ if (pInst->codecMode != MJPG_DEC) { ++ /* Fill Data */ ++ if (0 > FillBuffer(pInst, strmData, strmDataSize)) { ++ NX_ErrMsg(("FillBuffer Failed.\n")); ++ return VPU_RET_ERROR; ++ } + -+ if (pSeqArg->annexFlg) { -+ pEncInfo->enc_codec_para.h263EncParam.h263AnnexJEnable = 1; -+ pEncInfo->enc_codec_para.h263EncParam.h263AnnexTEnable = 1; ++ } else { ++ if (pInfo->headerSize == 0) { ++ ret = JPU_DecParseHeader(pInfo, strmData, strmDataSize); ++ if (ret < 0) { ++ NX_ErrMsg(("JpgHeader is failed(Error = %d)!\n", ret)); ++ return -1; ++ } ++ } ++ /* Fill Data */ ++ if (0 > FillBuffer(pInst, strmData, strmDataSize)) { ++ NX_ErrMsg(("FillBuffer Failed.\n")); ++ return VPU_RET_ERROR; ++ } + } ++ return VPU_RET_OK; ++} + -+ if (pSeqArg->enableAUDelimiter) -+ pEncInfo->enc_codec_para.avcEncParam.audEnable = 1; ++int NX_VpuDecRunFrame(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_frame_arg *pRunArg) ++{ ++ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; ++ enum nx_vpu_ret ret; + -+ NX_DbgMsg(INFO_MSG, ("NX_VpuEncSetSeqParam() information\n")); -+ NX_DbgMsg(INFO_MSG, ("Reloution : %d x %d\n", -+ pEncInfo->srcWidth, pEncInfo->srcHeight)); -+ NX_DbgMsg(INFO_MSG, ("Fps : %d/%d\n", -+ pEncInfo->frameRateNum, pEncInfo->frameRateDen)); -+ NX_DbgMsg(INFO_MSG, ("Target bitrate : %d kbps\n", pEncInfo->bitRate)); -+ NX_DbgMsg(INFO_MSG, ("GOP : %d\n", pEncInfo->gopSize)); -+ NX_DbgMsg(INFO_MSG, ("Max QP : %d\n", pEncInfo->userQpMax)); -+ NX_DbgMsg(INFO_MSG, ("SR : %d\n", pEncInfo->MESearchRange)); -+ NX_DbgMsg(INFO_MSG, ("Stream_buffer : 0x%llx, 0x%llx))\n", -+ pEncInfo->strmBufPhyAddr, pEncInfo->strmBufVirAddr)); + -+ if (CODEC_STD_MJPG == pEncInfo->codecStd) { -+ struct enc_jpeg_info *pJpgInfo = -+ &pEncInfo->enc_codec_para.jpgEncInfo; ++ if (pInst->codecMode != MJPG_DEC) { ++#if 0 ++ if (pInfo->bitStreamMode != BS_MODE_PIC_END) { ++ int streamSize; + -+ if (0 != pEncInfo->rotateAngle) { -+ pJpgInfo->rotationEnable = 1; -+ pJpgInfo->rotationAngle = pEncInfo->rotateAngle; -+ } ++ if (pInfo->writePos > pInfo->readPos) ++ streamSize = pInfo->writePos - pInfo->readPos; ++ else ++ streamSize = pInfo->strmBufSize - ++ (pInfo->readPos - pInfo->writePos); + -+ if (0 != pEncInfo->mirrorDirection) { -+ pJpgInfo->mirrorEnable = 1; -+ pJpgInfo->mirrorDirection = pEncInfo->mirrorDirection; ++ if (streamSize < VPU_GBU_SIZE*2) { ++ pRunArg->indexFrameDecoded = -1; ++ pRunArg->indexFrameDisplay = -1; ++ return VPU_RET_NEED_STREAM; ++ } + } ++#endif + -+ if (pSeqArg->quality == 0 || pSeqArg->quality < 0 || -+ pSeqArg->quality > 100) -+ pEncInfo->jpegQuality = 90; -+ else -+ pEncInfo->jpegQuality = pSeqArg->quality; -+ -+ pJpgInfo->format = pSeqArg->imgFormat; -+ pJpgInfo->picWidth = pEncInfo->srcWidth; -+ pJpgInfo->picHeight = pEncInfo->srcHeight; -+ -+ return VPU_RET_OK; ++ ret = VPU_DecStartOneFrameCommand(pInst, pRunArg); ++ if (ret == VPU_RET_OK) ++ ret = VPU_DecGetOutputInfo(pInst, pRunArg); ++ } else { ++ if (pInfo->validFlg > 0) { ++ ret = JPU_DecRunFrame(pInst, pRunArg); ++ pInfo->validFlg -= 1; ++ } else { ++ ret = -1; ++ } + } + -+ return VPU_EncSeqCommand(pInst); ++ return ret; +} + -+/* Frame Buffer Address Allocation */ -+int NX_VpuEncSetFrame(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_set_frame_arg *pFrmArg) ++int NX_VpuDecFlush(struct nx_vpu_codec_inst *pInst) +{ -+ int i; -+ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; ++ unsigned int val; ++ struct vpu_dec_info *pDecInfo = &pInst->codecInfo.decInfo; + -+ if (CODEC_STD_MJPG == pEncInfo->codecStd) -+ return VPU_RET_OK; ++ if (pInst->codecMode != MJPG_DEC) { ++ val = pDecInfo->frameDisplayFlag; ++ val &= ~pDecInfo->clearDisplayIndexes; ++ VpuWriteReg(pDecInfo->frameDisplayFlagRegAddr, val); ++ pDecInfo->clearDisplayIndexes = 0; ++ pDecInfo->writePos = pDecInfo->readPos; ++ VpuBitIssueCommand(pInst, DEC_BUF_FLUSH); + -+ pEncInfo->minFrameBuffers = pFrmArg->numFrameBuffer; -+ for (i = 0 ; i < pEncInfo->minFrameBuffers ; i++) -+ pEncInfo->frameBuffer[i] = pFrmArg->frameBuffer[i]; ++ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, ++ BIT_BUSY_FLAG)) ++ return VPU_RET_ERR_TIMEOUT; + -+ pEncInfo->subSampleAPhyAddr = pFrmArg->subSampleBuffer[0].phyAddr; -+ pEncInfo->subSampleBPhyAddr = pFrmArg->subSampleBuffer[1].phyAddr; ++ pDecInfo->frameDisplayFlag = VpuReadReg( ++ pDecInfo->frameDisplayFlagRegAddr); ++ pDecInfo->frameDisplayFlag = 0; ++ /* Clear End of Stream */ ++ pDecInfo->streamEndflag &= ~(1 << 2); ++ pDecInfo->readPos = pDecInfo->strmBufPhyAddr; ++ pDecInfo->writePos = pDecInfo->strmBufPhyAddr; ++ NX_DrvMemset((void *)(unsigned long)pDecInfo->strmBufVirAddr, ++ 0, pDecInfo->strmBufSize); ++ } else { ++ int i; + -+ return VPU_EncSetFrameBufCommand(pInst, pFrmArg->sramAddr, -+ pFrmArg->sramSize); ++ for (i = 0 ; i < pDecInfo->numFrameBuffer ; i++) ++ pDecInfo->frmBufferValid[i] = 0; ++ } ++ ++ return VPU_RET_OK; +} + -+int NX_VpuEncGetHeader(struct nx_vpu_codec_inst *pInst, -+ union vpu_enc_get_header_arg *pHeader) ++int NX_VpuDecClrDspFlag(struct nx_vpu_codec_inst *pInst, ++ unsigned indexFrameDisplay) +{ -+ enum nx_vpu_ret ret = VPU_RET_OK; -+ void *ptr; -+ int size; ++ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; + -+ if (AVC_ENC == pInst->codecMode) { -+ /* SPS */ -+ ret = VPU_EncGetHeaderCommand(pInst, SPS_RBSP, &ptr, &size); -+ if (ret != VPU_RET_OK) { -+ NX_ErrMsg(("NX_VpuEncGetHeader() SPS_RBSP Error!\n")); -+ goto GET_HEADER_EXIT; -+ } -+ NX_DrvMemcpy(pHeader->avcHeader.spsData, ptr, size); -+ pHeader->avcHeader.spsSize = size; -+ /* PPS */ -+ ret = VPU_EncGetHeaderCommand(pInst, PPS_RBSP, &ptr, &size); -+ if (ret != VPU_RET_OK) { -+ NX_ErrMsg(("NX_VpuEncGetHeader() PPS_RBSP Error!\n")); -+ goto GET_HEADER_EXIT; -+ } -+ NX_DrvMemcpy(pHeader->avcHeader.ppsData, ptr, size); -+ pHeader->avcHeader.ppsSize = size; -+ } else if (MP4_ENC == pInst->codecMode) { -+ ret = VPU_EncGetHeaderCommand(pInst, VOS_HEADER, &ptr, &size); -+ /* VOS */ -+ if (ret != VPU_RET_OK) { -+ NX_ErrMsg(("NX_VpuEncGetHeader() VOS_HEADER Error!\n")); -+ goto GET_HEADER_EXIT; -+ } -+ NX_DrvMemcpy(pHeader->mp4Header.vosData, ptr, size); -+ pHeader->mp4Header.vosSize = size; -+ /* VOL */ -+ ret = VPU_EncGetHeaderCommand(pInst, VOL_HEADER, &ptr, &size); -+ if (ret != VPU_RET_OK) { -+ NX_ErrMsg(("NX_VpuEncGetHeader() VOL_HEADER Error!\n")); -+ goto GET_HEADER_EXIT; -+ } -+ NX_DrvMemcpy(pHeader->mp4Header.volData, ptr, size); -+ pHeader->mp4Header.volSize = size; -+ } ++ if (pInst->codecMode != MJPG_DEC) ++ pInfo->clearDisplayIndexes |= 1 << indexFrameDisplay; ++ else ++ pInfo->frmBufferValid[indexFrameDisplay] = 0; + -+GET_HEADER_EXIT: -+ return ret; ++ return VPU_RET_OK; +} + -+int NX_VpuEncRunFrame(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_run_frame_arg *pRunArg) ++int NX_VpuDecClose(struct nx_vpu_codec_inst *pInst, ++ void *vpu_event_present) +{ -+ if (pInst->codecMode != MJPG_ENC) -+ return VPU_EncOneFrameCommand(pInst, pRunArg); -+ else -+ return JPU_EncRunFrame(pInst, pRunArg); ++ enum nx_vpu_ret ret; ++ ++ if (pInst->codecMode == MJPG_DEC) ++ return VPU_RET_OK; ++ ++ ret = VPU_DecCloseCommand(pInst, vpu_event_present); ++ if (ret != VPU_RET_OK) ++ NX_ErrMsg(("NX_VpuDecClose() failed.(%d)\n", ret)); ++ ++ return ret; +} + -+int NX_VpuEncChgParam(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_chg_para_arg *pChgArg) ++ ++/*---------------------------------------------------------------------------- ++ * Decoder Specific Static Functions ++ */ ++ ++static int FillBuffer(struct nx_vpu_codec_inst *pInst, unsigned char *stream, ++ int size) +{ -+ if (pInst->codecMode != MJPG_ENC) -+ return VPU_EncChangeParameterCommand(pInst, pChgArg); -+ else ++ uint32_t vWriteOffset, vReadOffset;/* Virtual Read/Write Position */ ++ int32_t bufSize; ++ struct vpu_dec_info *pDecInfo = &pInst->codecInfo.decInfo; ++ ++ /* EOS */ ++ if (size == 0) ++ return 0; ++ if (!stream || size < 0) ++ return -1; ++ ++ if (pDecInfo->codecStd == CODEC_STD_MJPG) { ++ stream += pDecInfo->headerSize; ++ size -= pDecInfo->headerSize; ++ ++ pDecInfo->writePos = pDecInfo->strmBufPhyAddr; ++ pDecInfo->readPos = pDecInfo->strmBufPhyAddr; ++ ++ pDecInfo->validFlg += 1; ++ } ++ ++ vWriteOffset = pDecInfo->writePos - pDecInfo->strmBufPhyAddr; ++ vReadOffset = pDecInfo->readPos - pDecInfo->strmBufPhyAddr; ++ bufSize = pDecInfo->strmBufSize; ++ ++ if (bufSize < vWriteOffset || bufSize < vReadOffset) { ++ NX_ErrMsg(("%s, stream_buffer(Addr=x0%08x, size=%d)\n", ++ __func__, (uint32_t)pDecInfo->strmBufVirAddr, ++ pDecInfo->strmBufSize)); ++ NX_ErrMsg(("InBuffer(Addr=%p, size=%d)", stream, size)); ++ NX_ErrMsg(("vWriteOffset = %d, vReadOffset = %d\n", ++ vWriteOffset, vReadOffset)); + return -1; ++ } ++ ++ if ((bufSize - vWriteOffset) > size) { ++ /* Just Memory Copy */ ++#if 1 ++ NX_DrvMemcpy((void *)(unsigned long)(pDecInfo->strmBufVirAddr + ++ vWriteOffset), stream, size); ++#else ++ if (copy_from_user((uint8_t *)(pDecInfo->strmBufVirAddr + ++ vWriteOffset), stream, size)) ++ return -1; ++#endif ++ vWriteOffset += size; ++ } else { ++ /* Memory Copy */ ++ int remain = bufSize - vWriteOffset; ++#if 1 ++ NX_DrvMemcpy((void *)(unsigned long)(pDecInfo->strmBufVirAddr + ++ vWriteOffset), stream, remain); ++ NX_DrvMemcpy((void *)(unsigned long)(pDecInfo->strmBufVirAddr), ++ stream + remain, size-remain); ++#else ++ if (copy_from_user( ++ (void *)(unsigned long)(pDecInfo->strmBufVirAddr + ++ vWriteOffset), stream, remain)) ++ return -1; ++ if (copy_from_user( ++ (void *)(unsigned long)(pDecInfo->strmBufVirAddr), ++ stream+remain, size-remain)) ++ return -1; ++#endif ++ vWriteOffset = size-remain; ++ } ++ ++ pDecInfo->writePos = vWriteOffset + pDecInfo->strmBufPhyAddr; ++ return 0; +} + ++static int VPU_DecSeqComplete(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_seq_init_arg *pArg) ++{ ++ unsigned int val, val2; ++ int errReason; ++ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; ++ ++ if (pInfo->bitStreamMode == BS_MODE_INTERRUPT && pInfo->seqInitEscape) { ++ pInfo->streamEndflag &= ~(3<<3); ++ VpuWriteReg(BIT_BIT_STREAM_PARAM, pInfo->streamEndflag); ++ pInfo->seqInitEscape = 0; ++ } ++ ++ pInfo->frameDisplayFlag = VpuReadReg(pInfo->frameDisplayFlagRegAddr); ++ pInfo->readPos = VpuReadReg(pInfo->streamRdPtrRegAddr); ++ pInfo->streamEndflag = VpuReadReg(BIT_BIT_STREAM_PARAM); ++ ++ errReason = 0; ++ val = VpuReadReg(RET_DEC_SEQ_SUCCESS); ++ if (val & (1<<31)) ++ return VPU_RET_ERR_MEM_ACCESS; ++ ++ if (pInfo->bitStreamMode == BS_MODE_PIC_END || ++ pInfo->bitStreamMode == BS_MODE_ROLLBACK) { ++ if (val & (1<<4)) { ++ errReason = VpuReadReg(RET_DEC_SEQ_SEQ_ERR_REASON); ++ NX_ErrMsg(("VPU decoder error: status=0x%x reason=0x%x\n", val, ++ errReason)); ++ return VPU_RET_ERROR; ++ } ++ } ++ ++ if (val == 0) { ++ errReason = VpuReadReg(RET_DEC_SEQ_SEQ_ERR_REASON); ++ NX_ErrMsg(("VPU decoder error: status=0 reason=0x%x\n", errReason)); ++ return VPU_RET_ERROR; ++ } + -+/*--------------------------------------------------------------------------- -+ * Encoder Specific Static Functions -+ */ ++ val = VpuReadReg(RET_DEC_SEQ_SRC_SIZE); ++ pArg->outWidth = ((val >> 16) & 0xffff); ++ pArg->outHeight = (val & 0xffff); + -+static void VPU_EncDefaultParam(struct vpu_enc_info *pEncInfo) -+{ -+ /* Set Default Frame Rate */ -+ pEncInfo->frameRateNum = 30; -+ pEncInfo->frameRateDen = 1; ++ pArg->frameRateNum = VpuReadReg(RET_DEC_SEQ_FRATE_NR); ++ pArg->frameRateDen = VpuReadReg(RET_DEC_SEQ_FRATE_DR); + -+ /* Set Slice Mode */ -+ pEncInfo->sliceMode = 0; /* one slice per picture */ -+ pEncInfo->sliceSizeMode = 0; -+ pEncInfo->sliceSize = 0; ++ if (pInst->codecMode == AVC_DEC && pArg->frameRateDen > 0) ++ pArg->frameRateDen *= 2; + -+ /* Set GOP Size */ -+ pEncInfo->gopSize = 30; ++ if (pInst->codecMode == MP4_DEC) { ++ val = VpuReadReg(RET_DEC_SEQ_INFO); ++ pArg->mp4ShortHeader = (val >> 2) & 1; ++ pArg->mp4PartitionEnable = val & 1; ++ pArg->mp4ReversibleVlcEnable = ++ pArg->mp4PartitionEnable ? ++ ((val >> 1) & 1) : 0; ++ pArg->h263AnnexJEnable = (val >> 3) & 1; ++ } else if (pInst->codecMode == VPX_DEC && pInst->auxMode == ++ VPX_AUX_VP8) { ++ /* h_scale[31:30] v_scale[29:28] pic_width[27:14] ++ * pic_height[13:0] */ ++ val = VpuReadReg(RET_DEC_SEQ_VP8_SCALE_INFO); ++ pArg->vp8HScaleFactor = (val >> 30) & 0x03; ++ pArg->vp8VScaleFactor = (val >> 28) & 0x03; ++ pArg->vp8ScaleWidth = (val >> 14) & 0x3FFF; ++ pArg->vp8ScaleHeight = (val >> 0) & 0x3FFF; ++ } + -+ /* Rate Control Related */ -+ pEncInfo->rcEnable = 0; -+ pEncInfo->intraRefresh = 0; /* Disalbe Intra Refresh */ -+ pEncInfo->rcIntraQp = -1; /* Disable */ ++ pArg->minFrameBufCnt = VpuReadReg(RET_DEC_SEQ_FRAME_NEED); ++ pArg->frameBufDelay = VpuReadReg(RET_DEC_SEQ_FRAME_DELAY); + -+ pEncInfo->bwbEnable = VPU_ENABLE_BWB; -+ pEncInfo->cbcrInterleave = CBCR_INTERLEAVE; -+ pEncInfo->cbcrInterleaveRefFrame = ENC_FRAME_BUF_CBCR_INTERLEAVE; -+ pEncInfo->frameEndian = VPU_FRAME_ENDIAN; ++ if (pInst->codecMode == AVC_DEC || pInst->codecMode == MP2_DEC) { ++ val = VpuReadReg(RET_DEC_SEQ_CROP_LEFT_RIGHT); ++ val2 = VpuReadReg(RET_DEC_SEQ_CROP_TOP_BOTTOM); ++ if (val == 0 && val2 == 0) { ++ pArg->cropLeft = 0; ++ pArg->cropRight = pArg->outWidth; ++ pArg->cropTop = 0; ++ pArg->cropBottom = pArg->outHeight; ++ } else { ++ pArg->cropLeft = ((val>>16) & 0xFFFF); ++ pArg->cropRight = pArg->outWidth - ((val & 0xFFFF)); ++ pArg->cropTop = ((val2>>16) & 0xFFFF); ++ pArg->cropBottom = pArg->outHeight - ((val2 & 0xFFFF)); ++ } + -+ pEncInfo->rcIntervalMode = 0; /* Frame Mode */ -+ pEncInfo->rcIntraCostWeigth = 400; -+ pEncInfo->enableAutoSkip = 0; -+ pEncInfo->initialDelay = 0; -+ pEncInfo->vbvBufSize = 0; ++ val = (pArg->outWidth * pArg->outHeight * 3 / 2) / 1024; ++ pArg->numSliceSize = val / 4; ++ pArg->worstSliceSize = val / 2; ++ } else { ++ pArg->cropLeft = 0; ++ pArg->cropRight = pArg->outWidth; ++ pArg->cropTop = 0; ++ pArg->cropBottom = pArg->outHeight; ++ } + -+ /* (0*32768 < gamma < 1*32768) */ -+ pEncInfo->userGamma = (unsigned int)(0.75*32768); ++ val = VpuReadReg(RET_DEC_SEQ_HEADER_REPORT); ++ pArg->profile = (val >> 0) & 0xFF; ++ pArg->level = (val >> 8) & 0xFF; ++ pArg->interlace = (val >> 16) & 0x01; ++ pArg->direct8x8Flag = (val >> 17) & 0x01; ++ pArg->vc1Psf = (val >> 18) & 0x01; ++ pArg->constraint_set_flag[0] = (val >> 19) & 0x01; ++ pArg->constraint_set_flag[1] = (val >> 20) & 0x01; ++ pArg->constraint_set_flag[2] = (val >> 21) & 0x01; ++ pArg->constraint_set_flag[3] = (val >> 22) & 0x01; ++ pArg->avcIsExtSAR = (val >> 25) & 0x01; ++ pArg->maxNumRefFrmFlag = (val >> 31) & 0x01; + -+ if (CODEC_STD_AVC == pEncInfo->codecStd) { -+ struct enc_avc_param *pAvcParam = -+ &pEncInfo->enc_codec_para.avcEncParam; ++ pArg->aspectRateInfo = VpuReadReg(RET_DEC_SEQ_ASPECT); + -+ pAvcParam->chromaQpOffset = 0; -+ pAvcParam->constrainedIntraPredFlag = 0; -+ pAvcParam->disableDeblk = 0; -+ pAvcParam->deblkFilterOffsetAlpha = 0; -+ pAvcParam->audEnable = 0; ++ val = VpuReadReg(RET_DEC_SEQ_BIT_RATE); ++ pArg->bitrate = val; + -+ pEncInfo->userQpMax = 51; -+ } else if (CODEC_STD_MPEG4 == pEncInfo->codecStd) { -+ struct enc_mp4_param *pMp4Param = -+ &pEncInfo->enc_codec_para.mp4EncParam; -+ pMp4Param->mp4DataPartitionEnable = 0; -+ pMp4Param->mp4ReversibleVlcEnable = 0; -+ pMp4Param->mp4IntraDcVlcThr = 0; -+ pMp4Param->mp4HecEnable = 0; -+ pMp4Param->mp4Verid = 2; ++ if (pInst->codecMode == AVC_DEC) { ++ val = VpuReadReg(RET_DEC_SEQ_VUI_INFO); ++ pArg->vui_info.fixedFrameRateFlag = val & 1; ++ pArg->vui_info.timingInfoPresent = (val>>1) & 0x01; ++ pArg->vui_info.chromaLocBotField = (val>>2) & 0x07; ++ pArg->vui_info.chromaLocTopField = (val>>5) & 0x07; ++ pArg->vui_info.chromaLocInfoPresent = (val>>8) & 0x01; ++ pArg->vui_info.colorPrimaries = (val>>16) & 0xff; ++ pArg->vui_info.colorDescPresent = (val>>24) & 0x01; ++ pArg->vui_info.isExtSAR = (val>>25) & 0x01; ++ pArg->vui_info.vidFullRange = (val>>26) & 0x01; ++ pArg->vui_info.vidFormat = (val>>27) & 0x07; ++ pArg->vui_info.vidSigTypePresent = (val>>30) & 0x01; ++ pArg->vui_info.vuiParamPresent = (val>>31) & 0x01; + -+ pEncInfo->userQpMax = 31; -+ } else if (CODEC_STD_H263 == pEncInfo->codecStd) { -+ struct enc_h263_param *pH263Param = -+ &pEncInfo->enc_codec_para.h263EncParam; -+ pH263Param->h263AnnexIEnable = 0; -+ pH263Param->h263AnnexJEnable = 0; -+ pH263Param->h263AnnexKEnable = 0; -+ pH263Param->h263AnnexTEnable = 0; ++ val = VpuReadReg(RET_DEC_SEQ_VUI_PIC_STRUCT); ++ pArg->vui_info.vuiPicStructPresent = (val & 0x1); ++ pArg->vui_info.vuiPicStruct = (val>>1); ++ } + -+ pEncInfo->userQpMax = 31; -+ } else if (CODEC_STD_MJPG == pEncInfo->codecStd) { -+ struct enc_jpeg_info *pJpgInfo = -+ &pEncInfo->enc_codec_para.jpgEncInfo; -+ pJpgInfo->format = IMG_FORMAT_420; -+ pJpgInfo->frameIdx = 0; -+ pJpgInfo->rstIntval = 60; ++ if (pInst->codecMode == MP2_DEC) { ++ /* seq_ext info */ ++ val = VpuReadReg(RET_DEC_SEQ_EXT_INFO); ++ pArg->mp2LowDelay = val & 1; ++ pArg->mp2DispVerSize = (val>>1) & 0x3fff; ++ pArg->mp2DispHorSize = (val>>15) & 0x3fff; + } + -+ /* Motion Estimation */ -+ pEncInfo->MEUseZeroPmv = 0; -+ pEncInfo->MESearchRange = 1; -+ pEncInfo->MEBlockMode = 0; /* Use All Macro Block Type */ -+} ++ pInfo->writePos = VpuReadReg(pInfo->streamWrPtrRegAddr); ++ pInfo->readPos = VpuReadReg(pInfo->streamRdPtrRegAddr); + -+static int VPU_EncSeqCommand(struct nx_vpu_codec_inst *pInst) -+{ -+ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; -+ unsigned int tmpData; ++ pArg->strmWritePos = pInfo->writePos - pInfo->strmBufPhyAddr; ++ pArg->strmReadPos = pInfo->readPos - pInfo->strmBufPhyAddr; + -+ /* Write Bitstream Buffer Information */ -+ VpuWriteReg(CMD_ENC_SEQ_BB_START, pEncInfo->strmBufPhyAddr); -+ VpuWriteReg(CMD_ENC_SEQ_BB_SIZE, pEncInfo->strmBufSize / 1024); ++ pInfo->width = pArg->outWidth; ++ pInfo->height = pArg->outHeight; + -+ /* Set Source Image Information */ -+ if (90 == pEncInfo->rotateAngle || 270 == pEncInfo->rotateAngle) -+ tmpData = (pEncInfo->srcHeight << 16) | pEncInfo->srcWidth; -+ else -+ tmpData = (pEncInfo->srcWidth << 16) | pEncInfo->srcHeight; ++ pInst->isInitialized = 1; + -+ VpuWriteReg(CMD_ENC_SEQ_SRC_SIZE, tmpData); -+ VpuWriteReg(CMD_ENC_SEQ_SRC_F_RATE, (pEncInfo->frameRateNum) | -+ ((pEncInfo->frameRateDen-1) << 16)); ++ return VPU_RET_OK; ++} + -+ if (pEncInfo->codecStd == CODEC_STD_MPEG4) { -+ struct enc_mp4_param *pMp4Param = -+ &pEncInfo->enc_codec_para.mp4EncParam; -+ VpuWriteReg(CMD_ENC_SEQ_COD_STD, 3); -+ tmpData = pMp4Param->mp4IntraDcVlcThr << 2 | -+ pMp4Param->mp4ReversibleVlcEnable << 1 | -+ pMp4Param->mp4DataPartitionEnable; -+ tmpData |= ((pMp4Param->mp4HecEnable > 0) ? 1:0)<<5; -+ tmpData |= ((pMp4Param->mp4Verid == 2) ? 0:1) << 6; -+ VpuWriteReg(CMD_ENC_SEQ_MP4_PARA, tmpData); -+ } else if (pEncInfo->codecStd == CODEC_STD_H263) { -+ struct enc_h263_param *pH263Param = -+ &pEncInfo->enc_codec_para.h263EncParam; ++static int VPU_DecSeqInitCommand(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_seq_init_arg *pArg) ++{ ++ unsigned int val, reason; ++ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; + -+ VpuWriteReg(CMD_ENC_SEQ_COD_STD, 11); -+ tmpData = pH263Param->h263AnnexIEnable << 3 | -+ pH263Param->h263AnnexJEnable << 2 | -+ pH263Param->h263AnnexKEnable << 1| -+ pH263Param->h263AnnexTEnable; -+ VpuWriteReg(CMD_ENC_SEQ_263_PARA, tmpData); -+ } else if (pEncInfo->codecStd == CODEC_STD_AVC) { -+ struct enc_avc_param *pAvcParam = -+ &pEncInfo->enc_codec_para.avcEncParam; -+ VpuWriteReg(CMD_ENC_SEQ_COD_STD, 0x0); -+ tmpData = (pAvcParam->deblkFilterOffsetBeta & 15) << 12 -+ | (pAvcParam->deblkFilterOffsetAlpha & 15) << 8 -+ | pAvcParam->disableDeblk << 6 -+ | pAvcParam->constrainedIntraPredFlag << 5 -+ | (pAvcParam->chromaQpOffset & 31); -+ VpuWriteReg(CMD_ENC_SEQ_264_PARA, tmpData); ++ if (pArg->disableOutReorder) { ++ NX_DbgMsg(INFO_MSG, ("Disable Out Reordering!!!\n")); ++ pInfo->low_delay_info.lowDelayEn = 1; ++ pInfo->low_delay_info.numRows = 0; + } + -+ /* Slice Mode */ -+ tmpData = pEncInfo->sliceSize << 2 | pEncInfo->sliceSizeMode << 1 -+ | pEncInfo->sliceMode; -+ VpuWriteReg(CMD_ENC_SEQ_SLICE_MODE, tmpData); -+ -+ /* Write GOP Size */ -+ if (pEncInfo->rcEnable) -+ VpuWriteReg(CMD_ENC_SEQ_GOP_NUM, pEncInfo->gopSize); -+ else -+ VpuWriteReg(CMD_ENC_SEQ_GOP_NUM, 0); -+ -+ /* Rate Control */ -+ if (pEncInfo->rcEnable) { -+ tmpData = (!pEncInfo->enableAutoSkip) << 31 | -+ pEncInfo->initialDelay << 16 | pEncInfo->bitRate<<1 | 1; -+ VpuWriteReg(CMD_ENC_SEQ_RC_PARA, tmpData); -+ } else { -+ VpuWriteReg(CMD_ENC_SEQ_RC_PARA, 0); ++ if (pInfo->needMoreFrame) { ++ pInfo->needMoreFrame = 0; ++ VpuWriteReg(pInfo->streamWrPtrRegAddr, pInfo->writePos); ++ NX_DbgMsg(INFO_MSG, ("Need More Buffer!!!!!\n")); ++ goto WAIT_INTERRUPT; + } + -+ VpuWriteReg(CMD_ENC_SEQ_RC_BUF_SIZE, pEncInfo->vbvBufSize); -+ VpuWriteReg(CMD_ENC_SEQ_INTRA_REFRESH, pEncInfo->intraRefresh); ++ pInfo->enableMp4Deblock = pArg->enablePostFilter; + -+ if (pEncInfo->rcIntraQp >= 0) { -+ tmpData = (1 << 5); -+ VpuWriteReg(CMD_ENC_SEQ_INTRA_QP, pEncInfo->rcIntraQp); -+ } else { -+ tmpData = 0; -+ VpuWriteReg(CMD_ENC_SEQ_INTRA_QP, (unsigned int)-1); -+ } ++ VpuWriteReg(CMD_DEC_SEQ_BB_START, pInfo->strmBufPhyAddr); ++ VpuWriteReg(CMD_DEC_SEQ_BB_SIZE, pInfo->strmBufSize / 1024); + -+ if (pEncInfo->codecStd == CODEC_STD_AVC) -+ tmpData |= (pEncInfo->enc_codec_para.avcEncParam.audEnable<<2); ++#if (DBG_REGISTER) ++ { ++ int i; + -+ if (pEncInfo->userQpMax >= 0) { -+ tmpData |= (1<<6); -+ VpuWriteReg(CMD_ENC_SEQ_RC_QP_MAX, pEncInfo->userQpMax); -+ } else { -+ VpuWriteReg(CMD_ENC_SEQ_RC_QP_MAX, 0); ++ VpuWriteReg(BIT_BIT_STREAM_PARAM, 0); ++ ++ /* Clear Stream end flag */ ++ i = (int)VpuReadReg(BIT_BIT_STREAM_PARAM); ++ if (i & (1 << (pInst->instIndex + 2))) ++ i -= 1 << (pInst->instIndex + 2); ++ VpuWriteReg(BIT_BIT_STREAM_PARAM, i); + } ++#endif + -+ if (pEncInfo->userGamma >= 0) { -+ tmpData |= (1<<7); -+ VpuWriteReg(CMD_ENC_SEQ_RC_GAMMA, pEncInfo->userGamma); ++ if (pArg->enableUserData) { ++ pInfo->userDataBufPhyAddr = ++ (uint64_t)pArg->userDataBuffer.phyAddr; ++ pInfo->userDataBufVirAddr = ++ (unsigned long)pArg->userDataBuffer.virAddr; ++ pInfo->userDataBufSize = pArg->userDataBuffer.size; ++ pInfo->userDataEnable = 1; ++ pInfo->userDataReportMode = 1; ++ ++ val = 0; ++ val |= (pInfo->userDataReportMode << 10); ++ /* val |= (pInfo->userDataEnable << 5); */ ++ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_OPTION, val); ++ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_BASE_ADDR, ++ pInfo->userDataBufPhyAddr); ++ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_BUF_SIZE, ++ pInfo->userDataBufSize); + } else { -+ VpuWriteReg(CMD_ENC_SEQ_RC_GAMMA, 0); ++ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_OPTION, 0); ++ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_BASE_ADDR, 0); ++ VpuWriteReg(CMD_DEC_SEQ_USER_DATA_BUF_SIZE, 0); + } ++ val = 0; + -+ VpuWriteReg(CMD_ENC_SEQ_OPTION, tmpData); ++ if (!pInfo->low_delay_info.lowDelayEn) ++ val |= (pInfo->enableReordering<<1) & 0x2; + -+ VpuWriteReg(CMD_ENC_SEQ_RC_INTERVAL_MODE, (pEncInfo->mbInterval<<2) -+ | pEncInfo->rcIntervalMode); -+ VpuWriteReg(CMD_ENC_SEQ_INTRA_WEIGHT, pEncInfo->rcIntraCostWeigth); -+ VpuWriteReg(CMD_ENC_SEQ_ME_OPTION, (pEncInfo->MEBlockMode << 3) -+ | (pEncInfo->MEUseZeroPmv << 2) | pEncInfo->MESearchRange); ++ val |= (pInfo->enableMp4Deblock & 0x1); + -+ VpuWriteReg(BIT_WR_PTR, pEncInfo->strmBufPhyAddr); -+ VpuWriteReg(BIT_RD_PTR, pEncInfo->strmBufPhyAddr); ++ /*Enable error conceal on missing reference in h.264/AVC */ ++ val |= (pInfo->avcErrorConcealMode << 2); + -+ tmpData = 0; -+ tmpData |= (pEncInfo->bwbEnable<<12)|(pEncInfo->cbcrInterleave<<2); -+ tmpData |= pEncInfo->frameEndian; -+ VpuWriteReg(BIT_FRAME_MEM_CTRL, tmpData); ++ VpuWriteReg(CMD_DEC_SEQ_OPTION, val); + -+ /* Ring Buffer Disable */ -+ if (pEncInfo->ringBufferEnable == 0) { -+ /* Line Buffer Interrupt Enable */ -+ tmpData = (0x1<<6); -+ /* The value of 1 means that bitstream buffer is reset at every -+ picture encoding command. */ -+ tmpData |= (0x1<<5); -+ /* Enables dynamic picture stream buffer allocation in encoder -+ operations. */ -+ tmpData |= (0x1<<4); -+ tmpData |= VPU_STREAM_ENDIAN; -+ } else { -+ /* Ring Buffer Enabled */ -+ tmpData = (0x1<<3); -+ tmpData |= VPU_STREAM_ENDIAN; ++ switch (pInst->codecMode) { ++ case VC1_DEC: ++ /* VpuWriteReg(CMD_DEC_SEQ_VC1_STREAM_FMT, 1); ++ VpuWriteReg(CMD_DEC_SEQ_VC1_STREAM_FMT, 2); */ ++ VpuWriteReg(CMD_DEC_SEQ_VC1_STREAM_FMT, (0 << 3) & 0x08); ++ break; ++ case MP4_DEC: ++ VpuWriteReg(CMD_DEC_SEQ_MP4_ASP_CLASS, ++ (VPU_GMC_PROCESS_METHOD<<3) | pInfo->mp4Class); ++ break; ++ case AVC_DEC: ++ VpuWriteReg(CMD_DEC_SEQ_X264_MV_EN, VPU_AVC_X264_SUPPORT); ++ break; + } + -+ VpuWriteReg(BIT_BIT_STREAM_CTRL, tmpData); ++ if (pInst->codecMode == AVC_DEC) ++ VpuWriteReg(CMD_DEC_SEQ_SPP_CHUNK_SIZE, VPU_GBU_SIZE); + -+#if (DBG_REGISTER) -+ { -+ int reg; ++ VpuWriteReg(pInfo->streamWrPtrRegAddr, pInfo->writePos); ++ VpuWriteReg(pInfo->streamRdPtrRegAddr, pInfo->readPos); + -+ NX_DbgMsg(DBG_REGISTER, ("[SEQ_INIT_Reg]\n")); -+ for (reg = 0x0 ; reg < 0x200 ; reg += 16) { -+ NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", -+ reg, VpuReadReg(BIT_BASE + reg), -+ VpuReadReg(BIT_BASE + reg + 4), -+ VpuReadReg(BIT_BASE + reg + 8), -+ VpuReadReg(BIT_BASE + reg + 12))); -+ } ++ /* Clear Stream Flag */ ++ pInfo->streamEndflag &= ~(1<<2); /* Clear End of Stream */ ++ pInfo->streamEndflag &= ~(3<<3); /* Clear Bitstream Mode */ ++ if (pInfo->bitStreamMode == BS_MODE_ROLLBACK) /*rollback mode */ ++ pInfo->streamEndflag |= (1<<3); ++ else if (pInfo->bitStreamMode == BS_MODE_PIC_END) ++ pInfo->streamEndflag |= (2<<3); ++ else { /* Interrupt Mode */ ++ if (pInfo->seqInitEscape) ++ pInfo->streamEndflag |= (2<<3); + } -+#endif + ++ VpuWriteReg(BIT_BIT_STREAM_PARAM, pInfo->streamEndflag); ++ VpuWriteReg(BIT_BIT_STREAM_CTRL, pInfo->streamEndian); + -+ VpuBitIssueCommand(pInst, SEQ_INIT); ++ val = 0; ++ val |= (pInfo->bwbEnable<<12); ++ val |= (pInfo->cbcrInterleave<<2); ++ VpuWriteReg(BIT_FRAME_MEM_CTRL, val); ++ ++ if (pInst->codecMode != MJPG_DEC) ++ VpuWriteReg(pInfo->frameDisplayFlagRegAddr, 0); + +#if (DBG_REGISTER) + { + int reg; + -+ NX_DbgMsg(DBG_REGISTER, ("[SEQ_INIT_Reg]\n")); -+ for (reg = 0x0 ; reg < 0x200 ; reg += 16) { ++ NX_DbgMsg(DBG_REGISTER, ("[DEC_SEQ_INIT]\n")); ++ NX_DbgMsg(DBG_REGISTER, ("[Strm_CTRL : 0x10C]%x\n", ++ VpuReadReg(BIT_BIT_STREAM_CTRL))); ++ for (reg = 0x180 ; reg < 0x200 ; reg += 16) { + NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", + reg, VpuReadReg(BIT_BASE + reg), + VpuReadReg(BIT_BASE + reg + 4), @@ -107580,135 +107706,133 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c b/drivers/media/p + } +#endif + -+ if (!VPU_WaitBitInterrupt(pInst->devHandle, VPU_DEC_TIMEOUT)) { -+ NX_ErrMsg(("VPU_EncSeqCommand() Failed. Timeout(%d)\n", ++ VpuBitIssueCommand(pInst, SEQ_INIT); ++ ++WAIT_INTERRUPT: ++ reason = VPU_WaitBitInterrupt(pInst->devHandle, VPU_DEC_TIMEOUT); ++ if (!reason) { ++ NX_ErrMsg(("VPU_DecSeqInitCommand() Failed. Timeout(%d)\n", + VPU_BUSY_CHECK_TIMEOUT)); ++ NX_ErrMsg(("WritePos = 0x%.8x, ReadPos = 0x%.8x\n", ++ VpuReadReg(pInfo->streamWrPtrRegAddr), ++ VpuReadReg(pInfo->streamRdPtrRegAddr))); + return VPU_RET_ERR_TIMEOUT; + } + -+ /* Get Encoder Frame Buffer Information */ -+ if (VpuReadReg(RET_ENC_SEQ_ENC_SUCCESS) & (1<<31)) -+ return VPU_RET_ERR_MEM_ACCESS; -+ -+ if (VpuReadReg(RET_ENC_SEQ_ENC_SUCCESS) == 0) -+ return VPU_RET_ERR_INIT; -+ -+ if (pInst->codecMode == MJPG_ENC) -+ pEncInfo->minFrameBuffers = 0; -+ else -+ /* reconstructed frame + reference frame + subsample */ -+ pEncInfo->minFrameBuffers = 2; -+ -+ pEncInfo->strmWritePrt = VpuReadReg(BIT_WR_PTR); -+ pEncInfo->strmEndFlag = VpuReadReg(BIT_BIT_STREAM_PARAM); -+ -+ NX_DbgMsg(INFO_MSG, ("VPU_EncSeqCommand() Success.\n")); -+ NX_DbgMsg(INFO_MSG, ("Writer Ptr = 0x%08x, Stream End Flag = %d\n", -+ pEncInfo->strmWritePrt, pEncInfo->strmEndFlag)); -+ -+ pInst->isInitialized = 1; -+ return VPU_RET_OK; ++ if (reason & (1<needMoreFrame = 1; ++ return VPU_RET_NEED_STREAM; ++ } else { ++ return VPU_RET_ERROR; ++ } +} + -+static int VPU_EncSetFrameBufCommand(struct nx_vpu_codec_inst *pInst, -+ uint32_t sramAddr, uint32_t sramSize) ++static void setBufAddr(char *paramVirAddr, unsigned idx, unsigned value) +{ -+ int i; -+ unsigned char frameAddr[22][3][4]; -+ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; -+ unsigned int frameBufStride = ((pEncInfo->srcWidth+15)&~15); -+ unsigned int val = 0; ++ ((uint32_t*)paramVirAddr)[idx ^ 1] = cpu_to_le32(value); ++} + -+ NX_DrvMemset(frameAddr, 0, sizeof(frameAddr)); ++static int VPU_DecRegisterFrameBufCommand(struct nx_vpu_codec_inst ++ *pInst, struct vpu_dec_reg_frame_arg *pArg) ++{ ++ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; ++ unsigned i, val; + -+ /* Set Second AXI Memory (SRAM) Configuration */ -+ if (VPU_RET_OK != ConfigEncSecAXI(pEncInfo->codecStd, -+ &pEncInfo->sec_axi_info, pEncInfo->srcWidth, -+ pEncInfo->srcHeight, sramAddr, sramSize)) -+ return VPU_RET_ERR_SRAM; ++ pInfo->cbcrInterleave = pArg->chromaInterleave; ++ pInfo->cacheConfig = ++ MaverickCache2Config(1, pInfo->cbcrInterleave, 0, 0, 3, 0, 15); + -+ /* decoder(0), cbcr interleve(0), bypass(0), burst(0), merge(3), -+ maptype(linear), wayshape(15) */ -+ pEncInfo->cacheConfig = MaverickCache2Config(0, -+ pEncInfo->cbcrInterleaveRefFrame, 0, 0, 3, 0, 15); ++ SetTiledMapType(VPU_LINEAR_FRAME_MAP, pArg->strideY, ++ pInfo->cbcrInterleave); + -+ SetTiledMapType(VPU_LINEAR_FRAME_MAP, frameBufStride, -+ pEncInfo->cbcrInterleaveRefFrame); ++ for (i = 0; i < pArg->numFrameBuffer; i++) { ++ const uint32_t *phyAddr = pArg->phyAddrs->addr[i]; + -+ if (pEncInfo->frameBufMapType) { -+ if (pEncInfo->frameBufMapType == VPU_TILED_FRAME_MB_RASTER_MAP -+ || pEncInfo->frameBufMapType == VPU_TILED_FIELD_MB_RASTER_MAP) -+ val |= (pEncInfo->cbcrInterleaveRefFrame<<11) | -+ (0x03<<9)|(IMG_FORMAT_420<<6); -+ else -+ val |= (pEncInfo->cbcrInterleaveRefFrame<<11) | -+ (0x02<<9)|(IMG_FORMAT_420<<6); ++ setBufAddr(pInst->paramVirAddr, 3 * i, phyAddr[0]); ++ setBufAddr(pInst->paramVirAddr, 3 * i + 1, phyAddr[1]); ++ if (pInfo->cbcrInterleave == 0) ++ setBufAddr(pInst->paramVirAddr, 3 * i + 2, phyAddr[2]); + } + -+ /* Interleave bit position is modified */ -+ val |= (pEncInfo->cbcrInterleaveRefFrame<<2); -+ val |= VPU_FRAME_ENDIAN; -+ VpuWriteReg(BIT_FRAME_MEM_CTRL, val); ++ pInfo->strideY = pArg->strideY; ++ pInfo->phyAddrs = *pArg->phyAddrs; + -+ /* Let the decoder know the addresses of the frame buffers. */ -+ for (i = 0; i < pEncInfo->minFrameBuffers; i++) { -+ struct nx_vid_memory_info *frameBuffer = -+ &pEncInfo->frameBuffer[i]; ++ /* MV allocation and registe */ ++ if (pInst->codecMode == AVC_DEC || pInst->codecMode == VC1_DEC || ++ pInst->codecMode == MP4_DEC || pInst->codecMode == RV_DEC || ++ pInst->codecMode == AVS_DEC) ++ { ++ unsigned mvStartAddr = pArg->colMvBuffer->phyAddr; ++ int size_mvcolbuf = ((pInfo->width+31)&~31) * ++ ((pInfo->height+31)&~31); + -+ /* Y */ -+ frameAddr[i][0][0] = (frameBuffer->phyAddr[0] >> 24) & 0xFF; -+ frameAddr[i][0][1] = (frameBuffer->phyAddr[0] >> 16) & 0xFF; -+ frameAddr[i][0][2] = (frameBuffer->phyAddr[0] >> 8) & 0xFF; -+ frameAddr[i][0][3] = (frameBuffer->phyAddr[0] >> 0) & 0xFF; -+ /* Cb */ -+ frameAddr[i][1][0] = (frameBuffer->phyAddr[1] >> 24) & 0xFF; -+ frameAddr[i][1][1] = (frameBuffer->phyAddr[1] >> 16) & 0xFF; -+ frameAddr[i][1][2] = (frameBuffer->phyAddr[1] >> 8) & 0xFF; -+ frameAddr[i][1][3] = (frameBuffer->phyAddr[1] >> 0) & 0xFF; -+ /* Cr */ -+ frameAddr[i][2][0] = (frameBuffer->phyAddr[2] >> 24) & 0xFF; -+ frameAddr[i][2][1] = (frameBuffer->phyAddr[2] >> 16) & 0xFF; -+ frameAddr[i][2][2] = (frameBuffer->phyAddr[2] >> 8) & 0xFF; -+ frameAddr[i][2][3] = (frameBuffer->phyAddr[2] >> 0) & 0xFF; ++ size_mvcolbuf = (size_mvcolbuf*3) / 2; ++ size_mvcolbuf = (size_mvcolbuf+4) / 5; ++ size_mvcolbuf = ((size_mvcolbuf+7) / 8) * 8; ++ ++ if (pInst->codecMode == AVC_DEC) { ++ for (i = 0; i < pArg->numFrameBuffer; i++) { ++ setBufAddr(pInst->paramVirAddr + 384, i, mvStartAddr); ++ mvStartAddr += size_mvcolbuf; ++ } ++ } else { ++ setBufAddr(pInst->paramVirAddr + 384, 0, mvStartAddr); ++ } + } + -+ swap_endian((unsigned char *)frameAddr, sizeof(frameAddr)); -+ NX_DrvMemcpy(pInst->paramVirAddr, frameAddr, sizeof(frameAddr)); ++ if (!ConfigDecSecAXI(pInfo->codecStd, &pInfo->sec_axi_info, ++ pInfo->width, pInfo->height, pArg->sramAddr, pArg->sramSize)) { ++ NX_ErrMsg(("ConfigDecSecAXI() failed !!!\n")); ++ NX_ErrMsg(("Width = %d, Heigth = %d\n", ++ pInfo->width, pInfo->height)); ++ return VPU_RET_ERR_SRAM; ++ } + -+ /* Tell the codec how much frame buffers were allocated. */ -+ VpuWriteReg(CMD_SET_FRAME_BUF_NUM, pEncInfo->minFrameBuffers); -+ VpuWriteReg(CMD_SET_FRAME_BUF_STRIDE, frameBufStride); -+ VpuWriteReg(CMD_SET_FRAME_AXI_BIT_ADDR, -+ pEncInfo->sec_axi_info.bufBitUse); ++ /* Tell the decoder how much frame buffers were allocated. */ ++ VpuWriteReg(CMD_SET_FRAME_BUF_NUM, pArg->numFrameBuffer); ++ VpuWriteReg(CMD_SET_FRAME_BUF_STRIDE, pArg->strideY); ++ VpuWriteReg(CMD_SET_FRAME_AXI_BIT_ADDR, pInfo->sec_axi_info.bufBitUse); + VpuWriteReg(CMD_SET_FRAME_AXI_IPACDC_ADDR, -+ pEncInfo->sec_axi_info.bufIpAcDcUse); ++ pInfo->sec_axi_info.bufIpAcDcUse); + VpuWriteReg(CMD_SET_FRAME_AXI_DBKY_ADDR, -+ pEncInfo->sec_axi_info.bufDbkYUse); ++ pInfo->sec_axi_info.bufDbkYUse); + VpuWriteReg(CMD_SET_FRAME_AXI_DBKC_ADDR, -+ pEncInfo->sec_axi_info.bufDbkCUse); -+ VpuWriteReg(CMD_SET_FRAME_AXI_OVL_ADDR, -+ pEncInfo->sec_axi_info.bufOvlUse); -+ VpuWriteReg(CMD_SET_FRAME_CACHE_CONFIG, -+ pEncInfo->cacheConfig); ++ pInfo->sec_axi_info.bufDbkCUse); ++ VpuWriteReg(CMD_SET_FRAME_AXI_OVL_ADDR, pInfo->sec_axi_info.bufOvlUse); ++ VpuWriteReg(CMD_SET_FRAME_AXI_BTP_ADDR, pInfo->sec_axi_info.bufBtpUse); ++ VpuWriteReg(CMD_SET_FRAME_DELAY, pInfo->frameDelay); + -+ /* Set Sub-Sampling buffer for ME-Reference and DBK-Reconstruction */ -+ /* BPU will swap below two buffer internally every pic by pic */ -+ VpuWriteReg(CMD_SET_FRAME_SUBSAMP_A, pEncInfo->subSampleAPhyAddr); -+ VpuWriteReg(CMD_SET_FRAME_SUBSAMP_B, pEncInfo->subSampleBPhyAddr); ++ /* Maverick Cache Configuration */ ++ VpuWriteReg(CMD_SET_FRAME_CACHE_CONFIG, pInfo->cacheConfig); + -+ if (pInst->codecMode == MP4_ENC) { -+ /* MPEG4 Encoder Data-Partitioned bitstream temporal buffer */ -+ VpuWriteReg(CMD_SET_FRAME_DP_BUF_BASE, -+ pEncInfo->usbSampleDPPhyAddr); -+ VpuWriteReg(CMD_SET_FRAME_DP_BUF_SIZE, -+ pEncInfo->usbSampleDPSize); ++ if (pInst->codecMode == VPX_DEC) { ++ VpuWriteReg(CMD_SET_FRAME_MB_BUF_BASE, ++ pArg->pvbSliceBuffer->phyAddr); ++ } ++ ++ if (pInst->codecMode == AVC_DEC) { ++ VpuWriteReg(CMD_SET_FRAME_SLICE_BB_START, ++ pArg->sliceBuffer->phyAddr); ++ VpuWriteReg(CMD_SET_FRAME_SLICE_BB_SIZE, ++ pArg->sliceBuffer->size/1024); + } + ++ val = 0; ++ val |= (VPU_ENABLE_BWB<<12); ++ val |= (pInfo->cbcrInterleave<<2); ++ val |= VPU_FRAME_ENDIAN; ++ VpuWriteReg(BIT_FRAME_MEM_CTRL, val); ++ VpuWriteReg(CMD_SET_FRAME_MAX_DEC_SIZE, 0); ++ ++ VpuBitIssueCommand(pInst, SET_FRAME_BUF); ++ +#if (DBG_REGISTER) + { + int reg; + -+ NX_DbgMsg(DBG_REGISTER, ("[ENC_SET_FRM_BUF_Reg]\n")); ++ NX_DbgMsg(DBG_REGISTER, ("[DEC_SET_FRM_BUF_Reg]\n")); + for (reg = 0x180 ; reg < 0x200 ; reg += 16) { + NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", + reg, VpuReadReg(BIT_BASE + reg), @@ -107719,308 +107843,341 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c b/drivers/media/p + } +#endif + -+ VpuBitIssueCommand(pInst, SET_FRAME_BUF); + if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, + BIT_BUSY_FLAG)) { -+ NX_ErrMsg(("VPU_EncSetFrameBuffer() Failed. Timeout(%d)\n", -+ VPU_BUSY_CHECK_TIMEOUT)); -+ return VPU_RET_ERR_TIMEOUT; ++ NX_ErrMsg(("Error VPU_DecRegisterFrameBufCommand failed!!!\n")); ++ return VPU_RET_ERR_INIT; + } + + if (VpuReadReg(RET_SET_FRAME_SUCCESS) & (1<<31)) -+ return VPU_RET_ERR_MEM_ACCESS; ++ return VPU_RET_ERR_MEM_ACCESS; + ++ FUNC_OUT(); + return VPU_RET_OK; +} + -+static int VPU_EncGetHeaderCommand(struct nx_vpu_codec_inst *pInst, -+ unsigned int headerType, void **ptr, int *size) ++static int VPU_DecGetOutputInfo(struct nx_vpu_codec_inst *pInst, ++ struct vpu_dec_frame_arg *pArg) +{ -+ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; -+ int flag = 0; -+ unsigned int wdPtr, rdPtr; -+ int headerSize; ++ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; ++ unsigned int val, val2; ++ struct vpu_rect rectInfo; + -+ if (pEncInfo->ringBufferEnable == 0) { -+ VpuWriteReg(CMD_ENC_HEADER_BB_START, pEncInfo->strmBufPhyAddr); -+ VpuWriteReg(CMD_ENC_HEADER_BB_SIZE, pEncInfo->strmBufSize/1024); ++ val = VpuReadReg(RET_DEC_PIC_SUCCESS); ++ if (val & (1<<31)) { ++ pArg->errReason = VpuReadReg(GDI_WPROT_ERR_RSN); ++ pArg->errAddress = VpuReadReg(GDI_WPROT_ERR_ADR); ++ return VPU_RET_ERR_MEM_ACCESS; + } + -+ if (pInst->codecMode == AVC_ENC && headerType == SPS_RBSP) { -+ struct enc_avc_param *avcParam = -+ &pEncInfo->enc_codec_para.avcEncParam; -+ int CropH = 0, CropV = 0; ++ if (pInst->codecMode == AVC_DEC) { ++ pArg->notSufficientPsBuffer = (val >> 3) & 0x1; ++ pArg->notSufficientSliceBuffer = (val >> 2) & 0x1; ++ } + -+ if (pEncInfo->encWidth & 0xF) { -+ flag = 1; -+ avcParam->cropRight = 16 - (pEncInfo->encWidth&0xF); -+ CropH = avcParam->cropLeft << 16; -+ CropH |= avcParam->cropRight; ++ pArg->indexFrameDecoded = VpuReadReg(RET_DEC_PIC_DECODED_IDX); ++ pArg->indexFrameDisplay = VpuReadReg(RET_DEC_PIC_DISPLAY_IDX); ++ ++ val = VpuReadReg(RET_DEC_PIC_SIZE);/* decoding picture size */ ++ pArg->outWidth = (val>>16) & 0xFFFF; ++ pArg->outHeight = (val) & 0xFFFF; ++ ++ /*if (pArg->indexFrameDecoded >= 0 && pArg->indexFrameDecoded < ++ MAX_REG_FRAME) */ ++ { ++ if ((pInst->codecMode == VPX_DEC) && (pInst->auxMode == ++ VPX_AUX_VP8)) { ++ /* VP8 specific header information ++ * h_scale[31:30] v_scale[29:28] pic_width[27:14] ++ * pic_height[13:0] */ ++ val = VpuReadReg(RET_DEC_PIC_VP8_SCALE_INFO); ++ pArg->scale_info.hScaleFactor = (val >> 30) & 0x03; ++ pArg->scale_info.vScaleFactor = (val >> 28) & 0x03; ++ pArg->scale_info.picWidth = (val >> 14) & 0x3FFF; ++ pArg->scale_info.picHeight = (val >> 0) & 0x3FFF; ++ ++ /* ref_idx_gold[31:24], ref_idx_altr[23:16], ++ * ref_idx_last[15: 8], ++ * version_number[3:1], show_frame[0] */ ++ val = VpuReadReg(RET_DEC_PIC_VP8_PIC_REPORT); ++ pArg->pic_info.refIdxGold = (val >> 24) & 0x0FF; ++ pArg->pic_info.refIdxAltr = (val >> 16) & 0x0FF; ++ pArg->pic_info.refIdxLast = (val >> 8) & 0x0FF; ++ pArg->pic_info.versionNumber = (val >> 1) & 0x07; ++ pArg->pic_info.showFrame = (val >> 0) & 0x01; + } + -+ if (pEncInfo->encHeight & 0xF) { -+ flag = 1; -+ avcParam->cropBottom = 16 - (pEncInfo->encHeight&0xF); -+ CropV = avcParam->cropTop << 16; -+ CropV |= avcParam->cropBottom; ++ /* default value */ ++ rectInfo.left = 0; ++ rectInfo.right = pArg->outWidth; ++ rectInfo.top = 0; ++ rectInfo.bottom = pArg->outHeight; ++ ++ if (pInst->codecMode == AVC_DEC || ++ pInst->codecMode == MP2_DEC) { ++ val = VpuReadReg(RET_DEC_PIC_CROP_LEFT_RIGHT); ++ val2 = VpuReadReg(RET_DEC_PIC_CROP_TOP_BOTTOM); ++ ++ if (val == (unsigned int)-1 || val == 0) { ++ rectInfo.left = 0; ++ rectInfo.right = pArg->outWidth; ++ } else { ++ rectInfo.left = ((val>>16) & 0xFFFF); ++ rectInfo.right = pArg->outWidth - (val&0xFFFF); ++ } ++ ++ if (val2 == (unsigned int)-1 || val2 == 0) { ++ rectInfo.top = 0; ++ rectInfo.bottom = pArg->outHeight; ++ } else { ++ rectInfo.top = ((val2>>16) & 0xFFFF); ++ rectInfo.bottom = pArg->outHeight - ++ (val2&0xFFFF); ++ } + } + -+ VpuWriteReg(CMD_ENC_HEADER_FRAME_CROP_H, CropH); -+ VpuWriteReg(CMD_ENC_HEADER_FRAME_CROP_V, CropV); ++ pArg->outRect.left = rectInfo.left; ++ pArg->outRect.top = rectInfo.top; ++ pArg->outRect.right = rectInfo.right; ++ pArg->outRect.bottom = rectInfo.bottom; + } + -+ /* 0: SPS, 1: PPS */ -+ VpuWriteReg(CMD_ENC_HEADER_CODE, headerType | (flag << 3)); ++ val = VpuReadReg(RET_DEC_PIC_TYPE); ++ pArg->isInterace = (val >> 18) & 0x1; + -+ VpuWriteReg(BIT_RD_PTR, pEncInfo->strmBufPhyAddr); -+ VpuWriteReg(BIT_WR_PTR, pEncInfo->strmBufPhyAddr); ++ if (pInst->codecMode == MP2_DEC) { ++ pArg->progressiveFrame = (val >> 23) & 0x0003; ++ pArg->isInterace = (pArg->progressiveFrame == 0) ? (1) : (0); ++ pArg->picStructure = (val >> 19) & 0x0003; ++ } + -+#if (DBG_REGISTER) -+ { -+ int reg; ++ if (pArg->isInterace) { ++ pArg->topFieldFirst = (val >> 21) & 0x0001; ++ pArg->picTypeFirst = (val & 0x38) >> 3; ++ pArg->picType = val & 0x7; ++ pArg->npf = (val >> 15) & 1; ++ } else { ++ pArg->topFieldFirst = 0; ++ pArg->picTypeFirst = 6; ++ pArg->picType = val & 0x7; ++ } + -+ NX_DbgMsg(DBG_REGISTER, ("[ENC_HEADER_Reg]\n")); -+ for (reg = 0x180 ; reg < 0x200 ; reg += 16) { -+ NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", -+ reg, VpuReadReg(BIT_BASE + reg), -+ VpuReadReg(BIT_BASE + reg + 4), -+ VpuReadReg(BIT_BASE + reg + 8), -+ VpuReadReg(BIT_BASE + reg + 12))); ++ if (pInst->codecMode == AVC_DEC) { ++ if (val & 0x40) { ++ if (pArg->isInterace) { ++ pArg->picTypeFirst = 6; /* IDR */ ++ pArg->picType = 6; ++ } else { ++ pArg->picType = 6; /* IDR */ ++ } + } + } -+#endif + -+ VpuBitIssueCommand(pInst, ENCODE_HEADER); -+ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, -+ BIT_BUSY_FLAG)) -+ return VPU_RET_ERR_TIMEOUT; ++ pArg->fRateNumerator = VpuReadReg(RET_DEC_PIC_FRATE_NR); ++ pArg->fRateDenominator = VpuReadReg(RET_DEC_PIC_FRATE_DR); ++ if (pInst->codecMode == AVC_DEC && pArg->fRateDenominator > 0) ++ pArg->fRateDenominator *= 2; ++ if (pInst->codecMode == MP4_DEC) { ++ pArg->mp4ModuloTimeBase = ++ VpuReadReg(RET_DEC_PIC_MODULO_TIME_BASE); ++ pArg->mp4TimeIncrement = ++ VpuReadReg(RET_DEC_PIC_VOP_TIME_INCREMENT); ++ } + -+ if (pEncInfo->ringBufferEnable == 0) { -+ rdPtr = pEncInfo->strmBufPhyAddr; -+ wdPtr = VpuReadReg(BIT_WR_PTR); -+ headerSize = wdPtr - rdPtr; -+ } else { -+ rdPtr = VpuReadReg(BIT_RD_PTR); -+ wdPtr = VpuReadReg(BIT_WR_PTR); -+ headerSize = wdPtr - rdPtr; ++ if (pInst->codecMode == VPX_DEC) ++ pArg->aspectRateInfo = 0; ++ else ++ pArg->aspectRateInfo = VpuReadReg(RET_DEC_PIC_ASPECT); ++ ++ pArg->numOfErrMBs = VpuReadReg(RET_DEC_PIC_ERR_MB); ++ val = VpuReadReg(RET_DEC_PIC_SUCCESS); ++ pArg->isSuccess = val; ++ pArg->sequenceChanged = ((val>>20) & 0x1); ++ ++ if (pInst->codecMode == VC1_DEC && pArg->indexFrameDisplay != -3) { ++ if (pInfo->vc1BframeDisplayValid == 0) { ++ if (pArg->picType == 2) ++ pArg->indexFrameDisplay = -3; ++ else ++ pInfo->vc1BframeDisplayValid = 1; ++ } + } + -+ pEncInfo->strmWritePrt = wdPtr; -+ pEncInfo->strmReadPrt = rdPtr; ++ if (pInfo->codecStd == CODEC_STD_VC1) ++ pArg->multiRes = (VpuReadReg(RET_DEC_PIC_POST) >> 1) & 3; + -+ *ptr = (void *)(unsigned long)pEncInfo->strmBufVirAddr; -+ *size = headerSize; ++ pInfo->readPos = VpuReadReg(pInfo->streamRdPtrRegAddr); ++ pInfo->frameDisplayFlag = VpuReadReg(pInfo->frameDisplayFlagRegAddr); ++ ++ pInfo->bytePosFrameStart = VpuReadReg(BIT_BYTE_POS_FRAME_START); ++ pInfo->bytePosFrameEnd = VpuReadReg(BIT_BYTE_POS_FRAME_END); ++ ++ pArg->strmReadPos = pInfo->readPos - pInfo->strmBufPhyAddr; ++ pArg->strmWritePos = pInfo->writePos - pInfo->strmBufPhyAddr; + + return VPU_RET_OK; +} + -+static int VPU_EncOneFrameCommand(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_run_frame_arg *pRunArg) ++static int VPU_DecStartOneFrameCommand(struct nx_vpu_codec_inst ++ *pInst, struct vpu_dec_frame_arg *pArg) +{ -+ unsigned int readPtr, writePtr; -+ int size, picFlag/*, frameIndex*/, val, reason; -+ unsigned int sliceNumber, picEncResult, picType; -+ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; ++ struct vpu_dec_info *pInfo = &pInst->codecInfo.decInfo; ++ unsigned int val, reason = 0; + -+ /* For Linear Frame Buffer Mode */ -+ VpuWriteReg(GDI_TILEDBUF_BASE, 0x00); ++ if (pInfo->needMoreFrame) { ++ pInfo->needMoreFrame = 0; ++ VpuWriteReg(pInfo->streamWrPtrRegAddr, pInfo->writePos); ++ NX_DbgMsg(INFO_MSG, ("Need More Buffer!!!!!\n")); ++ goto WAIT_INTERRUPT; ++ } + -+ /* Mirror/Rotate Mode */ -+ if (pEncInfo->rotateAngle == 0 && pEncInfo->mirrorDirection == 0) -+ VpuWriteReg(CMD_ENC_PIC_ROT_MODE, 0); -+ else -+ VpuWriteReg(CMD_ENC_PIC_ROT_MODE, (1 << 4) | -+ (pEncInfo->mirrorDirection << 2) | -+ (pEncInfo->rotateAngle)); ++ VpuWriteReg(RET_DEC_PIC_CROP_LEFT_RIGHT, 0); ++ VpuWriteReg(RET_DEC_PIC_CROP_TOP_BOTTOM, 0); + -+ /* If rate control is enabled, this register is ignored. -+ *(MPEG-4/H.263 : 1~31, AVC : 0 ~51) */ -+ VpuWriteReg(CMD_ENC_PIC_QS, pRunArg->quantParam); ++ VpuWriteReg(GDI_TILEDBUF_BASE, 0); + -+ if (pRunArg->forceSkipPicture) { -+ VpuWriteReg(CMD_ENC_PIC_OPTION, 1); -+ } else { -+ /* Registering Source Frame Buffer information */ -+ /* Hide GDI IF under FW level */ -+ if (pRunArg->inImgBuffer.planes == 2) -+ pEncInfo->cbcrInterleave = 1; ++ if ((pInfo->enableMp4Deblock & 2) && ++ ((pInfo->codecStd == CODEC_STD_MPEG4) || ++ (pInfo->codecStd == CODEC_STD_MPEG2) || ++ (pInfo->codecStd == CODEC_STD_H263) || ++ (pInfo->codecStd == CODEC_STD_DIV3))) ++ VpuWriteReg(CMD_DEC_PIC_ROT_MODE, 1 << 5); ++ else ++ VpuWriteReg(CMD_DEC_PIC_ROT_MODE, 0); + -+ VpuWriteReg(CMD_ENC_PIC_SRC_INDEX, 2); -+ VpuWriteReg(CMD_ENC_PIC_SRC_STRIDE, -+ pRunArg->inImgBuffer.strideY); -+ VpuWriteReg(CMD_ENC_PIC_SRC_ADDR_Y, -+ pRunArg->inImgBuffer.phyAddr[0]); -+ VpuWriteReg(CMD_ENC_PIC_SRC_ADDR_CB, -+ pRunArg->inImgBuffer.phyAddr[1]); -+ VpuWriteReg(CMD_ENC_PIC_SRC_ADDR_CR, -+ pRunArg->inImgBuffer.phyAddr[2]); -+ VpuWriteReg(CMD_ENC_PIC_OPTION, -+ (pRunArg->forceIPicture << 1 & 0x2)); ++ if (pInfo->userDataEnable) { ++ VpuWriteReg(CMD_DEC_PIC_USER_DATA_BASE_ADDR, ++ pInfo->userDataBufPhyAddr); ++ VpuWriteReg(CMD_DEC_PIC_USER_DATA_BUF_SIZE, ++ pInfo->userDataBufSize); ++ } else { ++ VpuWriteReg(CMD_DEC_PIC_USER_DATA_BASE_ADDR, 0); ++ VpuWriteReg(CMD_DEC_PIC_USER_DATA_BUF_SIZE, 0); + } + -+ if (pEncInfo->ringBufferEnable == 0) { -+ VpuWriteReg(CMD_ENC_PIC_BB_START, pEncInfo->strmBufPhyAddr); -+ VpuWriteReg(CMD_ENC_PIC_BB_SIZE, pEncInfo->strmBufSize/1024); -+ VpuWriteReg(BIT_RD_PTR, pEncInfo->strmBufPhyAddr); ++ val = 0; ++ /* if iframeSearch is Enable, other bit is ignore; */ ++ if (pArg->iFrameSearchEnable != 0) { ++ val |= (pInfo->userDataReportMode << 10); ++ if (pInst->codecMode == AVC_DEC) { ++ if (pArg->iFrameSearchEnable == 1) ++ val |= (1 << 11) | (1 << 2); ++ else if (pArg->iFrameSearchEnable == 2) ++ val |= (1 << 2); ++ } else { ++ val |= ((pArg->iFrameSearchEnable & 0x1) << 2); ++ } ++ } else { ++ val |= (pInfo->userDataReportMode << 10); ++ if (!pArg->skipFrameMode) ++ val |= (pInfo->userDataEnable << 5); ++ val |= (pArg->skipFrameMode << 3); + } + ++ if (pInst->codecMode == AVC_DEC && pInfo->low_delay_info.lowDelayEn) ++ val |= (pInfo->low_delay_info.lowDelayEn << 18); ++ ++ VpuWriteReg(CMD_DEC_PIC_OPTION, val); ++ ++ if (pInfo->low_delay_info.lowDelayEn) ++ VpuWriteReg(CMD_DEC_PIC_NUM_ROWS, ++ pInfo->low_delay_info.numRows); ++ else ++ VpuWriteReg(CMD_DEC_PIC_NUM_ROWS, 0); ++ + val = 0; + val = ( -+ (pEncInfo->sec_axi_info.useBitEnable & 0x01)<<0 | -+ (pEncInfo->sec_axi_info.useIpEnable & 0x01)<<1 | -+ (pEncInfo->sec_axi_info.useDbkYEnable & 0x01)<<2 | -+ (pEncInfo->sec_axi_info.useDbkCEnable & 0x01)<<3 | ++ (pInfo->sec_axi_info.useBitEnable&0x01)<<0 | ++ (pInfo->sec_axi_info.useIpEnable&0x01)<<1 | ++ (pInfo->sec_axi_info.useDbkYEnable&0x01)<<2 | ++ (pInfo->sec_axi_info.useDbkCEnable&0x01)<<3 | ++ (pInfo->sec_axi_info.useOvlEnable&0x01)<<4 | ++ (pInfo->sec_axi_info.useBtpEnable&0x01)<<5 | ++ (pInfo->sec_axi_info.useBitEnable&0x01)<<8 | ++ (pInfo->sec_axi_info.useIpEnable&0x01)<<9 | ++ (pInfo->sec_axi_info.useDbkYEnable&0x01)<<10 | ++ (pInfo->sec_axi_info.useDbkCEnable&0x01)<<11 | ++ (pInfo->sec_axi_info.useOvlEnable&0x01)<<12 | ++ (pInfo->sec_axi_info.useBtpEnable&0x01)<<13); + -+ (pEncInfo->sec_axi_info.useOvlEnable & 0x01)<<4 | -+ (pEncInfo->sec_axi_info.useBtpEnable & 0x01)<<5 | ++ VpuWriteReg(BIT_AXI_SRAM_USE, val); + -+ (pEncInfo->sec_axi_info.useBitEnable & 0x01)<<8 | -+ (pEncInfo->sec_axi_info.useIpEnable & 0x01)<<9 | -+ (pEncInfo->sec_axi_info.useDbkYEnable & 0x01)<<10| -+ (pEncInfo->sec_axi_info.useDbkCEnable & 0x01)<<11| ++ VpuWriteReg(pInfo->streamWrPtrRegAddr, pInfo->writePos); ++ VpuWriteReg(pInfo->streamRdPtrRegAddr, pInfo->readPos); + -+ (pEncInfo->sec_axi_info.useOvlEnable & 0x01)<<12| -+ (pEncInfo->sec_axi_info.useBtpEnable & 0x01)<<13); ++ val = pInfo->frameDisplayFlag; ++ val &= ~pInfo->clearDisplayIndexes; ++ VpuWriteReg(pInfo->frameDisplayFlagRegAddr, val); ++ pInfo->clearDisplayIndexes = 0; + -+ VpuWriteReg(BIT_AXI_SRAM_USE, val); ++ if (pArg->eos) ++ pInfo->streamEndflag |= 1<<2; ++ else ++ pInfo->streamEndflag &= ~(1<<2); + -+ VpuWriteReg(BIT_WR_PTR, pEncInfo->strmBufPhyAddr); -+ VpuWriteReg(BIT_RD_PTR, pEncInfo->strmBufPhyAddr); -+ VpuWriteReg(BIT_BIT_STREAM_PARAM, pEncInfo->strmEndFlag); ++ pInfo->streamEndflag &= ~(3<<3); ++ if (pInfo->bitStreamMode == BS_MODE_ROLLBACK) ++ pInfo->streamEndflag |= (1<<3); ++ else if (pInfo->bitStreamMode == BS_MODE_PIC_END) ++ pInfo->streamEndflag |= (2<<3); ++ ++ VpuWriteReg(BIT_BIT_STREAM_PARAM, pInfo->streamEndflag); + + val = 0; -+ val |= (pEncInfo->bwbEnable<<12) | (pEncInfo->cbcrInterleave<<2); -+ val |= pEncInfo->frameEndian; ++ val |= (pInfo->bwbEnable<<12); ++ val |= ((pInfo->cbcrInterleave)<<2); ++ /* val |= pInfo->frameEndian; */ + VpuWriteReg(BIT_FRAME_MEM_CTRL, val); + -+ if (pEncInfo->ringBufferEnable == 0) { -+ val = 0; -+ val |= (0x1<<6); -+ val |= (0x1<<5); -+ val |= (0x1<<4); -+ } else { -+ val |= (0x1<<3); -+ } -+ val |= VPU_STREAM_ENDIAN; ++ val = pInfo->streamEndian; + VpuWriteReg(BIT_BIT_STREAM_CTRL, val); + +#if (DBG_REGISTER) + { + int reg; + -+ NX_DbgMsg(DBG_REGISTER, ("[ENC_RUN_Reg]\n")); ++ NX_DbgMsg(DBG_REGISTER, ("[DEC_FRAME]\n")); + for (reg = 0x180 ; reg < 0x200 ; reg += 16) { + NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", + reg, VpuReadReg(BIT_BASE + reg), + VpuReadReg(BIT_BASE + reg + 4), + VpuReadReg(BIT_BASE + reg + 8), + VpuReadReg(BIT_BASE + reg + 12))); -+ } -+ } -+#endif -+ -+ VpuBitIssueCommand(pInst, PIC_RUN); -+ -+ do { -+ reason = VPU_WaitBitInterrupt(pInst->devHandle, -+ VPU_ENC_TIMEOUT); -+ -+ if (reason == 0) -+ return VPU_RET_ERR_TIMEOUT; -+ if (reason & (1<reconImgIdx = VpuReadReg(RET_ENC_PIC_FRAME_IDX); -+ -+ pEncInfo->strmEndFlag = VpuReadReg(BIT_BIT_STREAM_PARAM); -+ -+ pRunArg->frameType = picType; -+ pRunArg->outStreamSize = size; -+ pRunArg->outStreamAddr = pEncInfo->strmBufVirAddr; -+ -+ /*NX_DbgMsg(INFO_MSG, ("Encoded Size = %d, PicType = %d, picFlag = %d, -+ sliceNumber = %d\n", size, picType, picFlag, sliceNumber));*/ -+ -+ return VPU_RET_OK; -+} -+ -+static int VPU_EncChangeParameterCommand(struct nx_vpu_codec_inst *pInst, -+ struct vpu_enc_chg_para_arg *pChgArg) -+{ -+ int ret; -+ -+ if (pChgArg->chgFlg & VPU_BIT_CHG_GOP) -+ VpuWriteReg(CMD_ENC_SEQ_PARA_RC_GOP, pChgArg->gopSize); -+ -+ if (pChgArg->chgFlg & VPU_BIT_CHG_INTRAQP) -+ VpuWriteReg(CMD_ENC_SEQ_PARA_RC_INTRA_QP, pChgArg->intraQp); -+ -+ if (pChgArg->chgFlg & VPU_BIT_CHG_BITRATE) -+ VpuWriteReg(CMD_ENC_SEQ_PARA_RC_BITRATE, pChgArg->bitrate); -+ -+ if (pChgArg->chgFlg & VPU_BIT_CHG_FRAMERATE) -+ VpuWriteReg(CMD_ENC_SEQ_PARA_RC_FRAME_RATE, -+ (pChgArg->frameRateNum) | ((pChgArg->frameRateDen-1) << 16)); -+ -+ if (pChgArg->chgFlg & VPU_BIT_CHG_INTRARF) -+ VpuWriteReg(CMD_ENC_SEQ_PARA_INTRA_MB_NUM, -+ pChgArg->intraRefreshMbs); -+ -+ if (pChgArg->chgFlg & VPU_BIT_CHG_SLICEMOD) -+ VpuWriteReg(CMD_ENC_SEQ_PARA_SLICE_MODE, (pChgArg->sliceMode) | -+ (pChgArg->sliceSizeMode << 2) | (pChgArg->sliceSizeNum << 3)); -+ -+ if (pChgArg->chgFlg & VPU_BIT_CHG_HECMODE) -+ VpuWriteReg(CMD_ENC_SEQ_PARA_HEC_MODE, pChgArg->hecMode); ++ } ++ } ++#endif + -+ VpuWriteReg(CMD_ENC_SEQ_PARA_CHANGE_ENABLE, pChgArg->chgFlg & 0x7F); ++ VpuBitIssueCommand(pInst, PIC_RUN); + -+ VpuBitIssueCommand(pInst, RC_CHANGE_PARAMETER); -+ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, -+ BIT_BUSY_FLAG)) ++WAIT_INTERRUPT: ++ reason = VPU_WaitBitInterrupt(pInst->devHandle, VPU_DEC_TIMEOUT); ++ if (!reason) { ++ NX_ErrMsg(("VPU_DecStartOneFrameCommand() Fail. Timeout(%d)\n", ++ VPU_BUSY_CHECK_TIMEOUT)); + return VPU_RET_ERR_TIMEOUT; ++ } + -+ ret = VpuReadReg(RET_ENC_SEQ_PARA_CHANGE_SECCESS); -+ if ((ret & 1) == 0) -+ return VPU_RET_ERR_CHG_PARAM; -+ if (ret >> 31) -+ return VPU_RET_ERR_MEM_ACCESS; -+ -+ return VPU_RET_OK; ++ if (reason & (1<needMoreFrame = 1; ++ return VPU_RET_NEED_STREAM; ++ } else { ++ return VPU_RET_ERROR; ++ } +} + -+static int VPU_EncCloseCommand(struct nx_vpu_codec_inst *pInst, ++static int VPU_DecCloseCommand(struct nx_vpu_codec_inst *pInst, + void *vpu_event_present) +{ + FUNC_IN(); -+ + if (pInst->isInitialized) { -+ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; -+ -+ VpuWriteReg(BIT_WR_PTR, pEncInfo->strmBufPhyAddr); -+ VpuWriteReg(BIT_RD_PTR, pEncInfo->strmBufPhyAddr); -+ + VpuBitIssueCommand(pInst, SEQ_END); + if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, + BIT_BUSY_FLAG)) { + VpuWriteReg(BIT_INT_CLEAR, 0x1); + atomic_set((atomic_t *)vpu_event_present, 0); -+ NX_ErrMsg(("VPU_EncCloseCommand() Failed!!!\n")); ++ NX_ErrMsg(("VPU_DecCloseCommand() Failed!!!\n")); + NX_ErrMsg(("Timeout(%d)\n", VPU_BUSY_CHECK_TIMEOUT)); + VPU_SWReset(SW_RESET_SAFETY); + pInst->isInitialized = 0; @@ -108029,15 +108186,16 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c b/drivers/media/p + pInst->isInitialized = 0; + } + -+ VpuWriteReg(BIT_INT_CLEAR, 0x1); /* For Signal Break Out */ -+ atomic_set((atomic_t *)vpu_event_present, 0);/* Clear Atomic */ -+ ++ VpuWriteReg(BIT_INT_CLEAR, 0x1); ++ atomic_set((atomic_t *)vpu_event_present, 0); + FUNC_OUT(); + return VPU_RET_OK; +} -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_enc_v4l2.c b/drivers/media/platform/nxp-vpu/nx_vpu_enc_v4l2.c ---- a/drivers/media/platform/nxp-vpu/nx_vpu_enc_v4l2.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_vpu_enc_v4l2.c 2018-05-06 08:49:50.074731776 +0200 +diff --git a/drivers/media/platform/nxp-vpu/nx_vpu_enc_v4l2.c b/drivers/media/platform/nxp-vpu/nx_vpu_enc_v4l2.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_vpu_enc_v4l2.c @@ -0,0 +1,1668 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -109101,615 +109259,1618 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_enc_v4l2.c b/drivers/media/ + spin_unlock_irqrestore(&dev->irqlock, flags); +} + -+static void nx_vpu_enc_buf_queue(struct vb2_buffer *vb) ++static void nx_vpu_enc_buf_queue(struct vb2_buffer *vb) ++{ ++ struct vb2_queue *vq = vb->vb2_queue; ++ struct nx_vpu_ctx *ctx = vq->drv_priv; ++ struct nx_vpu_v4l2 *dev = ctx->dev; ++ unsigned long flags; ++ struct nx_vpu_buf *buf = vb_to_vpu_buf(vb); ++ ++ FUNC_IN(); ++ ++ spin_lock_irqsave(&dev->irqlock, flags); ++ ++ if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { ++ ++ NX_DbgMsg(INFO_MSG, ("adding to dst: %p (%08lx)\n", vb, ++ (unsigned long)nx_vpu_mem_plane_addr(vb, 0))); ++ ++ list_add_tail(&buf->list, &ctx->strm_queue); ++ ctx->strm_queue_cnt++; ++ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { ++ NX_DbgMsg(INFO_MSG, ("adding to src: %p(%08lx, %08lx)\n", ++ vb, (unsigned long)nx_vpu_mem_plane_addr(vb, 0), ++ (unsigned long)nx_vpu_mem_plane_addr(vb, 1))); ++ ++ list_add_tail(&buf->list, &ctx->img_queue); ++ ctx->img_queue_cnt++; ++ } else { ++ NX_ErrMsg(("unsupported buffer type (%d)\n", vq->type)); ++ } ++ ++ spin_unlock_irqrestore(&dev->irqlock, flags); ++ ++ if (nx_vpu_enc_ctx_ready(ctx)) ++ nx_vpu_enc_try_run(ctx); ++} ++ ++static struct vb2_ops nx_vpu_enc_qops = { ++ .queue_setup = nx_vpu_queue_setup, ++ .wait_prepare = nx_vpu_unlock, ++ .wait_finish = nx_vpu_lock, ++ .buf_prepare = nx_vpu_buf_prepare, ++ .start_streaming = nx_vpu_enc_start_streaming, ++ .stop_streaming = nx_vpu_enc_stop_streaming, ++ .buf_queue = nx_vpu_enc_buf_queue, ++}; ++ ++/* -------------------------------------------------------------------------- */ ++ ++ ++const struct v4l2_ioctl_ops *get_enc_ioctl_ops(void) ++{ ++ return &nx_vpu_enc_ioctl_ops; ++}; ++ ++int nx_vpu_enc_open(struct nx_vpu_ctx *ctx) ++{ ++ int ret = 0; ++ ++ FUNC_IN(); ++ ++ /* Init videobuf2 queue for INPUT */ ++ ctx->vq_img.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; ++ ctx->vq_img.drv_priv = ctx; ++ ctx->vq_img.lock = &ctx->dev->dev_mutex; ++ ctx->vq_img.buf_struct_size = sizeof(struct nx_vpu_buf); ++ ctx->vq_img.io_modes = VB2_USERPTR | VB2_DMABUF; ++ /* ctx->vq_strm.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; */ ++ ctx->vq_img.ops = &nx_vpu_enc_qops; ++ ctx->vq_img.mem_ops = &vb2_dma_contig_memops; ++ /*ctx->vq_img.allow_zero_byteused = 1; */ ++ ctx->vq_img.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ++ ctx->vq_img.dev = &ctx->dev->plat_dev->dev; ++ ret = vb2_queue_init(&ctx->vq_img); ++ if (ret) { ++ NX_ErrMsg(("Failed to initialize videobuf2 queue(output)\n")); ++ return ret; ++ } ++ ++ /* Init videobuf2 queue for OUTPUT */ ++ ctx->vq_strm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ ctx->vq_strm.drv_priv = ctx; ++ ctx->vq_strm.lock = &ctx->dev->dev_mutex; ++ ctx->vq_strm.buf_struct_size = sizeof(struct nx_vpu_buf); ++ ctx->vq_strm.io_modes = VB2_USERPTR | VB2_DMABUF; ++ /* ctx->vq_strm.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; */ ++ ctx->vq_strm.ops = &nx_vpu_enc_qops; ++ ctx->vq_strm.mem_ops = &vb2_dma_contig_memops; ++ ctx->vq_strm.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ++ ctx->vq_strm.dev = &ctx->dev->plat_dev->dev; ++ ret = vb2_queue_init(&ctx->vq_strm); ++ if (ret) { ++ NX_ErrMsg(("Failed to initialize videobuf2 queue(capture)\n")); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++int vpu_enc_open_instance(struct nx_vpu_ctx *ctx) ++{ ++ struct nx_vpu_v4l2 *dev = ctx->dev; ++ struct nx_vpu_codec_inst *hInst = 0; ++ struct vpu_open_arg openArg; ++ int ret; ++ ++ FUNC_IN(); ++ ++ memset(&openArg, 0, sizeof(openArg)); ++ ++ switch (ctx->strm_fmt->fourcc) { ++ case V4L2_PIX_FMT_MPEG4: ++ ctx->codec_mode = CODEC_STD_MPEG4; ++ break; ++ case V4L2_PIX_FMT_H264: ++ ctx->codec_mode = CODEC_STD_AVC; ++ break; ++ case V4L2_PIX_FMT_H263: ++ ctx->codec_mode = CODEC_STD_H263; ++ break; ++ case V4L2_PIX_FMT_MJPEG: ++ ctx->codec_mode = CODEC_STD_MJPG; ++ break; ++ default: ++ NX_ErrMsg(("Invalid codec type (%x)!!!\n", ++ ctx->strm_fmt->fourcc)); ++ goto err_exit; ++ } ++ openArg.codecStd = ctx->codec_mode; ++ ++ /* Allocate Instance Memory & Stream Buffer */ ++ ctx->instance_buf = nx_alloc_memory(&dev->plat_dev->dev, WORK_BUF_SIZE, ++ 4096); ++ if (ctx->instance_buf == NULL) { ++ NX_ErrMsg(("hinstance_buf allocation failed.\n")); ++ goto err_exit; ++ } ++ ++ openArg.instanceBuf = *ctx->instance_buf; ++ openArg.instIndex = ctx->idx; ++ openArg.isEncoder = 1; ++ ++ ret = NX_VpuEncOpen(&openArg, dev, &hInst); ++ if ((VPU_RET_OK != ret) || (0 == hInst)) { ++ NX_ErrMsg(("Cannot open VPU Instance!!!\n")); ++ NX_ErrMsg((" codecStd=%d, is_encoder=%d, hInst=%p)\n", ++ openArg.codecStd, openArg.isEncoder, hInst)); ++ ret = -1; ++ goto err_exit; ++ } ++ ++ ctx->hInst = (void *)hInst; ++ dev->cur_num_instance++; ++ ++ return ret; ++ ++err_exit: ++ if (ctx->instance_buf) ++ nx_free_memory(ctx->instance_buf); ++ ++ return ret; ++} ++ ++static void get_stream_buffer(struct nx_vpu_ctx *ctx, ++ struct nx_memory_info *stream_buf) ++{ ++ struct nx_vpu_buf *dst_mb; ++ ++ FUNC_IN(); ++ ++ /* spin_lock_irqsave(&ctx->dev->irqlock, flags); */ ++ ++ dst_mb = list_entry(ctx->strm_queue.next, struct nx_vpu_buf, list); ++ ++ stream_buf->phyAddr = nx_vpu_mem_plane_addr(&dst_mb->vb, 0); ++ stream_buf->size = vb2_plane_size(&dst_mb->vb, 0); ++#ifdef USE_ION_MEMORY ++ stream_buf->virAddr = (unsigned int)cma_get_virt(stream_buf->phyAddr, ++ stream_buf->size, 1); ++#else ++ stream_buf->virAddr = vb2_plane_vaddr(&dst_mb->vb, 0); ++#endif ++ ++ /* spin_unlock_irqrestore(&ctx->dev->irqlock, flags); */ ++} ++ ++int vpu_enc_init(struct nx_vpu_ctx *ctx) ++{ ++ struct vpu_enc_ctx *enc_ctx = &ctx->codec.enc; ++ struct vpu_enc_seq_arg *pSeqArg = &ctx->codec.enc.seq_para; ++ int ret = 0; ++ ++ FUNC_IN(); ++ ++ if (ctx->hInst == NULL) { ++ NX_ErrMsg(("Err : vpu is not opened\n")); ++ return -EAGAIN; ++ } ++ ++ pSeqArg->strmBufPhyAddr = (uint64_t)ctx->bit_stream_buf->phyAddr; ++ pSeqArg->strmBufVirAddr = (unsigned long)ctx->bit_stream_buf->virAddr; ++ pSeqArg->strmBufSize = ctx->bit_stream_buf->size; ++ ++ if ((pSeqArg->strmBufPhyAddr == 0) || (pSeqArg->strmBufSize == 0)) { ++ NX_ErrMsg(("stream buffer error(addr = %llx, size = %d)\n", ++ pSeqArg->strmBufPhyAddr, pSeqArg->strmBufSize)); ++ return -1; ++ } ++ ++ if ((pSeqArg->srcWidth == 0) || (pSeqArg->srcWidth > 1920) || ++ (pSeqArg->srcHeight == 0) || (pSeqArg->srcHeight > 1088)) { ++ NX_ErrMsg(("resolution pamameter error(W = %d, H = %d)\n", ++ pSeqArg->srcWidth, pSeqArg->srcHeight)); ++ return -1; ++ } ++ ++ if (ctx->codec_mode != CODEC_STD_MJPG) { ++ if (pSeqArg->bitrate) { ++ if (pSeqArg->gammaFactor == 0) ++ pSeqArg->gammaFactor = (int)(0.75 * 32768); ++ } else { ++ if (enc_ctx->userIQP == 0) ++ enc_ctx->userIQP = 26; ++ if (enc_ctx->userPQP == 0) ++ enc_ctx->userPQP = 26; ++ } ++ ++ if (ctx->codec_mode == CODEC_STD_AVC) { ++ if ((pSeqArg->maxQP > 51) || (pSeqArg->maxQP == 0)) ++ pSeqArg->maxQP = 51; ++ } else { ++ if ((pSeqArg->maxQP > 31) || (pSeqArg->maxQP == 0)) ++ pSeqArg->maxQP = 31; ++ ++ if (ctx->codec_mode == CODEC_STD_H263) ++ pSeqArg->searchRange = 3; ++ } ++ } else { ++ pSeqArg->frameRateNum = 1; ++ pSeqArg->frameRateDen = 1; ++ pSeqArg->gopSize = 1; ++ ++ switch (ctx->img_fmt->fourcc) { ++ case V4L2_PIX_FMT_YUV420M: ++ pSeqArg->imgFormat = IMG_FORMAT_420; ++ pSeqArg->chromaInterleave = 0; ++ break; ++ case V4L2_PIX_FMT_YUV422M: ++ pSeqArg->imgFormat = IMG_FORMAT_422; ++ pSeqArg->chromaInterleave = 0; ++ break; ++ case V4L2_PIX_FMT_YUV444M: ++ pSeqArg->imgFormat = IMG_FORMAT_444; ++ pSeqArg->chromaInterleave = 0; ++ break; ++ case V4L2_PIX_FMT_GREY: ++ pSeqArg->imgFormat = IMG_FORMAT_400; ++ break; ++ case V4L2_PIX_FMT_NV12M: ++ pSeqArg->imgFormat = IMG_FORMAT_420; ++ pSeqArg->chromaInterleave = 1; ++ break; ++ case V4L2_PIX_FMT_NV16M: ++ pSeqArg->imgFormat = IMG_FORMAT_422; ++ pSeqArg->chromaInterleave = 1; ++ break; ++ case V4L2_PIX_FMT_NV24M: ++ pSeqArg->imgFormat = IMG_FORMAT_444; ++ pSeqArg->chromaInterleave = 1; ++ break; ++ default: ++ NX_ErrMsg(("Color format is not supported!!")); ++ return -EINVAL; ++ } ++ } ++ ++ ret = NX_VpuEncSetSeqParam(ctx->hInst, pSeqArg); ++ if (ret != VPU_RET_OK) { ++ NX_ErrMsg(("NX_VpuEncSetSeqParam() failed.(ErrorCode=%d)\n", ++ ret)); ++ return ret; ++ } ++ ++ if (ctx->codec_mode != CODEC_STD_MJPG) { ++ struct vpu_enc_set_frame_arg frameArg; ++ union vpu_enc_get_header_arg *pHdrArg ++ = &ctx->codec.enc.seq_info; ++ ++ /* We use always 2 frame */ ++ frameArg.numFrameBuffer = 2; ++ ++ frameArg.frameBuffer[0] = *enc_ctx->ref_recon_buf[0]; ++ frameArg.frameBuffer[1] = *enc_ctx->ref_recon_buf[1]; ++ frameArg.subSampleBuffer[0] = *enc_ctx->sub_sample_buf[0]; ++ frameArg.subSampleBuffer[1] = *enc_ctx->sub_sample_buf[1]; ++ ++ /* data partition mode always disabled (for MPEG4) */ ++ frameArg.dataPartitionBuffer.phyAddr = 0; ++ frameArg.dataPartitionBuffer.virAddr = 0; ++ ++ frameArg.sramAddr = ctx->dev->sram_base_addr; ++ frameArg.sramSize = ctx->dev->sram_size; ++ ++ ret = NX_VpuEncSetFrame(ctx->hInst, &frameArg); ++ if (ret != VPU_RET_OK) { ++ NX_ErrMsg(("NX_VpuEncSetFrame() is failed!(ret = %d\n", ++ ret)); ++ goto ERROR_EXIT; ++ } ++ ++ ret = NX_VpuEncGetHeader(ctx->hInst, pHdrArg); ++ if (ret != VPU_RET_OK) { ++ NX_ErrMsg(("NX_VpuEncGetHeader() is failed!(ret = %d\n", ++ ret)); ++ goto ERROR_EXIT; ++ } ++ } ++ ++ enc_ctx->gop_frm_cnt = 0; ++ ++ERROR_EXIT: ++ return ret; ++} ++ ++void vpu_enc_get_seq_info(struct nx_vpu_ctx *ctx) ++{ ++ struct nx_memory_info stream_buf; ++ union vpu_enc_get_header_arg *pHdr = &ctx->codec.enc.seq_info; ++ void *pvDst; ++ ++ FUNC_IN(); ++ ++ if (ctx->codec_mode == CODEC_STD_AVC) { ++ get_stream_buffer(ctx, &stream_buf); ++ pvDst = stream_buf.virAddr; ++ ++ NX_DrvMemcpy(pvDst, (void *)pHdr->avcHeader.spsData, ++ pHdr->avcHeader.spsSize); ++ pvDst += pHdr->avcHeader.spsSize; ++ NX_DrvMemcpy(pvDst, (void *)pHdr->avcHeader.ppsData, ++ pHdr->avcHeader.ppsSize); ++ ctx->strm_size = pHdr->avcHeader.spsSize + ++ pHdr->avcHeader.ppsSize; ++ } else if (ctx->codec_mode == CODEC_STD_MPEG4) { ++ get_stream_buffer(ctx, &stream_buf); ++ pvDst = stream_buf.virAddr; ++ ++ NX_DrvMemcpy((void *)stream_buf.virAddr, ++ pHdr->mp4Header.vosData, pHdr->mp4Header.vosSize); ++ NX_DrvMemcpy((void *)stream_buf.virAddr + ++ pHdr->mp4Header.vosSize, pHdr->mp4Header.volData, ++ pHdr->mp4Header.volSize); ++ ctx->strm_size = pHdr->mp4Header.vosSize + ++ pHdr->mp4Header.volSize; ++ } else { ++ ctx->strm_size = 0; ++ } ++ ++ { ++ struct nx_vpu_buf *dst_mb; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ctx->dev->irqlock, flags); ++ ++ dst_mb = list_entry(ctx->strm_queue.next, struct nx_vpu_buf, ++ list); ++ list_del(&dst_mb->list); ++ ctx->strm_queue_cnt--; ++ ++ vb2_set_plane_payload(&dst_mb->vb, 0, ctx->strm_size); ++ vb2_buffer_done(&dst_mb->vb, VB2_BUF_STATE_DONE); ++ ++ spin_unlock_irqrestore(&ctx->dev->irqlock, flags); ++ } ++} ++ ++int vpu_enc_encode_frame(struct nx_vpu_ctx *ctx) ++{ ++ struct vpu_enc_ctx *enc_ctx = &ctx->codec.enc; ++ struct nx_vpu_v4l2 *dev = ctx->dev; ++ struct nx_vpu_codec_inst *hInst = ctx->hInst; ++ int ret = 0, i; ++ unsigned long flags; ++ struct nx_vpu_buf *mb_entry; ++ struct vpu_enc_run_frame_arg *pRunArg = &enc_ctx->run_info; ++ struct nx_memory_info stream_buf; ++ int num_planes; ++ ++ FUNC_IN(); ++ ++ if (ctx->hInst == NULL) { ++ NX_ErrMsg(("Err : vpu is not opened\n")); ++ return -EAGAIN; ++ } ++ ++ if (enc_ctx->chg_para.chgFlg) { ++ ret = NX_VpuEncChgParam(hInst, &enc_ctx->chg_para); ++ if (ret != VPU_RET_OK) { ++ NX_ErrMsg(("NX_VpuEncChgParam() failed.(Err=%d)\n", ++ ret)); ++ return ret; ++ } ++ ++ NX_DrvMemset(&enc_ctx->chg_para, 0, sizeof(enc_ctx->chg_para)); ++ } ++ ++ get_stream_buffer(ctx, &stream_buf); ++ ++ spin_lock_irqsave(&dev->irqlock, flags); ++ ++ mb_entry = list_entry(ctx->img_queue.next, struct nx_vpu_buf, list); ++ ++ num_planes = ctx->useSingleBuf || ctx->img_fmt->singleBuffer ? 1 : ++ ctx->img_fmt->chromaInterleave ? 2 : 3; ++ for (i = 0 ; i < num_planes ; i++) { ++ pRunArg->inImgBuffer.phyAddr[i] = nx_vpu_mem_plane_addr( ++ &mb_entry->vb, i); ++ pRunArg->inImgBuffer.strideY = ctx->buf_y_width; ++ } ++ ++ if( num_planes == 1 && ctx->chroma_size > 0 ) { ++ pRunArg->inImgBuffer.phyAddr[1] = ctx->luma_size + ++ pRunArg->inImgBuffer.phyAddr[0]; ++ if (ctx->chromaInterleave == 0) ++ pRunArg->inImgBuffer.phyAddr[2] = ctx->chroma_size + ++ pRunArg->inImgBuffer.phyAddr[1]; ++ } ++ ++ spin_unlock_irqrestore(&dev->irqlock, flags); ++ ++ dev->curr_ctx = ctx->idx; ++ ++ if (ctx->codec_mode != V4L2_PIX_FMT_MJPEG) { ++ if ((enc_ctx->gop_frm_cnt >= enc_ctx->seq_para.gopSize) || ++ (enc_ctx->gop_frm_cnt == 0)) ++ pRunArg->forceIPicture = 1; ++ ++ enc_ctx->gop_frm_cnt = (pRunArg->forceIPicture) ? ++ (1) : (enc_ctx->gop_frm_cnt + 1); ++ } ++ ++ ret = NX_VpuEncRunFrame(hInst, pRunArg); ++ if (ret != VPU_RET_OK) { ++ NX_ErrMsg(("NX_VpuEncRunFrame() failed.(ErrorCode=%d)\n", ret)); ++ return ret; ++ } ++ ++ memcpy(stream_buf.virAddr, ++ (void *)(unsigned long)pRunArg->outStreamAddr, ++ pRunArg->outStreamSize); ++ ctx->strm_size = pRunArg->outStreamSize; ++ ++ spin_lock_irqsave(&dev->irqlock, flags); ++ ++ if (ctx->img_queue_cnt > 0) { ++ mb_entry = list_entry(ctx->img_queue.next, struct nx_vpu_buf, ++ list); ++ list_del(&mb_entry->list); ++ ctx->img_queue_cnt--; ++ ++ vb2_buffer_done(&mb_entry->vb, VB2_BUF_STATE_DONE); ++ } ++ ++ if (ctx->strm_size > 0) { ++ struct vb2_v4l2_buffer *vbuf; ++ mb_entry = list_entry(ctx->strm_queue.next, struct nx_vpu_buf, ++ list); ++ ++ list_del(&mb_entry->list); ++ ctx->strm_queue_cnt--; ++ vbuf = to_vb2_v4l2_buffer(&mb_entry->vb); ++ ++ switch (pRunArg->frameType) { ++ case 0: ++ case 6: ++ vbuf->flags = V4L2_BUF_FLAG_KEYFRAME; ++ break; ++ case 1: ++ vbuf->flags = V4L2_BUF_FLAG_PFRAME; ++ break; ++ case 2: ++ case 3: ++ vbuf->flags = V4L2_BUF_FLAG_BFRAME; ++ break; ++ default: ++ vbuf->flags = V4L2_BUF_FLAG_PFRAME; ++ NX_ErrMsg(("not defined frame type!!!\n")); ++ break; ++ } ++ vb2_set_plane_payload(&mb_entry->vb, 0, ctx->strm_size); ++ ++ vb2_buffer_done(&mb_entry->vb, VB2_BUF_STATE_DONE); ++ } ++ ++ spin_unlock_irqrestore(&dev->irqlock, flags); ++ ++ return ret; ++} ++ ++static int alloc_encoder_memory(struct nx_vpu_ctx *ctx) ++{ ++ int width, height, i; ++ struct vpu_enc_ctx *enc_ctx = &ctx->codec.enc; ++ void *drv = &ctx->dev->plat_dev->dev; ++ ++ FUNC_IN(); ++ ++ width = ALIGN(ctx->width, 16); ++ height = ALIGN(ctx->height, 16); ++ ++ if (ctx->codec_mode != CODEC_STD_MJPG) { ++ int num; ++ uint32_t format; ++ ++ if (enc_ctx->reconChromaInterleave == 0) { ++ num = 3; ++ format = V4L2_PIX_FMT_YUV420M; ++ } else { ++ num = 2; ++ format = V4L2_PIX_FMT_NV12M; ++ } ++ ++ for (i = 0 ; i < 2 ; i++) { ++ enc_ctx->ref_recon_buf[i] = nx_alloc_frame_memory(drv, ++ width, height, num, format, 64); ++ ++ if (enc_ctx->ref_recon_buf[i] == 0) { ++ NX_ErrMsg(("alloc(%d,%d,..) failed(recon%d)\n", ++ width, height, i)); ++ goto Error_Exit; ++ } ++ ++ enc_ctx->sub_sample_buf[i] = nx_alloc_memory(drv, ++ width * height/4, 4096); ++ if (enc_ctx->sub_sample_buf[i] == 0) { ++ NX_ErrMsg(("sub_buf allocation failed\n")); ++ NX_ErrMsg((" size = %d, align = %d)\n", ++ width * height, 16)); ++ goto Error_Exit; ++ } ++ } ++ } ++ ++ ctx->bit_stream_buf = nx_alloc_memory(drv, STREAM_BUF_SIZE, 4096); ++ if (0 == ctx->bit_stream_buf) { ++ NX_ErrMsg(("bit_stream_buf allocation failed.\n")); ++ NX_ErrMsg((" size = %d, align = %d)\n", ++ STREAM_BUF_SIZE, 4096)); ++ goto Error_Exit; ++ } ++ ++ return 0; ++ ++Error_Exit: ++ free_encoder_memory(ctx); ++ return -1; ++} ++ ++static int free_encoder_memory(struct nx_vpu_ctx *ctx) ++{ ++ struct vpu_enc_ctx *enc_ctx = &ctx->codec.enc; ++ ++ FUNC_IN(); ++ ++ if (!ctx) { ++ NX_ErrMsg(("invalid encoder handle!!!\n")); ++ return -1; ++ } ++ ++ /* Free Reconstruct Buffer & Reference Buffer */ ++ if (enc_ctx->ref_recon_buf[0]) ++ nx_free_frame_memory(enc_ctx->ref_recon_buf[0]); ++ ++ if (enc_ctx->ref_recon_buf[1]) ++ nx_free_frame_memory(enc_ctx->ref_recon_buf[1]); ++ ++ /* Free SubSampleb Buffer */ ++ if (enc_ctx->sub_sample_buf[0]) ++ nx_free_memory(enc_ctx->sub_sample_buf[0]); ++ ++ if (enc_ctx->sub_sample_buf[1]) ++ nx_free_memory(enc_ctx->sub_sample_buf[1]); ++ ++ /* Free Bitstream Buffer */ ++ if (ctx->bit_stream_buf) ++ nx_free_memory(ctx->bit_stream_buf); ++ ++ if (ctx->instance_buf) ++ nx_free_memory(ctx->instance_buf); ++ ++ return 0; ++} ++ ++void nx_vpu_enc_close_instance(struct nx_vpu_ctx *ctx) ++{ ++ struct nx_vpu_v4l2 *dev = ctx->dev; ++ ++ if (ctx->hInst) { ++ int ret = NX_VpuEncClose(ctx->hInst, (void*)&dev->vpu_event_present); ++ if (ret != 0) ++ NX_ErrMsg(("Failed to return an instance.\n")); ++ free_encoder_memory(ctx); ++ --dev->cur_num_instance; ++ ctx->hInst = NULL; ++ } ++} ++ +diff --git a/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c b/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_vpu_encoder.c +@@ -0,0 +1,995 @@ ++/* ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * Author: Seonghee, Kim ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef UNUSED ++#define UNUSED(p) ((void)(p)) ++#endif ++ ++#include ++ ++#include "vpu_hw_interface.h" /* Register Access */ ++#include "nx_vpu_api.h" ++#include "nx_vpu_gdi.h" ++ ++ ++#define DBG_REGISTER 0 ++#define DBG_ES_ADDR 0 ++#define INFO_MSG 0 ++ ++ ++/*--------------------------------------------------------------------------- */ ++/* Define Static Functions */ ++static void VPU_EncDefaultParam(struct vpu_enc_info *pInfo); ++static int VPU_EncSeqCommand(struct nx_vpu_codec_inst *pInst); ++static int VPU_EncSetFrameBufCommand(struct nx_vpu_codec_inst ++ *pInst, uint32_t sramAddr, uint32_t sramSize); ++static int VPU_EncOneFrameCommand(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_run_frame_arg *runArg); ++static int VPU_EncChangeParameterCommand(struct nx_vpu_codec_inst ++ *pInst, struct vpu_enc_chg_para_arg *chgArg); ++static int VPU_EncGetHeaderCommand(struct nx_vpu_codec_inst *pInst, ++ unsigned int headerType, void **ptr, int *size); ++static int VPU_EncCloseCommand(struct nx_vpu_codec_inst *pInst, ++ void *vpu_event_present); ++ ++ ++/*---------------------------------------------------------------------------- ++ * Encoder APIs ++ */ ++ ++int NX_VpuEncOpen(struct vpu_open_arg *pOpenArg, void *devHandle, ++ struct nx_vpu_codec_inst **ppInst) ++{ ++ struct vpu_enc_info *pEncInfo; ++ struct nx_vpu_codec_inst *hInst = 0; ++ ++ *ppInst = 0; ++ if (!NX_VpuIsInitialized()) ++ return VPU_RET_ERR_INIT; ++ ++ hInst = NX_VpuGetInstance(pOpenArg->instIndex); ++ if (!hInst) ++ return VPU_RET_ERR_INST; ++ ++ if (CODEC_STD_AVC == pOpenArg->codecStd) { ++ hInst->codecMode = AVC_ENC; ++ hInst->auxMode = 0; ++ } else if (CODEC_STD_MPEG4 == pOpenArg->codecStd) { ++ hInst->codecMode = MP4_ENC; ++ hInst->auxMode = 0; ++ } else if (CODEC_STD_H263 == pOpenArg->codecStd) { ++ hInst->codecMode = MP4_ENC; ++ hInst->auxMode = 1; ++ } else if (CODEC_STD_MJPG == pOpenArg->codecStd) { ++ hInst->codecMode = MJPG_ENC; ++ hInst->auxMode = 0; ++ } else { ++ NX_ErrMsg(("NX_VpuEncOpen() failed!!!\n")); ++ NX_ErrMsg(("Cannot support codec standard(%d)\n", ++ pOpenArg->codecStd)); ++ return VPU_RET_ERR_PARAM; ++ } ++ ++ NX_DrvMemset(&hInst->codecInfo, 0, sizeof(hInst->codecInfo)); ++ ++ hInst->inUse = 1; ++ hInst->instIndex = pOpenArg->instIndex; ++ hInst->devHandle = devHandle; ++ ++ hInst->instBufPhyAddr = (uint64_t)pOpenArg->instanceBuf.phyAddr; ++ ++ pEncInfo = &hInst->codecInfo.encInfo; ++ pEncInfo->codecStd = pOpenArg->codecStd; ++ ++ VPU_EncDefaultParam(pEncInfo); ++ ++ *ppInst = hInst; ++ return VPU_RET_OK; ++} ++ ++int NX_VpuEncClose(struct nx_vpu_codec_inst *pInst, void *vpu_event_present) ++{ ++ enum nx_vpu_ret ret; ++ ++ if (MJPG_ENC == pInst->codecMode) ++ return VPU_RET_OK; ++ ++ ret = VPU_EncCloseCommand(pInst, vpu_event_present); ++ if (ret != VPU_RET_OK) ++ NX_ErrMsg(("NX_VpuEncClose() failed.(%d)\n", ret)); ++ ++ return ret; ++} ++ ++int NX_VpuEncSetSeqParam(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_seq_arg *pSeqArg) ++{ ++ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; ++ ++ pEncInfo->srcWidth = pSeqArg->srcWidth; ++ pEncInfo->srcHeight = pSeqArg->srcHeight; ++ pEncInfo->encWidth = pSeqArg->srcWidth; ++ pEncInfo->encHeight = pSeqArg->srcHeight; ++ pEncInfo->gopSize = pSeqArg->gopSize; ++ pEncInfo->frameRateNum = pSeqArg->frameRateNum; ++ pEncInfo->frameRateDen = pSeqArg->frameRateDen; ++ ++ pEncInfo->rcEnable = (pSeqArg->bitrate) ? (1) : (0); ++ pEncInfo->bitRate = (pSeqArg->bitrate/1024)&0x7FFF; ++ pEncInfo->userQpMax = pSeqArg->maxQP; ++ pEncInfo->enableAutoSkip = !pSeqArg->disableSkip; ++ pEncInfo->initialDelay = pSeqArg->initialDelay; ++ pEncInfo->vbvBufSize = pSeqArg->vbvBufferSize; ++ pEncInfo->userGamma = pSeqArg->gammaFactor; ++ pEncInfo->frameQp = pSeqArg->initQP; ++ ++ pEncInfo->MESearchRange = pSeqArg->searchRange; ++ pEncInfo->intraRefresh = pSeqArg->intraRefreshMbs; ++ ++ pEncInfo->cbcrInterleave = pSeqArg->chromaInterleave; ++ pEncInfo->cbcrInterleaveRefFrame = pSeqArg->refChromaInterleave; ++ ++ pEncInfo->rotateAngle = pSeqArg->rotAngle / 90; ++ pEncInfo->mirrorDirection = pSeqArg->mirDirection; ++ ++ pEncInfo->strmBufVirAddr = pSeqArg->strmBufVirAddr; ++ pEncInfo->strmBufPhyAddr = pSeqArg->strmBufPhyAddr; ++ pEncInfo->strmBufSize = pSeqArg->strmBufSize; ++ ++ pEncInfo->jpegQuality = pSeqArg->quality; ++ ++ if (pSeqArg->annexFlg) { ++ pEncInfo->enc_codec_para.h263EncParam.h263AnnexJEnable = 1; ++ pEncInfo->enc_codec_para.h263EncParam.h263AnnexTEnable = 1; ++ } ++ ++ if (pSeqArg->enableAUDelimiter) ++ pEncInfo->enc_codec_para.avcEncParam.audEnable = 1; ++ ++ NX_DbgMsg(INFO_MSG, ("NX_VpuEncSetSeqParam() information\n")); ++ NX_DbgMsg(INFO_MSG, ("Reloution : %d x %d\n", ++ pEncInfo->srcWidth, pEncInfo->srcHeight)); ++ NX_DbgMsg(INFO_MSG, ("Fps : %d/%d\n", ++ pEncInfo->frameRateNum, pEncInfo->frameRateDen)); ++ NX_DbgMsg(INFO_MSG, ("Target bitrate : %d kbps\n", pEncInfo->bitRate)); ++ NX_DbgMsg(INFO_MSG, ("GOP : %d\n", pEncInfo->gopSize)); ++ NX_DbgMsg(INFO_MSG, ("Max QP : %d\n", pEncInfo->userQpMax)); ++ NX_DbgMsg(INFO_MSG, ("SR : %d\n", pEncInfo->MESearchRange)); ++ NX_DbgMsg(INFO_MSG, ("Stream_buffer : 0x%llx, 0x%llx))\n", ++ pEncInfo->strmBufPhyAddr, pEncInfo->strmBufVirAddr)); ++ ++ if (CODEC_STD_MJPG == pEncInfo->codecStd) { ++ struct enc_jpeg_info *pJpgInfo = ++ &pEncInfo->enc_codec_para.jpgEncInfo; ++ ++ if (0 != pEncInfo->rotateAngle) { ++ pJpgInfo->rotationEnable = 1; ++ pJpgInfo->rotationAngle = pEncInfo->rotateAngle; ++ } ++ ++ if (0 != pEncInfo->mirrorDirection) { ++ pJpgInfo->mirrorEnable = 1; ++ pJpgInfo->mirrorDirection = pEncInfo->mirrorDirection; ++ } ++ ++ if (pSeqArg->quality == 0 || pSeqArg->quality < 0 || ++ pSeqArg->quality > 100) ++ pEncInfo->jpegQuality = 90; ++ else ++ pEncInfo->jpegQuality = pSeqArg->quality; ++ ++ pJpgInfo->format = pSeqArg->imgFormat; ++ pJpgInfo->picWidth = pEncInfo->srcWidth; ++ pJpgInfo->picHeight = pEncInfo->srcHeight; ++ ++ return VPU_RET_OK; ++ } ++ ++ return VPU_EncSeqCommand(pInst); ++} ++ ++/* Frame Buffer Address Allocation */ ++int NX_VpuEncSetFrame(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_set_frame_arg *pFrmArg) ++{ ++ int i; ++ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; ++ ++ if (CODEC_STD_MJPG == pEncInfo->codecStd) ++ return VPU_RET_OK; ++ ++ pEncInfo->minFrameBuffers = pFrmArg->numFrameBuffer; ++ for (i = 0 ; i < pEncInfo->minFrameBuffers ; i++) ++ pEncInfo->frameBuffer[i] = pFrmArg->frameBuffer[i]; ++ ++ pEncInfo->subSampleAPhyAddr = pFrmArg->subSampleBuffer[0].phyAddr; ++ pEncInfo->subSampleBPhyAddr = pFrmArg->subSampleBuffer[1].phyAddr; ++ ++ return VPU_EncSetFrameBufCommand(pInst, pFrmArg->sramAddr, ++ pFrmArg->sramSize); ++} ++ ++int NX_VpuEncGetHeader(struct nx_vpu_codec_inst *pInst, ++ union vpu_enc_get_header_arg *pHeader) ++{ ++ enum nx_vpu_ret ret = VPU_RET_OK; ++ void *ptr; ++ int size; ++ ++ if (AVC_ENC == pInst->codecMode) { ++ /* SPS */ ++ ret = VPU_EncGetHeaderCommand(pInst, SPS_RBSP, &ptr, &size); ++ if (ret != VPU_RET_OK) { ++ NX_ErrMsg(("NX_VpuEncGetHeader() SPS_RBSP Error!\n")); ++ goto GET_HEADER_EXIT; ++ } ++ NX_DrvMemcpy(pHeader->avcHeader.spsData, ptr, size); ++ pHeader->avcHeader.spsSize = size; ++ /* PPS */ ++ ret = VPU_EncGetHeaderCommand(pInst, PPS_RBSP, &ptr, &size); ++ if (ret != VPU_RET_OK) { ++ NX_ErrMsg(("NX_VpuEncGetHeader() PPS_RBSP Error!\n")); ++ goto GET_HEADER_EXIT; ++ } ++ NX_DrvMemcpy(pHeader->avcHeader.ppsData, ptr, size); ++ pHeader->avcHeader.ppsSize = size; ++ } else if (MP4_ENC == pInst->codecMode) { ++ ret = VPU_EncGetHeaderCommand(pInst, VOS_HEADER, &ptr, &size); ++ /* VOS */ ++ if (ret != VPU_RET_OK) { ++ NX_ErrMsg(("NX_VpuEncGetHeader() VOS_HEADER Error!\n")); ++ goto GET_HEADER_EXIT; ++ } ++ NX_DrvMemcpy(pHeader->mp4Header.vosData, ptr, size); ++ pHeader->mp4Header.vosSize = size; ++ /* VOL */ ++ ret = VPU_EncGetHeaderCommand(pInst, VOL_HEADER, &ptr, &size); ++ if (ret != VPU_RET_OK) { ++ NX_ErrMsg(("NX_VpuEncGetHeader() VOL_HEADER Error!\n")); ++ goto GET_HEADER_EXIT; ++ } ++ NX_DrvMemcpy(pHeader->mp4Header.volData, ptr, size); ++ pHeader->mp4Header.volSize = size; ++ } ++ ++GET_HEADER_EXIT: ++ return ret; ++} ++ ++int NX_VpuEncRunFrame(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_run_frame_arg *pRunArg) ++{ ++ if (pInst->codecMode != MJPG_ENC) ++ return VPU_EncOneFrameCommand(pInst, pRunArg); ++ else ++ return JPU_EncRunFrame(pInst, pRunArg); ++} ++ ++int NX_VpuEncChgParam(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_chg_para_arg *pChgArg) ++{ ++ if (pInst->codecMode != MJPG_ENC) ++ return VPU_EncChangeParameterCommand(pInst, pChgArg); ++ else ++ return -1; ++} ++ ++ ++/*--------------------------------------------------------------------------- ++ * Encoder Specific Static Functions ++ */ ++ ++static void VPU_EncDefaultParam(struct vpu_enc_info *pEncInfo) ++{ ++ /* Set Default Frame Rate */ ++ pEncInfo->frameRateNum = 30; ++ pEncInfo->frameRateDen = 1; ++ ++ /* Set Slice Mode */ ++ pEncInfo->sliceMode = 0; /* one slice per picture */ ++ pEncInfo->sliceSizeMode = 0; ++ pEncInfo->sliceSize = 0; ++ ++ /* Set GOP Size */ ++ pEncInfo->gopSize = 30; ++ ++ /* Rate Control Related */ ++ pEncInfo->rcEnable = 0; ++ pEncInfo->intraRefresh = 0; /* Disalbe Intra Refresh */ ++ pEncInfo->rcIntraQp = -1; /* Disable */ ++ ++ pEncInfo->bwbEnable = VPU_ENABLE_BWB; ++ pEncInfo->cbcrInterleave = CBCR_INTERLEAVE; ++ pEncInfo->cbcrInterleaveRefFrame = ENC_FRAME_BUF_CBCR_INTERLEAVE; ++ pEncInfo->frameEndian = VPU_FRAME_ENDIAN; ++ ++ pEncInfo->rcIntervalMode = 0; /* Frame Mode */ ++ pEncInfo->rcIntraCostWeigth = 400; ++ pEncInfo->enableAutoSkip = 0; ++ pEncInfo->initialDelay = 0; ++ pEncInfo->vbvBufSize = 0; ++ ++ /* (0*32768 < gamma < 1*32768) */ ++ pEncInfo->userGamma = (unsigned int)(0.75*32768); ++ ++ if (CODEC_STD_AVC == pEncInfo->codecStd) { ++ struct enc_avc_param *pAvcParam = ++ &pEncInfo->enc_codec_para.avcEncParam; ++ ++ pAvcParam->chromaQpOffset = 0; ++ pAvcParam->constrainedIntraPredFlag = 0; ++ pAvcParam->disableDeblk = 0; ++ pAvcParam->deblkFilterOffsetAlpha = 0; ++ pAvcParam->audEnable = 0; ++ ++ pEncInfo->userQpMax = 51; ++ } else if (CODEC_STD_MPEG4 == pEncInfo->codecStd) { ++ struct enc_mp4_param *pMp4Param = ++ &pEncInfo->enc_codec_para.mp4EncParam; ++ pMp4Param->mp4DataPartitionEnable = 0; ++ pMp4Param->mp4ReversibleVlcEnable = 0; ++ pMp4Param->mp4IntraDcVlcThr = 0; ++ pMp4Param->mp4HecEnable = 0; ++ pMp4Param->mp4Verid = 2; ++ ++ pEncInfo->userQpMax = 31; ++ } else if (CODEC_STD_H263 == pEncInfo->codecStd) { ++ struct enc_h263_param *pH263Param = ++ &pEncInfo->enc_codec_para.h263EncParam; ++ pH263Param->h263AnnexIEnable = 0; ++ pH263Param->h263AnnexJEnable = 0; ++ pH263Param->h263AnnexKEnable = 0; ++ pH263Param->h263AnnexTEnable = 0; ++ ++ pEncInfo->userQpMax = 31; ++ } else if (CODEC_STD_MJPG == pEncInfo->codecStd) { ++ struct enc_jpeg_info *pJpgInfo = ++ &pEncInfo->enc_codec_para.jpgEncInfo; ++ pJpgInfo->format = IMG_FORMAT_420; ++ pJpgInfo->frameIdx = 0; ++ pJpgInfo->rstIntval = 60; ++ } ++ ++ /* Motion Estimation */ ++ pEncInfo->MEUseZeroPmv = 0; ++ pEncInfo->MESearchRange = 1; ++ pEncInfo->MEBlockMode = 0; /* Use All Macro Block Type */ ++} ++ ++static int VPU_EncSeqCommand(struct nx_vpu_codec_inst *pInst) +{ -+ struct vb2_queue *vq = vb->vb2_queue; -+ struct nx_vpu_ctx *ctx = vq->drv_priv; -+ struct nx_vpu_v4l2 *dev = ctx->dev; -+ unsigned long flags; -+ struct nx_vpu_buf *buf = vb_to_vpu_buf(vb); -+ -+ FUNC_IN(); ++ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; ++ unsigned int tmpData; + -+ spin_lock_irqsave(&dev->irqlock, flags); ++ /* Write Bitstream Buffer Information */ ++ VpuWriteReg(CMD_ENC_SEQ_BB_START, pEncInfo->strmBufPhyAddr); ++ VpuWriteReg(CMD_ENC_SEQ_BB_SIZE, pEncInfo->strmBufSize / 1024); + -+ if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { ++ /* Set Source Image Information */ ++ if (90 == pEncInfo->rotateAngle || 270 == pEncInfo->rotateAngle) ++ tmpData = (pEncInfo->srcHeight << 16) | pEncInfo->srcWidth; ++ else ++ tmpData = (pEncInfo->srcWidth << 16) | pEncInfo->srcHeight; + -+ NX_DbgMsg(INFO_MSG, ("adding to dst: %p (%08lx)\n", vb, -+ (unsigned long)nx_vpu_mem_plane_addr(vb, 0))); ++ VpuWriteReg(CMD_ENC_SEQ_SRC_SIZE, tmpData); ++ VpuWriteReg(CMD_ENC_SEQ_SRC_F_RATE, (pEncInfo->frameRateNum) | ++ ((pEncInfo->frameRateDen-1) << 16)); + -+ list_add_tail(&buf->list, &ctx->strm_queue); -+ ctx->strm_queue_cnt++; -+ } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { -+ NX_DbgMsg(INFO_MSG, ("adding to src: %p(%08lx, %08lx)\n", -+ vb, (unsigned long)nx_vpu_mem_plane_addr(vb, 0), -+ (unsigned long)nx_vpu_mem_plane_addr(vb, 1))); ++ if (pEncInfo->codecStd == CODEC_STD_MPEG4) { ++ struct enc_mp4_param *pMp4Param = ++ &pEncInfo->enc_codec_para.mp4EncParam; ++ VpuWriteReg(CMD_ENC_SEQ_COD_STD, 3); ++ tmpData = pMp4Param->mp4IntraDcVlcThr << 2 | ++ pMp4Param->mp4ReversibleVlcEnable << 1 | ++ pMp4Param->mp4DataPartitionEnable; ++ tmpData |= ((pMp4Param->mp4HecEnable > 0) ? 1:0)<<5; ++ tmpData |= ((pMp4Param->mp4Verid == 2) ? 0:1) << 6; ++ VpuWriteReg(CMD_ENC_SEQ_MP4_PARA, tmpData); ++ } else if (pEncInfo->codecStd == CODEC_STD_H263) { ++ struct enc_h263_param *pH263Param = ++ &pEncInfo->enc_codec_para.h263EncParam; + -+ list_add_tail(&buf->list, &ctx->img_queue); -+ ctx->img_queue_cnt++; -+ } else { -+ NX_ErrMsg(("unsupported buffer type (%d)\n", vq->type)); ++ VpuWriteReg(CMD_ENC_SEQ_COD_STD, 11); ++ tmpData = pH263Param->h263AnnexIEnable << 3 | ++ pH263Param->h263AnnexJEnable << 2 | ++ pH263Param->h263AnnexKEnable << 1| ++ pH263Param->h263AnnexTEnable; ++ VpuWriteReg(CMD_ENC_SEQ_263_PARA, tmpData); ++ } else if (pEncInfo->codecStd == CODEC_STD_AVC) { ++ struct enc_avc_param *pAvcParam = ++ &pEncInfo->enc_codec_para.avcEncParam; ++ VpuWriteReg(CMD_ENC_SEQ_COD_STD, 0x0); ++ tmpData = (pAvcParam->deblkFilterOffsetBeta & 15) << 12 ++ | (pAvcParam->deblkFilterOffsetAlpha & 15) << 8 ++ | pAvcParam->disableDeblk << 6 ++ | pAvcParam->constrainedIntraPredFlag << 5 ++ | (pAvcParam->chromaQpOffset & 31); ++ VpuWriteReg(CMD_ENC_SEQ_264_PARA, tmpData); + } + -+ spin_unlock_irqrestore(&dev->irqlock, flags); -+ -+ if (nx_vpu_enc_ctx_ready(ctx)) -+ nx_vpu_enc_try_run(ctx); -+} -+ -+static struct vb2_ops nx_vpu_enc_qops = { -+ .queue_setup = nx_vpu_queue_setup, -+ .wait_prepare = nx_vpu_unlock, -+ .wait_finish = nx_vpu_lock, -+ .buf_prepare = nx_vpu_buf_prepare, -+ .start_streaming = nx_vpu_enc_start_streaming, -+ .stop_streaming = nx_vpu_enc_stop_streaming, -+ .buf_queue = nx_vpu_enc_buf_queue, -+}; ++ /* Slice Mode */ ++ tmpData = pEncInfo->sliceSize << 2 | pEncInfo->sliceSizeMode << 1 ++ | pEncInfo->sliceMode; ++ VpuWriteReg(CMD_ENC_SEQ_SLICE_MODE, tmpData); + -+/* -------------------------------------------------------------------------- */ ++ /* Write GOP Size */ ++ if (pEncInfo->rcEnable) ++ VpuWriteReg(CMD_ENC_SEQ_GOP_NUM, pEncInfo->gopSize); ++ else ++ VpuWriteReg(CMD_ENC_SEQ_GOP_NUM, 0); + ++ /* Rate Control */ ++ if (pEncInfo->rcEnable) { ++ tmpData = (!pEncInfo->enableAutoSkip) << 31 | ++ pEncInfo->initialDelay << 16 | pEncInfo->bitRate<<1 | 1; ++ VpuWriteReg(CMD_ENC_SEQ_RC_PARA, tmpData); ++ } else { ++ VpuWriteReg(CMD_ENC_SEQ_RC_PARA, 0); ++ } + -+const struct v4l2_ioctl_ops *get_enc_ioctl_ops(void) -+{ -+ return &nx_vpu_enc_ioctl_ops; -+}; ++ VpuWriteReg(CMD_ENC_SEQ_RC_BUF_SIZE, pEncInfo->vbvBufSize); ++ VpuWriteReg(CMD_ENC_SEQ_INTRA_REFRESH, pEncInfo->intraRefresh); + -+int nx_vpu_enc_open(struct nx_vpu_ctx *ctx) -+{ -+ int ret = 0; ++ if (pEncInfo->rcIntraQp >= 0) { ++ tmpData = (1 << 5); ++ VpuWriteReg(CMD_ENC_SEQ_INTRA_QP, pEncInfo->rcIntraQp); ++ } else { ++ tmpData = 0; ++ VpuWriteReg(CMD_ENC_SEQ_INTRA_QP, (unsigned int)-1); ++ } + -+ FUNC_IN(); ++ if (pEncInfo->codecStd == CODEC_STD_AVC) ++ tmpData |= (pEncInfo->enc_codec_para.avcEncParam.audEnable<<2); + -+ /* Init videobuf2 queue for INPUT */ -+ ctx->vq_img.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; -+ ctx->vq_img.drv_priv = ctx; -+ ctx->vq_img.lock = &ctx->dev->dev_mutex; -+ ctx->vq_img.buf_struct_size = sizeof(struct nx_vpu_buf); -+ ctx->vq_img.io_modes = VB2_USERPTR | VB2_DMABUF; -+ /* ctx->vq_strm.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; */ -+ ctx->vq_img.ops = &nx_vpu_enc_qops; -+ ctx->vq_img.mem_ops = &vb2_dma_contig_memops; -+ /*ctx->vq_img.allow_zero_byteused = 1; */ -+ ctx->vq_img.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; -+ ctx->vq_img.dev = &ctx->dev->plat_dev->dev; -+ ret = vb2_queue_init(&ctx->vq_img); -+ if (ret) { -+ NX_ErrMsg(("Failed to initialize videobuf2 queue(output)\n")); -+ return ret; ++ if (pEncInfo->userQpMax >= 0) { ++ tmpData |= (1<<6); ++ VpuWriteReg(CMD_ENC_SEQ_RC_QP_MAX, pEncInfo->userQpMax); ++ } else { ++ VpuWriteReg(CMD_ENC_SEQ_RC_QP_MAX, 0); + } + -+ /* Init videobuf2 queue for OUTPUT */ -+ ctx->vq_strm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; -+ ctx->vq_strm.drv_priv = ctx; -+ ctx->vq_strm.lock = &ctx->dev->dev_mutex; -+ ctx->vq_strm.buf_struct_size = sizeof(struct nx_vpu_buf); -+ ctx->vq_strm.io_modes = VB2_USERPTR | VB2_DMABUF; -+ /* ctx->vq_strm.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; */ -+ ctx->vq_strm.ops = &nx_vpu_enc_qops; -+ ctx->vq_strm.mem_ops = &vb2_dma_contig_memops; -+ ctx->vq_strm.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; -+ ctx->vq_strm.dev = &ctx->dev->plat_dev->dev; -+ ret = vb2_queue_init(&ctx->vq_strm); -+ if (ret) { -+ NX_ErrMsg(("Failed to initialize videobuf2 queue(capture)\n")); -+ return ret; ++ if (pEncInfo->userGamma >= 0) { ++ tmpData |= (1<<7); ++ VpuWriteReg(CMD_ENC_SEQ_RC_GAMMA, pEncInfo->userGamma); ++ } else { ++ VpuWriteReg(CMD_ENC_SEQ_RC_GAMMA, 0); + } + -+ return 0; -+} ++ VpuWriteReg(CMD_ENC_SEQ_OPTION, tmpData); + -+int vpu_enc_open_instance(struct nx_vpu_ctx *ctx) -+{ -+ struct nx_vpu_v4l2 *dev = ctx->dev; -+ struct nx_vpu_codec_inst *hInst = 0; -+ struct vpu_open_arg openArg; -+ int ret; ++ VpuWriteReg(CMD_ENC_SEQ_RC_INTERVAL_MODE, (pEncInfo->mbInterval<<2) ++ | pEncInfo->rcIntervalMode); ++ VpuWriteReg(CMD_ENC_SEQ_INTRA_WEIGHT, pEncInfo->rcIntraCostWeigth); ++ VpuWriteReg(CMD_ENC_SEQ_ME_OPTION, (pEncInfo->MEBlockMode << 3) ++ | (pEncInfo->MEUseZeroPmv << 2) | pEncInfo->MESearchRange); + -+ FUNC_IN(); ++ VpuWriteReg(BIT_WR_PTR, pEncInfo->strmBufPhyAddr); ++ VpuWriteReg(BIT_RD_PTR, pEncInfo->strmBufPhyAddr); + -+ memset(&openArg, 0, sizeof(openArg)); ++ tmpData = 0; ++ tmpData |= (pEncInfo->bwbEnable<<12)|(pEncInfo->cbcrInterleave<<2); ++ tmpData |= pEncInfo->frameEndian; ++ VpuWriteReg(BIT_FRAME_MEM_CTRL, tmpData); + -+ switch (ctx->strm_fmt->fourcc) { -+ case V4L2_PIX_FMT_MPEG4: -+ ctx->codec_mode = CODEC_STD_MPEG4; -+ break; -+ case V4L2_PIX_FMT_H264: -+ ctx->codec_mode = CODEC_STD_AVC; -+ break; -+ case V4L2_PIX_FMT_H263: -+ ctx->codec_mode = CODEC_STD_H263; -+ break; -+ case V4L2_PIX_FMT_MJPEG: -+ ctx->codec_mode = CODEC_STD_MJPG; -+ break; -+ default: -+ NX_ErrMsg(("Invalid codec type (%x)!!!\n", -+ ctx->strm_fmt->fourcc)); -+ goto err_exit; ++ /* Ring Buffer Disable */ ++ if (pEncInfo->ringBufferEnable == 0) { ++ /* Line Buffer Interrupt Enable */ ++ tmpData = (0x1<<6); ++ /* The value of 1 means that bitstream buffer is reset at every ++ picture encoding command. */ ++ tmpData |= (0x1<<5); ++ /* Enables dynamic picture stream buffer allocation in encoder ++ operations. */ ++ tmpData |= (0x1<<4); ++ tmpData |= VPU_STREAM_ENDIAN; ++ } else { ++ /* Ring Buffer Enabled */ ++ tmpData = (0x1<<3); ++ tmpData |= VPU_STREAM_ENDIAN; + } -+ openArg.codecStd = ctx->codec_mode; + -+ /* Allocate Instance Memory & Stream Buffer */ -+ ctx->instance_buf = nx_alloc_memory(&dev->plat_dev->dev, WORK_BUF_SIZE, -+ 4096); -+ if (ctx->instance_buf == NULL) { -+ NX_ErrMsg(("hinstance_buf allocation failed.\n")); -+ goto err_exit; -+ } ++ VpuWriteReg(BIT_BIT_STREAM_CTRL, tmpData); + -+ openArg.instanceBuf = *ctx->instance_buf; -+ openArg.instIndex = ctx->idx; -+ openArg.isEncoder = 1; ++#if (DBG_REGISTER) ++ { ++ int reg; + -+ ret = NX_VpuEncOpen(&openArg, dev, &hInst); -+ if ((VPU_RET_OK != ret) || (0 == hInst)) { -+ NX_ErrMsg(("Cannot open VPU Instance!!!\n")); -+ NX_ErrMsg((" codecStd=%d, is_encoder=%d, hInst=%p)\n", -+ openArg.codecStd, openArg.isEncoder, hInst)); -+ ret = -1; -+ goto err_exit; ++ NX_DbgMsg(DBG_REGISTER, ("[SEQ_INIT_Reg]\n")); ++ for (reg = 0x0 ; reg < 0x200 ; reg += 16) { ++ NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", ++ reg, VpuReadReg(BIT_BASE + reg), ++ VpuReadReg(BIT_BASE + reg + 4), ++ VpuReadReg(BIT_BASE + reg + 8), ++ VpuReadReg(BIT_BASE + reg + 12))); ++ } + } ++#endif + -+ ctx->hInst = (void *)hInst; -+ dev->cur_num_instance++; + -+ return ret; ++ VpuBitIssueCommand(pInst, SEQ_INIT); + -+err_exit: -+ if (ctx->instance_buf) -+ nx_free_memory(ctx->instance_buf); ++#if (DBG_REGISTER) ++ { ++ int reg; + -+ return ret; -+} ++ NX_DbgMsg(DBG_REGISTER, ("[SEQ_INIT_Reg]\n")); ++ for (reg = 0x0 ; reg < 0x200 ; reg += 16) { ++ NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", ++ reg, VpuReadReg(BIT_BASE + reg), ++ VpuReadReg(BIT_BASE + reg + 4), ++ VpuReadReg(BIT_BASE + reg + 8), ++ VpuReadReg(BIT_BASE + reg + 12))); ++ } ++ } ++#endif + -+static void get_stream_buffer(struct nx_vpu_ctx *ctx, -+ struct nx_memory_info *stream_buf) -+{ -+ struct nx_vpu_buf *dst_mb; ++ if (!VPU_WaitBitInterrupt(pInst->devHandle, VPU_DEC_TIMEOUT)) { ++ NX_ErrMsg(("VPU_EncSeqCommand() Failed. Timeout(%d)\n", ++ VPU_BUSY_CHECK_TIMEOUT)); ++ return VPU_RET_ERR_TIMEOUT; ++ } + -+ FUNC_IN(); ++ /* Get Encoder Frame Buffer Information */ ++ if (VpuReadReg(RET_ENC_SEQ_ENC_SUCCESS) & (1<<31)) ++ return VPU_RET_ERR_MEM_ACCESS; + -+ /* spin_lock_irqsave(&ctx->dev->irqlock, flags); */ ++ if (VpuReadReg(RET_ENC_SEQ_ENC_SUCCESS) == 0) ++ return VPU_RET_ERR_INIT; + -+ dst_mb = list_entry(ctx->strm_queue.next, struct nx_vpu_buf, list); ++ if (pInst->codecMode == MJPG_ENC) ++ pEncInfo->minFrameBuffers = 0; ++ else ++ /* reconstructed frame + reference frame + subsample */ ++ pEncInfo->minFrameBuffers = 2; + -+ stream_buf->phyAddr = nx_vpu_mem_plane_addr(&dst_mb->vb, 0); -+ stream_buf->size = vb2_plane_size(&dst_mb->vb, 0); -+#ifdef USE_ION_MEMORY -+ stream_buf->virAddr = (unsigned int)cma_get_virt(stream_buf->phyAddr, -+ stream_buf->size, 1); -+#else -+ stream_buf->virAddr = vb2_plane_vaddr(&dst_mb->vb, 0); -+#endif ++ pEncInfo->strmWritePrt = VpuReadReg(BIT_WR_PTR); ++ pEncInfo->strmEndFlag = VpuReadReg(BIT_BIT_STREAM_PARAM); + -+ /* spin_unlock_irqrestore(&ctx->dev->irqlock, flags); */ ++ NX_DbgMsg(INFO_MSG, ("VPU_EncSeqCommand() Success.\n")); ++ NX_DbgMsg(INFO_MSG, ("Writer Ptr = 0x%08x, Stream End Flag = %d\n", ++ pEncInfo->strmWritePrt, pEncInfo->strmEndFlag)); ++ ++ pInst->isInitialized = 1; ++ return VPU_RET_OK; +} + -+int vpu_enc_init(struct nx_vpu_ctx *ctx) ++static int VPU_EncSetFrameBufCommand(struct nx_vpu_codec_inst *pInst, ++ uint32_t sramAddr, uint32_t sramSize) +{ -+ struct vpu_enc_ctx *enc_ctx = &ctx->codec.enc; -+ struct vpu_enc_seq_arg *pSeqArg = &ctx->codec.enc.seq_para; -+ int ret = 0; ++ int i; ++ unsigned char frameAddr[22][3][4]; ++ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; ++ unsigned int frameBufStride = ((pEncInfo->srcWidth+15)&~15); ++ unsigned int val = 0; + -+ FUNC_IN(); ++ NX_DrvMemset(frameAddr, 0, sizeof(frameAddr)); + -+ if (ctx->hInst == NULL) { -+ NX_ErrMsg(("Err : vpu is not opened\n")); -+ return -EAGAIN; -+ } ++ /* Set Second AXI Memory (SRAM) Configuration */ ++ if (VPU_RET_OK != ConfigEncSecAXI(pEncInfo->codecStd, ++ &pEncInfo->sec_axi_info, pEncInfo->srcWidth, ++ pEncInfo->srcHeight, sramAddr, sramSize)) ++ return VPU_RET_ERR_SRAM; + -+ pSeqArg->strmBufPhyAddr = (uint64_t)ctx->bit_stream_buf->phyAddr; -+ pSeqArg->strmBufVirAddr = (unsigned long)ctx->bit_stream_buf->virAddr; -+ pSeqArg->strmBufSize = ctx->bit_stream_buf->size; ++ /* decoder(0), cbcr interleve(0), bypass(0), burst(0), merge(3), ++ maptype(linear), wayshape(15) */ ++ pEncInfo->cacheConfig = MaverickCache2Config(0, ++ pEncInfo->cbcrInterleaveRefFrame, 0, 0, 3, 0, 15); + -+ if ((pSeqArg->strmBufPhyAddr == 0) || (pSeqArg->strmBufSize == 0)) { -+ NX_ErrMsg(("stream buffer error(addr = %llx, size = %d)\n", -+ pSeqArg->strmBufPhyAddr, pSeqArg->strmBufSize)); -+ return -1; -+ } ++ SetTiledMapType(VPU_LINEAR_FRAME_MAP, frameBufStride, ++ pEncInfo->cbcrInterleaveRefFrame); + -+ if ((pSeqArg->srcWidth == 0) || (pSeqArg->srcWidth > 1920) || -+ (pSeqArg->srcHeight == 0) || (pSeqArg->srcHeight > 1088)) { -+ NX_ErrMsg(("resolution pamameter error(W = %d, H = %d)\n", -+ pSeqArg->srcWidth, pSeqArg->srcHeight)); -+ return -1; ++ if (pEncInfo->frameBufMapType) { ++ if (pEncInfo->frameBufMapType == VPU_TILED_FRAME_MB_RASTER_MAP ++ || pEncInfo->frameBufMapType == VPU_TILED_FIELD_MB_RASTER_MAP) ++ val |= (pEncInfo->cbcrInterleaveRefFrame<<11) | ++ (0x03<<9)|(IMG_FORMAT_420<<6); ++ else ++ val |= (pEncInfo->cbcrInterleaveRefFrame<<11) | ++ (0x02<<9)|(IMG_FORMAT_420<<6); + } + -+ if (ctx->codec_mode != CODEC_STD_MJPG) { -+ if (pSeqArg->bitrate) { -+ if (pSeqArg->gammaFactor == 0) -+ pSeqArg->gammaFactor = (int)(0.75 * 32768); -+ } else { -+ if (enc_ctx->userIQP == 0) -+ enc_ctx->userIQP = 26; -+ if (enc_ctx->userPQP == 0) -+ enc_ctx->userPQP = 26; -+ } -+ -+ if (ctx->codec_mode == CODEC_STD_AVC) { -+ if ((pSeqArg->maxQP > 51) || (pSeqArg->maxQP == 0)) -+ pSeqArg->maxQP = 51; -+ } else { -+ if ((pSeqArg->maxQP > 31) || (pSeqArg->maxQP == 0)) -+ pSeqArg->maxQP = 31; -+ -+ if (ctx->codec_mode == CODEC_STD_H263) -+ pSeqArg->searchRange = 3; -+ } -+ } else { -+ pSeqArg->frameRateNum = 1; -+ pSeqArg->frameRateDen = 1; -+ pSeqArg->gopSize = 1; ++ /* Interleave bit position is modified */ ++ val |= (pEncInfo->cbcrInterleaveRefFrame<<2); ++ val |= VPU_FRAME_ENDIAN; ++ VpuWriteReg(BIT_FRAME_MEM_CTRL, val); + -+ switch (ctx->img_fmt->fourcc) { -+ case V4L2_PIX_FMT_YUV420M: -+ pSeqArg->imgFormat = IMG_FORMAT_420; -+ pSeqArg->chromaInterleave = 0; -+ break; -+ case V4L2_PIX_FMT_YUV422M: -+ pSeqArg->imgFormat = IMG_FORMAT_422; -+ pSeqArg->chromaInterleave = 0; -+ break; -+ case V4L2_PIX_FMT_YUV444M: -+ pSeqArg->imgFormat = IMG_FORMAT_444; -+ pSeqArg->chromaInterleave = 0; -+ break; -+ case V4L2_PIX_FMT_GREY: -+ pSeqArg->imgFormat = IMG_FORMAT_400; -+ break; -+ case V4L2_PIX_FMT_NV12M: -+ pSeqArg->imgFormat = IMG_FORMAT_420; -+ pSeqArg->chromaInterleave = 1; -+ break; -+ case V4L2_PIX_FMT_NV16M: -+ pSeqArg->imgFormat = IMG_FORMAT_422; -+ pSeqArg->chromaInterleave = 1; -+ break; -+ case V4L2_PIX_FMT_NV24M: -+ pSeqArg->imgFormat = IMG_FORMAT_444; -+ pSeqArg->chromaInterleave = 1; -+ break; -+ default: -+ NX_ErrMsg(("Color format is not supported!!")); -+ return -EINVAL; -+ } -+ } ++ /* Let the decoder know the addresses of the frame buffers. */ ++ for (i = 0; i < pEncInfo->minFrameBuffers; i++) { ++ struct nx_vid_memory_info *frameBuffer = ++ &pEncInfo->frameBuffer[i]; + -+ ret = NX_VpuEncSetSeqParam(ctx->hInst, pSeqArg); -+ if (ret != VPU_RET_OK) { -+ NX_ErrMsg(("NX_VpuEncSetSeqParam() failed.(ErrorCode=%d)\n", -+ ret)); -+ return ret; ++ /* Y */ ++ frameAddr[i][0][0] = (frameBuffer->phyAddr[0] >> 24) & 0xFF; ++ frameAddr[i][0][1] = (frameBuffer->phyAddr[0] >> 16) & 0xFF; ++ frameAddr[i][0][2] = (frameBuffer->phyAddr[0] >> 8) & 0xFF; ++ frameAddr[i][0][3] = (frameBuffer->phyAddr[0] >> 0) & 0xFF; ++ /* Cb */ ++ frameAddr[i][1][0] = (frameBuffer->phyAddr[1] >> 24) & 0xFF; ++ frameAddr[i][1][1] = (frameBuffer->phyAddr[1] >> 16) & 0xFF; ++ frameAddr[i][1][2] = (frameBuffer->phyAddr[1] >> 8) & 0xFF; ++ frameAddr[i][1][3] = (frameBuffer->phyAddr[1] >> 0) & 0xFF; ++ /* Cr */ ++ frameAddr[i][2][0] = (frameBuffer->phyAddr[2] >> 24) & 0xFF; ++ frameAddr[i][2][1] = (frameBuffer->phyAddr[2] >> 16) & 0xFF; ++ frameAddr[i][2][2] = (frameBuffer->phyAddr[2] >> 8) & 0xFF; ++ frameAddr[i][2][3] = (frameBuffer->phyAddr[2] >> 0) & 0xFF; + } + -+ if (ctx->codec_mode != CODEC_STD_MJPG) { -+ struct vpu_enc_set_frame_arg frameArg; -+ union vpu_enc_get_header_arg *pHdrArg -+ = &ctx->codec.enc.seq_info; ++ swap_endian((unsigned char *)frameAddr, sizeof(frameAddr)); ++ NX_DrvMemcpy(pInst->paramVirAddr, frameAddr, sizeof(frameAddr)); + -+ /* We use always 2 frame */ -+ frameArg.numFrameBuffer = 2; ++ /* Tell the codec how much frame buffers were allocated. */ ++ VpuWriteReg(CMD_SET_FRAME_BUF_NUM, pEncInfo->minFrameBuffers); ++ VpuWriteReg(CMD_SET_FRAME_BUF_STRIDE, frameBufStride); ++ VpuWriteReg(CMD_SET_FRAME_AXI_BIT_ADDR, ++ pEncInfo->sec_axi_info.bufBitUse); ++ VpuWriteReg(CMD_SET_FRAME_AXI_IPACDC_ADDR, ++ pEncInfo->sec_axi_info.bufIpAcDcUse); ++ VpuWriteReg(CMD_SET_FRAME_AXI_DBKY_ADDR, ++ pEncInfo->sec_axi_info.bufDbkYUse); ++ VpuWriteReg(CMD_SET_FRAME_AXI_DBKC_ADDR, ++ pEncInfo->sec_axi_info.bufDbkCUse); ++ VpuWriteReg(CMD_SET_FRAME_AXI_OVL_ADDR, ++ pEncInfo->sec_axi_info.bufOvlUse); ++ VpuWriteReg(CMD_SET_FRAME_CACHE_CONFIG, ++ pEncInfo->cacheConfig); + -+ frameArg.frameBuffer[0] = *enc_ctx->ref_recon_buf[0]; -+ frameArg.frameBuffer[1] = *enc_ctx->ref_recon_buf[1]; -+ frameArg.subSampleBuffer[0] = *enc_ctx->sub_sample_buf[0]; -+ frameArg.subSampleBuffer[1] = *enc_ctx->sub_sample_buf[1]; ++ /* Set Sub-Sampling buffer for ME-Reference and DBK-Reconstruction */ ++ /* BPU will swap below two buffer internally every pic by pic */ ++ VpuWriteReg(CMD_SET_FRAME_SUBSAMP_A, pEncInfo->subSampleAPhyAddr); ++ VpuWriteReg(CMD_SET_FRAME_SUBSAMP_B, pEncInfo->subSampleBPhyAddr); + -+ /* data partition mode always disabled (for MPEG4) */ -+ frameArg.dataPartitionBuffer.phyAddr = 0; -+ frameArg.dataPartitionBuffer.virAddr = 0; ++ if (pInst->codecMode == MP4_ENC) { ++ /* MPEG4 Encoder Data-Partitioned bitstream temporal buffer */ ++ VpuWriteReg(CMD_SET_FRAME_DP_BUF_BASE, ++ pEncInfo->usbSampleDPPhyAddr); ++ VpuWriteReg(CMD_SET_FRAME_DP_BUF_SIZE, ++ pEncInfo->usbSampleDPSize); ++ } + -+ frameArg.sramAddr = ctx->dev->sram_base_addr; -+ frameArg.sramSize = ctx->dev->sram_size; ++#if (DBG_REGISTER) ++ { ++ int reg; + -+ ret = NX_VpuEncSetFrame(ctx->hInst, &frameArg); -+ if (ret != VPU_RET_OK) { -+ NX_ErrMsg(("NX_VpuEncSetFrame() is failed!(ret = %d\n", -+ ret)); -+ goto ERROR_EXIT; ++ NX_DbgMsg(DBG_REGISTER, ("[ENC_SET_FRM_BUF_Reg]\n")); ++ for (reg = 0x180 ; reg < 0x200 ; reg += 16) { ++ NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", ++ reg, VpuReadReg(BIT_BASE + reg), ++ VpuReadReg(BIT_BASE + reg + 4), ++ VpuReadReg(BIT_BASE + reg + 8), ++ VpuReadReg(BIT_BASE + reg + 12))); + } ++ } ++#endif + -+ ret = NX_VpuEncGetHeader(ctx->hInst, pHdrArg); -+ if (ret != VPU_RET_OK) { -+ NX_ErrMsg(("NX_VpuEncGetHeader() is failed!(ret = %d\n", -+ ret)); -+ goto ERROR_EXIT; -+ } ++ VpuBitIssueCommand(pInst, SET_FRAME_BUF); ++ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, ++ BIT_BUSY_FLAG)) { ++ NX_ErrMsg(("VPU_EncSetFrameBuffer() Failed. Timeout(%d)\n", ++ VPU_BUSY_CHECK_TIMEOUT)); ++ return VPU_RET_ERR_TIMEOUT; + } + -+ enc_ctx->gop_frm_cnt = 0; ++ if (VpuReadReg(RET_SET_FRAME_SUCCESS) & (1<<31)) ++ return VPU_RET_ERR_MEM_ACCESS; + -+ERROR_EXIT: -+ return ret; ++ return VPU_RET_OK; +} + -+void vpu_enc_get_seq_info(struct nx_vpu_ctx *ctx) ++static int VPU_EncGetHeaderCommand(struct nx_vpu_codec_inst *pInst, ++ unsigned int headerType, void **ptr, int *size) +{ -+ struct nx_memory_info stream_buf; -+ union vpu_enc_get_header_arg *pHdr = &ctx->codec.enc.seq_info; -+ void *pvDst; -+ -+ FUNC_IN(); -+ -+ if (ctx->codec_mode == CODEC_STD_AVC) { -+ get_stream_buffer(ctx, &stream_buf); -+ pvDst = stream_buf.virAddr; -+ -+ NX_DrvMemcpy(pvDst, (void *)pHdr->avcHeader.spsData, -+ pHdr->avcHeader.spsSize); -+ pvDst += pHdr->avcHeader.spsSize; -+ NX_DrvMemcpy(pvDst, (void *)pHdr->avcHeader.ppsData, -+ pHdr->avcHeader.ppsSize); -+ ctx->strm_size = pHdr->avcHeader.spsSize + -+ pHdr->avcHeader.ppsSize; -+ } else if (ctx->codec_mode == CODEC_STD_MPEG4) { -+ get_stream_buffer(ctx, &stream_buf); -+ pvDst = stream_buf.virAddr; ++ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; ++ int flag = 0; ++ unsigned int wdPtr, rdPtr; ++ int headerSize; + -+ NX_DrvMemcpy((void *)stream_buf.virAddr, -+ pHdr->mp4Header.vosData, pHdr->mp4Header.vosSize); -+ NX_DrvMemcpy((void *)stream_buf.virAddr + -+ pHdr->mp4Header.vosSize, pHdr->mp4Header.volData, -+ pHdr->mp4Header.volSize); -+ ctx->strm_size = pHdr->mp4Header.vosSize + -+ pHdr->mp4Header.volSize; -+ } else { -+ ctx->strm_size = 0; ++ if (pEncInfo->ringBufferEnable == 0) { ++ VpuWriteReg(CMD_ENC_HEADER_BB_START, pEncInfo->strmBufPhyAddr); ++ VpuWriteReg(CMD_ENC_HEADER_BB_SIZE, pEncInfo->strmBufSize/1024); + } + -+ { -+ struct nx_vpu_buf *dst_mb; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ctx->dev->irqlock, flags); ++ if (pInst->codecMode == AVC_ENC && headerType == SPS_RBSP) { ++ struct enc_avc_param *avcParam = ++ &pEncInfo->enc_codec_para.avcEncParam; ++ int CropH = 0, CropV = 0; + -+ dst_mb = list_entry(ctx->strm_queue.next, struct nx_vpu_buf, -+ list); -+ list_del(&dst_mb->list); -+ ctx->strm_queue_cnt--; ++ if (pEncInfo->encWidth & 0xF) { ++ flag = 1; ++ avcParam->cropRight = 16 - (pEncInfo->encWidth&0xF); ++ CropH = avcParam->cropLeft << 16; ++ CropH |= avcParam->cropRight; ++ } + -+ vb2_set_plane_payload(&dst_mb->vb, 0, ctx->strm_size); -+ vb2_buffer_done(&dst_mb->vb, VB2_BUF_STATE_DONE); ++ if (pEncInfo->encHeight & 0xF) { ++ flag = 1; ++ avcParam->cropBottom = 16 - (pEncInfo->encHeight&0xF); ++ CropV = avcParam->cropTop << 16; ++ CropV |= avcParam->cropBottom; ++ } + -+ spin_unlock_irqrestore(&ctx->dev->irqlock, flags); ++ VpuWriteReg(CMD_ENC_HEADER_FRAME_CROP_H, CropH); ++ VpuWriteReg(CMD_ENC_HEADER_FRAME_CROP_V, CropV); + } -+} + -+int vpu_enc_encode_frame(struct nx_vpu_ctx *ctx) -+{ -+ struct vpu_enc_ctx *enc_ctx = &ctx->codec.enc; -+ struct nx_vpu_v4l2 *dev = ctx->dev; -+ struct nx_vpu_codec_inst *hInst = ctx->hInst; -+ int ret = 0, i; -+ unsigned long flags; -+ struct nx_vpu_buf *mb_entry; -+ struct vpu_enc_run_frame_arg *pRunArg = &enc_ctx->run_info; -+ struct nx_memory_info stream_buf; -+ int num_planes; ++ /* 0: SPS, 1: PPS */ ++ VpuWriteReg(CMD_ENC_HEADER_CODE, headerType | (flag << 3)); + -+ FUNC_IN(); ++ VpuWriteReg(BIT_RD_PTR, pEncInfo->strmBufPhyAddr); ++ VpuWriteReg(BIT_WR_PTR, pEncInfo->strmBufPhyAddr); + -+ if (ctx->hInst == NULL) { -+ NX_ErrMsg(("Err : vpu is not opened\n")); -+ return -EAGAIN; -+ } ++#if (DBG_REGISTER) ++ { ++ int reg; + -+ if (enc_ctx->chg_para.chgFlg) { -+ ret = NX_VpuEncChgParam(hInst, &enc_ctx->chg_para); -+ if (ret != VPU_RET_OK) { -+ NX_ErrMsg(("NX_VpuEncChgParam() failed.(Err=%d)\n", -+ ret)); -+ return ret; ++ NX_DbgMsg(DBG_REGISTER, ("[ENC_HEADER_Reg]\n")); ++ for (reg = 0x180 ; reg < 0x200 ; reg += 16) { ++ NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", ++ reg, VpuReadReg(BIT_BASE + reg), ++ VpuReadReg(BIT_BASE + reg + 4), ++ VpuReadReg(BIT_BASE + reg + 8), ++ VpuReadReg(BIT_BASE + reg + 12))); + } ++ } ++#endif + -+ NX_DrvMemset(&enc_ctx->chg_para, 0, sizeof(enc_ctx->chg_para)); ++ VpuBitIssueCommand(pInst, ENCODE_HEADER); ++ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, ++ BIT_BUSY_FLAG)) ++ return VPU_RET_ERR_TIMEOUT; ++ ++ if (pEncInfo->ringBufferEnable == 0) { ++ rdPtr = pEncInfo->strmBufPhyAddr; ++ wdPtr = VpuReadReg(BIT_WR_PTR); ++ headerSize = wdPtr - rdPtr; ++ } else { ++ rdPtr = VpuReadReg(BIT_RD_PTR); ++ wdPtr = VpuReadReg(BIT_WR_PTR); ++ headerSize = wdPtr - rdPtr; + } + -+ get_stream_buffer(ctx, &stream_buf); ++ pEncInfo->strmWritePrt = wdPtr; ++ pEncInfo->strmReadPrt = rdPtr; + -+ spin_lock_irqsave(&dev->irqlock, flags); ++ *ptr = (void *)(unsigned long)pEncInfo->strmBufVirAddr; ++ *size = headerSize; + -+ mb_entry = list_entry(ctx->img_queue.next, struct nx_vpu_buf, list); ++ return VPU_RET_OK; ++} + -+ num_planes = ctx->useSingleBuf || ctx->img_fmt->singleBuffer ? 1 : -+ ctx->img_fmt->chromaInterleave ? 2 : 3; -+ for (i = 0 ; i < num_planes ; i++) { -+ pRunArg->inImgBuffer.phyAddr[i] = nx_vpu_mem_plane_addr( -+ &mb_entry->vb, i); -+ pRunArg->inImgBuffer.strideY = ctx->buf_y_width; -+ } ++static int VPU_EncOneFrameCommand(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_run_frame_arg *pRunArg) ++{ ++ unsigned int readPtr, writePtr; ++ int size, picFlag/*, frameIndex*/, val, reason; ++ unsigned int sliceNumber, picEncResult, picType; ++ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; + -+ if( num_planes == 1 && ctx->chroma_size > 0 ) { -+ pRunArg->inImgBuffer.phyAddr[1] = ctx->luma_size + -+ pRunArg->inImgBuffer.phyAddr[0]; -+ if (ctx->chromaInterleave == 0) -+ pRunArg->inImgBuffer.phyAddr[2] = ctx->chroma_size + -+ pRunArg->inImgBuffer.phyAddr[1]; -+ } ++ /* For Linear Frame Buffer Mode */ ++ VpuWriteReg(GDI_TILEDBUF_BASE, 0x00); + -+ spin_unlock_irqrestore(&dev->irqlock, flags); ++ /* Mirror/Rotate Mode */ ++ if (pEncInfo->rotateAngle == 0 && pEncInfo->mirrorDirection == 0) ++ VpuWriteReg(CMD_ENC_PIC_ROT_MODE, 0); ++ else ++ VpuWriteReg(CMD_ENC_PIC_ROT_MODE, (1 << 4) | ++ (pEncInfo->mirrorDirection << 2) | ++ (pEncInfo->rotateAngle)); + -+ dev->curr_ctx = ctx->idx; ++ /* If rate control is enabled, this register is ignored. ++ *(MPEG-4/H.263 : 1~31, AVC : 0 ~51) */ ++ VpuWriteReg(CMD_ENC_PIC_QS, pRunArg->quantParam); + -+ if (ctx->codec_mode != V4L2_PIX_FMT_MJPEG) { -+ if ((enc_ctx->gop_frm_cnt >= enc_ctx->seq_para.gopSize) || -+ (enc_ctx->gop_frm_cnt == 0)) -+ pRunArg->forceIPicture = 1; ++ if (pRunArg->forceSkipPicture) { ++ VpuWriteReg(CMD_ENC_PIC_OPTION, 1); ++ } else { ++ /* Registering Source Frame Buffer information */ ++ /* Hide GDI IF under FW level */ ++ if (pRunArg->inImgBuffer.planes == 2) ++ pEncInfo->cbcrInterleave = 1; + -+ enc_ctx->gop_frm_cnt = (pRunArg->forceIPicture) ? -+ (1) : (enc_ctx->gop_frm_cnt + 1); ++ VpuWriteReg(CMD_ENC_PIC_SRC_INDEX, 2); ++ VpuWriteReg(CMD_ENC_PIC_SRC_STRIDE, ++ pRunArg->inImgBuffer.strideY); ++ VpuWriteReg(CMD_ENC_PIC_SRC_ADDR_Y, ++ pRunArg->inImgBuffer.phyAddr[0]); ++ VpuWriteReg(CMD_ENC_PIC_SRC_ADDR_CB, ++ pRunArg->inImgBuffer.phyAddr[1]); ++ VpuWriteReg(CMD_ENC_PIC_SRC_ADDR_CR, ++ pRunArg->inImgBuffer.phyAddr[2]); ++ VpuWriteReg(CMD_ENC_PIC_OPTION, ++ (pRunArg->forceIPicture << 1 & 0x2)); + } + -+ ret = NX_VpuEncRunFrame(hInst, pRunArg); -+ if (ret != VPU_RET_OK) { -+ NX_ErrMsg(("NX_VpuEncRunFrame() failed.(ErrorCode=%d)\n", ret)); -+ return ret; ++ if (pEncInfo->ringBufferEnable == 0) { ++ VpuWriteReg(CMD_ENC_PIC_BB_START, pEncInfo->strmBufPhyAddr); ++ VpuWriteReg(CMD_ENC_PIC_BB_SIZE, pEncInfo->strmBufSize/1024); ++ VpuWriteReg(BIT_RD_PTR, pEncInfo->strmBufPhyAddr); + } + -+ memcpy(stream_buf.virAddr, -+ (void *)(unsigned long)pRunArg->outStreamAddr, -+ pRunArg->outStreamSize); -+ ctx->strm_size = pRunArg->outStreamSize; ++ val = 0; ++ val = ( ++ (pEncInfo->sec_axi_info.useBitEnable & 0x01)<<0 | ++ (pEncInfo->sec_axi_info.useIpEnable & 0x01)<<1 | ++ (pEncInfo->sec_axi_info.useDbkYEnable & 0x01)<<2 | ++ (pEncInfo->sec_axi_info.useDbkCEnable & 0x01)<<3 | + -+ spin_lock_irqsave(&dev->irqlock, flags); ++ (pEncInfo->sec_axi_info.useOvlEnable & 0x01)<<4 | ++ (pEncInfo->sec_axi_info.useBtpEnable & 0x01)<<5 | + -+ if (ctx->img_queue_cnt > 0) { -+ mb_entry = list_entry(ctx->img_queue.next, struct nx_vpu_buf, -+ list); -+ list_del(&mb_entry->list); -+ ctx->img_queue_cnt--; ++ (pEncInfo->sec_axi_info.useBitEnable & 0x01)<<8 | ++ (pEncInfo->sec_axi_info.useIpEnable & 0x01)<<9 | ++ (pEncInfo->sec_axi_info.useDbkYEnable & 0x01)<<10| ++ (pEncInfo->sec_axi_info.useDbkCEnable & 0x01)<<11| + -+ vb2_buffer_done(&mb_entry->vb, VB2_BUF_STATE_DONE); -+ } ++ (pEncInfo->sec_axi_info.useOvlEnable & 0x01)<<12| ++ (pEncInfo->sec_axi_info.useBtpEnable & 0x01)<<13); + -+ if (ctx->strm_size > 0) { -+ struct vb2_v4l2_buffer *vbuf; -+ mb_entry = list_entry(ctx->strm_queue.next, struct nx_vpu_buf, -+ list); ++ VpuWriteReg(BIT_AXI_SRAM_USE, val); + -+ list_del(&mb_entry->list); -+ ctx->strm_queue_cnt--; -+ vbuf = to_vb2_v4l2_buffer(&mb_entry->vb); ++ VpuWriteReg(BIT_WR_PTR, pEncInfo->strmBufPhyAddr); ++ VpuWriteReg(BIT_RD_PTR, pEncInfo->strmBufPhyAddr); ++ VpuWriteReg(BIT_BIT_STREAM_PARAM, pEncInfo->strmEndFlag); + -+ switch (pRunArg->frameType) { -+ case 0: -+ case 6: -+ vbuf->flags = V4L2_BUF_FLAG_KEYFRAME; -+ break; -+ case 1: -+ vbuf->flags = V4L2_BUF_FLAG_PFRAME; -+ break; -+ case 2: -+ case 3: -+ vbuf->flags = V4L2_BUF_FLAG_BFRAME; -+ break; -+ default: -+ vbuf->flags = V4L2_BUF_FLAG_PFRAME; -+ NX_ErrMsg(("not defined frame type!!!\n")); -+ break; -+ } -+ vb2_set_plane_payload(&mb_entry->vb, 0, ctx->strm_size); ++ val = 0; ++ val |= (pEncInfo->bwbEnable<<12) | (pEncInfo->cbcrInterleave<<2); ++ val |= pEncInfo->frameEndian; ++ VpuWriteReg(BIT_FRAME_MEM_CTRL, val); + -+ vb2_buffer_done(&mb_entry->vb, VB2_BUF_STATE_DONE); ++ if (pEncInfo->ringBufferEnable == 0) { ++ val = 0; ++ val |= (0x1<<6); ++ val |= (0x1<<5); ++ val |= (0x1<<4); ++ } else { ++ val |= (0x1<<3); + } ++ val |= VPU_STREAM_ENDIAN; ++ VpuWriteReg(BIT_BIT_STREAM_CTRL, val); + -+ spin_unlock_irqrestore(&dev->irqlock, flags); ++#if (DBG_REGISTER) ++ { ++ int reg; + -+ return ret; -+} ++ NX_DbgMsg(DBG_REGISTER, ("[ENC_RUN_Reg]\n")); ++ for (reg = 0x180 ; reg < 0x200 ; reg += 16) { ++ NX_DbgMsg(DBG_REGISTER, ("[Addr = %3x]%x %x %x %x\n", ++ reg, VpuReadReg(BIT_BASE + reg), ++ VpuReadReg(BIT_BASE + reg + 4), ++ VpuReadReg(BIT_BASE + reg + 8), ++ VpuReadReg(BIT_BASE + reg + 12))); ++ } ++ } ++#endif + -+static int alloc_encoder_memory(struct nx_vpu_ctx *ctx) -+{ -+ int width, height, i; -+ struct vpu_enc_ctx *enc_ctx = &ctx->codec.enc; -+ void *drv = &ctx->dev->plat_dev->dev; ++ VpuBitIssueCommand(pInst, PIC_RUN); + -+ FUNC_IN(); ++ do { ++ reason = VPU_WaitBitInterrupt(pInst->devHandle, ++ VPU_ENC_TIMEOUT); + -+ width = ALIGN(ctx->width, 16); -+ height = ALIGN(ctx->height, 16); ++ if (reason == 0) ++ return VPU_RET_ERR_TIMEOUT; ++ if (reason & (1<codec_mode != CODEC_STD_MJPG) { -+ int num; -+ uint32_t format; ++ picEncResult = VpuReadReg(RET_ENC_PIC_SUCCESS); ++ if (picEncResult & (1<<31)) ++ return VPU_RET_ERR_MEM_ACCESS; + -+ if (enc_ctx->reconChromaInterleave == 0) { -+ num = 3; -+ format = V4L2_PIX_FMT_YUV420M; -+ } else { -+ num = 2; -+ format = V4L2_PIX_FMT_NV12M; -+ } ++ picType = VpuReadReg(RET_ENC_PIC_TYPE); ++ readPtr = VpuReadReg(BIT_RD_PTR); ++ writePtr = VpuReadReg(BIT_WR_PTR); + -+ for (i = 0 ; i < 2 ; i++) { -+ enc_ctx->ref_recon_buf[i] = nx_alloc_frame_memory(drv, -+ width, height, num, format, 64); ++ size = writePtr - readPtr; ++ sliceNumber = VpuReadReg(RET_ENC_PIC_SLICE_NUM); + -+ if (enc_ctx->ref_recon_buf[i] == 0) { -+ NX_ErrMsg(("alloc(%d,%d,..) failed(recon%d)\n", -+ width, height, i)); -+ goto Error_Exit; -+ } ++ picFlag = VpuReadReg(RET_ENC_PIC_FLAG); ++ pRunArg->reconImgIdx = VpuReadReg(RET_ENC_PIC_FRAME_IDX); + -+ enc_ctx->sub_sample_buf[i] = nx_alloc_memory(drv, -+ width * height/4, 4096); -+ if (enc_ctx->sub_sample_buf[i] == 0) { -+ NX_ErrMsg(("sub_buf allocation failed\n")); -+ NX_ErrMsg((" size = %d, align = %d)\n", -+ width * height, 16)); -+ goto Error_Exit; -+ } -+ } -+ } ++ pEncInfo->strmEndFlag = VpuReadReg(BIT_BIT_STREAM_PARAM); + -+ ctx->bit_stream_buf = nx_alloc_memory(drv, STREAM_BUF_SIZE, 4096); -+ if (0 == ctx->bit_stream_buf) { -+ NX_ErrMsg(("bit_stream_buf allocation failed.\n")); -+ NX_ErrMsg((" size = %d, align = %d)\n", -+ STREAM_BUF_SIZE, 4096)); -+ goto Error_Exit; -+ } ++ pRunArg->frameType = picType; ++ pRunArg->outStreamSize = size; ++ pRunArg->outStreamAddr = pEncInfo->strmBufVirAddr; + -+ return 0; ++ /*NX_DbgMsg(INFO_MSG, ("Encoded Size = %d, PicType = %d, picFlag = %d, ++ sliceNumber = %d\n", size, picType, picFlag, sliceNumber));*/ + -+Error_Exit: -+ free_encoder_memory(ctx); -+ return -1; ++ return VPU_RET_OK; +} + -+static int free_encoder_memory(struct nx_vpu_ctx *ctx) ++static int VPU_EncChangeParameterCommand(struct nx_vpu_codec_inst *pInst, ++ struct vpu_enc_chg_para_arg *pChgArg) +{ -+ struct vpu_enc_ctx *enc_ctx = &ctx->codec.enc; ++ int ret; + -+ FUNC_IN(); ++ if (pChgArg->chgFlg & VPU_BIT_CHG_GOP) ++ VpuWriteReg(CMD_ENC_SEQ_PARA_RC_GOP, pChgArg->gopSize); + -+ if (!ctx) { -+ NX_ErrMsg(("invalid encoder handle!!!\n")); -+ return -1; -+ } ++ if (pChgArg->chgFlg & VPU_BIT_CHG_INTRAQP) ++ VpuWriteReg(CMD_ENC_SEQ_PARA_RC_INTRA_QP, pChgArg->intraQp); + -+ /* Free Reconstruct Buffer & Reference Buffer */ -+ if (enc_ctx->ref_recon_buf[0]) -+ nx_free_frame_memory(enc_ctx->ref_recon_buf[0]); ++ if (pChgArg->chgFlg & VPU_BIT_CHG_BITRATE) ++ VpuWriteReg(CMD_ENC_SEQ_PARA_RC_BITRATE, pChgArg->bitrate); + -+ if (enc_ctx->ref_recon_buf[1]) -+ nx_free_frame_memory(enc_ctx->ref_recon_buf[1]); ++ if (pChgArg->chgFlg & VPU_BIT_CHG_FRAMERATE) ++ VpuWriteReg(CMD_ENC_SEQ_PARA_RC_FRAME_RATE, ++ (pChgArg->frameRateNum) | ((pChgArg->frameRateDen-1) << 16)); + -+ /* Free SubSampleb Buffer */ -+ if (enc_ctx->sub_sample_buf[0]) -+ nx_free_memory(enc_ctx->sub_sample_buf[0]); ++ if (pChgArg->chgFlg & VPU_BIT_CHG_INTRARF) ++ VpuWriteReg(CMD_ENC_SEQ_PARA_INTRA_MB_NUM, ++ pChgArg->intraRefreshMbs); + -+ if (enc_ctx->sub_sample_buf[1]) -+ nx_free_memory(enc_ctx->sub_sample_buf[1]); ++ if (pChgArg->chgFlg & VPU_BIT_CHG_SLICEMOD) ++ VpuWriteReg(CMD_ENC_SEQ_PARA_SLICE_MODE, (pChgArg->sliceMode) | ++ (pChgArg->sliceSizeMode << 2) | (pChgArg->sliceSizeNum << 3)); + -+ /* Free Bitstream Buffer */ -+ if (ctx->bit_stream_buf) -+ nx_free_memory(ctx->bit_stream_buf); ++ if (pChgArg->chgFlg & VPU_BIT_CHG_HECMODE) ++ VpuWriteReg(CMD_ENC_SEQ_PARA_HEC_MODE, pChgArg->hecMode); + -+ if (ctx->instance_buf) -+ nx_free_memory(ctx->instance_buf); ++ VpuWriteReg(CMD_ENC_SEQ_PARA_CHANGE_ENABLE, pChgArg->chgFlg & 0x7F); + -+ return 0; ++ VpuBitIssueCommand(pInst, RC_CHANGE_PARAMETER); ++ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, ++ BIT_BUSY_FLAG)) ++ return VPU_RET_ERR_TIMEOUT; ++ ++ ret = VpuReadReg(RET_ENC_SEQ_PARA_CHANGE_SECCESS); ++ if ((ret & 1) == 0) ++ return VPU_RET_ERR_CHG_PARAM; ++ if (ret >> 31) ++ return VPU_RET_ERR_MEM_ACCESS; ++ ++ return VPU_RET_OK; +} + -+void nx_vpu_enc_close_instance(struct nx_vpu_ctx *ctx) ++static int VPU_EncCloseCommand(struct nx_vpu_codec_inst *pInst, ++ void *vpu_event_present) +{ -+ struct nx_vpu_v4l2 *dev = ctx->dev; ++ FUNC_IN(); + -+ if (ctx->hInst) { -+ int ret = NX_VpuEncClose(ctx->hInst, (void*)&dev->vpu_event_present); -+ if (ret != 0) -+ NX_ErrMsg(("Failed to return an instance.\n")); -+ free_encoder_memory(ctx); -+ --dev->cur_num_instance; -+ ctx->hInst = NULL; ++ if (pInst->isInitialized) { ++ struct vpu_enc_info *pEncInfo = &pInst->codecInfo.encInfo; ++ ++ VpuWriteReg(BIT_WR_PTR, pEncInfo->strmBufPhyAddr); ++ VpuWriteReg(BIT_RD_PTR, pEncInfo->strmBufPhyAddr); ++ ++ VpuBitIssueCommand(pInst, SEQ_END); ++ if (VPU_RET_OK != VPU_WaitVpuBusy(VPU_BUSY_CHECK_TIMEOUT, ++ BIT_BUSY_FLAG)) { ++ VpuWriteReg(BIT_INT_CLEAR, 0x1); ++ atomic_set((atomic_t *)vpu_event_present, 0); ++ NX_ErrMsg(("VPU_EncCloseCommand() Failed!!!\n")); ++ NX_ErrMsg(("Timeout(%d)\n", VPU_BUSY_CHECK_TIMEOUT)); ++ VPU_SWReset(SW_RESET_SAFETY); ++ pInst->isInitialized = 0; ++ return VPU_RET_ERR_TIMEOUT; ++ } ++ pInst->isInitialized = 0; + } -+} + -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_gdi.c b/drivers/media/platform/nxp-vpu/nx_vpu_gdi.c ---- a/drivers/media/platform/nxp-vpu/nx_vpu_gdi.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_vpu_gdi.c 2018-05-06 08:49:50.074731776 +0200 ++ VpuWriteReg(BIT_INT_CLEAR, 0x1); /* For Signal Break Out */ ++ atomic_set((atomic_t *)vpu_event_present, 0);/* Clear Atomic */ ++ ++ FUNC_OUT(); ++ return VPU_RET_OK; ++} +diff --git a/drivers/media/platform/nxp-vpu/nx_vpu_gdi.c b/drivers/media/platform/nxp-vpu/nx_vpu_gdi.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_vpu_gdi.c @@ -0,0 +1,670 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -110381,9 +111542,11 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_gdi.c b/drivers/media/platf + + return cacheConfig; +} -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_gdi.h b/drivers/media/platform/nxp-vpu/nx_vpu_gdi.h ---- a/drivers/media/platform/nxp-vpu/nx_vpu_gdi.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_vpu_gdi.h 2018-05-06 08:49:50.074731776 +0200 +diff --git a/drivers/media/platform/nxp-vpu/nx_vpu_gdi.h b/drivers/media/platform/nxp-vpu/nx_vpu_gdi.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_vpu_gdi.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -110415,9 +111578,11 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_gdi.h b/drivers/media/platf + int burst, int merge, int mapType, int wayshape); + +#endif /*__NX_VPU_GDI_H__ */ -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.c b/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.c ---- a/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.c 2018-05-06 08:49:50.074731776 +0200 +diff --git a/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.c b/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.c @@ -0,0 +1,1496 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -111915,9 +113080,11 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.c b/drivers/media/plat +MODULE_AUTHOR("Kim SeongHee "); +MODULE_DESCRIPTION("Nexell S5P6818 series SoC V4L2/Codec device driver"); +MODULE_LICENSE("GPL"); -diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.h b/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.h ---- a/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.h 2018-05-06 08:49:50.074731776 +0200 +diff --git a/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.h b/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.h @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -112198,9 +113365,11 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/nx_vpu_v4l2.h b/drivers/media/plat +void nx_vpu_dec_close_instance(struct nx_vpu_ctx*); + +#endif /* #define _nx_vpu_v4l2_H */ -diff -ENwbur a/drivers/media/platform/nxp-vpu/regdefine.h b/drivers/media/platform/nxp-vpu/regdefine.h ---- a/drivers/media/platform/nxp-vpu/regdefine.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/regdefine.h 2018-05-06 08:49:50.074731776 +0200 +diff --git a/drivers/media/platform/nxp-vpu/regdefine.h b/drivers/media/platform/nxp-vpu/regdefine.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/regdefine.h @@ -0,0 +1,617 @@ +/* + * This file is a part of VPU Reference API project @@ -112819,9 +113988,11 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/regdefine.h b/drivers/media/platfo +#define RET_FW_CODE_REV (BIT_BASE + 0x1c4) + +#endif -diff -ENwbur a/drivers/media/platform/nxp-vpu/vpu_hw_interface.c b/drivers/media/platform/nxp-vpu/vpu_hw_interface.c ---- a/drivers/media/platform/nxp-vpu/vpu_hw_interface.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/vpu_hw_interface.c 2018-05-06 08:49:50.074731776 +0200 +diff --git a/drivers/media/platform/nxp-vpu/vpu_hw_interface.c b/drivers/media/platform/nxp-vpu/vpu_hw_interface.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/vpu_hw_interface.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -112920,9 +114091,11 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/vpu_hw_interface.c b/drivers/media + VpuWriteReg(BIT_RUN_AUX_STD, inst->auxMode); + VpuWriteReg(BIT_RUN_COMMAND, cmd); +} -diff -ENwbur a/drivers/media/platform/nxp-vpu/vpu_hw_interface.h b/drivers/media/platform/nxp-vpu/vpu_hw_interface.h ---- a/drivers/media/platform/nxp-vpu/vpu_hw_interface.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/vpu_hw_interface.h 2018-05-06 08:49:50.074731776 +0200 +diff --git a/drivers/media/platform/nxp-vpu/vpu_hw_interface.h b/drivers/media/platform/nxp-vpu/vpu_hw_interface.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/vpu_hw_interface.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -112975,9 +114148,11 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/vpu_hw_interface.h b/drivers/media +void VpuBitIssueCommand(struct nx_vpu_codec_inst *inst, enum nx_vpu_cmd cmd); + +#endif /* __VPU_HW_INTERFACE_H__ */ -diff -ENwbur a/drivers/media/platform/nxp-vpu/vpu_types.h b/drivers/media/platform/nxp-vpu/vpu_types.h ---- a/drivers/media/platform/nxp-vpu/vpu_types.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/media/platform/nxp-vpu/vpu_types.h 2018-05-06 08:49:50.078731938 +0200 +diff --git a/drivers/media/platform/nxp-vpu/vpu_types.h b/drivers/media/platform/nxp-vpu/vpu_types.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/media/platform/nxp-vpu/vpu_types.h @@ -0,0 +1,452 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -113431,18 +114606,19 @@ diff -ENwbur a/drivers/media/platform/nxp-vpu/vpu_types.h b/drivers/media/platfo +/*/////////////////////////////////////////////////////////////////////////// */ + +#endif /* __VPU_TYPES_H__ */ -diff -ENwbur a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c ---- a/drivers/media/v4l2-core/v4l2-ioctl.c 2018-05-06 08:47:37.317343639 +0200 -+++ b/drivers/media/v4l2-core/v4l2-ioctl.c 2018-05-06 08:49:50.166735509 +0200 +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 111111111111..222222222222 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -31,6 +31,7 @@ #include - + #include +#include - + /* Zero out the end of the struct pointed to by p. Everything after, but * not including, the specified field is cleared. */ -@@ -1181,6 +1182,8 @@ +@@ -1183,6 +1184,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_NV61M: descr = "Y/CrCb 4:2:2 (N-C)"; break; case V4L2_PIX_FMT_NV12MT: descr = "Y/CbCr 4:2:0 (64x32 MB, N-C)"; break; case V4L2_PIX_FMT_NV12MT_16X16: descr = "Y/CbCr 4:2:0 (16x16 MB, N-C)"; break; @@ -113451,7 +114627,7 @@ diff -ENwbur a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4 case V4L2_PIX_FMT_YUV420M: descr = "Planar YUV 4:2:0 (N-C)"; break; case V4L2_PIX_FMT_YVU420M: descr = "Planar YVU 4:2:0 (N-C)"; break; case V4L2_PIX_FMT_YUV422M: descr = "Planar YUV 4:2:2 (N-C)"; break; -@@ -1284,6 +1287,17 @@ +@@ -1286,6 +1289,17 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_SE401: descr = "GSPCA SE401"; break; case V4L2_PIX_FMT_S5C_UYVY_JPG: descr = "S5C73MX interleaved UYVY/JPEG"; break; case V4L2_PIX_FMT_MT21C: descr = "Mediatek Compressed Format"; break; @@ -113469,9 +114645,45 @@ diff -ENwbur a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4 default: WARN(1, "Unknown pixelformat 0x%08x\n", fmt->pixelformat); if (fmt->description[0]) -diff -ENwbur a/drivers/mfd/axp228-mfd.c b/drivers/mfd/axp228-mfd.c ---- a/drivers/mfd/axp228-mfd.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/mfd/axp228-mfd.c 2018-05-06 08:49:50.182736159 +0200 +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -125,6 +125,17 @@ config MFD_ATMEL_SMC + bool + select MFD_SYSCON + ++config MFD_AXP228 ++ bool "X-Powers AXP228 PMIC Support" ++ depends on I2C=y ++ select MFD_CORE ++ help ++ If you say yes here you get support for the X-Powers AXP228 ++ Power Management system device. ++ This driver provides common support for accessing the device, ++ additional drivers must be enabled in order to use the ++ functionality of the device. ++ + config MFD_BCM590XX + tristate "Broadcom BCM590xx PMUs" + select MFD_CORE +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o + obj-$(CONFIG_MFD_ACT8945A) += act8945a.o + obj-$(CONFIG_MFD_SM501) += sm501.o + obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o ++obj-$(CONFIG_MFD_AXP228) += axp228-mfd.o + obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o + obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o + cros_ec_core-objs := cros_ec.o +diff --git a/drivers/mfd/axp228-mfd.c b/drivers/mfd/axp228-mfd.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/mfd/axp228-mfd.c @@ -0,0 +1,1147 @@ +/* + * axp228-mfd.c -- PMIC driver for the X-Powers AXP228 @@ -114620,45 +115832,14 @@ diff -ENwbur a/drivers/mfd/axp228-mfd.c b/drivers/mfd/axp228-mfd.c +MODULE_DESCRIPTION("MFD Driver for X-Powers AXP228 PMIC"); +MODULE_AUTHOR("Jongsin Park "); +MODULE_LICENSE("GPL"); -diff -ENwbur a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig ---- a/drivers/mfd/Kconfig 2018-05-06 08:47:37.329344127 +0200 -+++ b/drivers/mfd/Kconfig 2018-05-06 08:49:50.178735995 +0200 -@@ -125,6 +125,17 @@ - bool - select MFD_SYSCON - -+config MFD_AXP228 -+ bool "X-Powers AXP228 PMIC Support" -+ depends on I2C=y -+ select MFD_CORE -+ help -+ If you say yes here you get support for the X-Powers AXP228 -+ Power Management system device. -+ This driver provides common support for accessing the device, -+ additional drivers must be enabled in order to use the -+ functionality of the device. -+ - config MFD_BCM590XX - tristate "Broadcom BCM590xx PMUs" - select MFD_CORE -diff -ENwbur a/drivers/mfd/Makefile b/drivers/mfd/Makefile ---- a/drivers/mfd/Makefile 2018-05-06 08:47:37.329344127 +0200 -+++ b/drivers/mfd/Makefile 2018-05-06 08:49:50.178735995 +0200 -@@ -10,6 +10,7 @@ - obj-$(CONFIG_MFD_ACT8945A) += act8945a.o - obj-$(CONFIG_MFD_SM501) += sm501.o - obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o -+obj-$(CONFIG_MFD_AXP228) += axp228-mfd.o - obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o - obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o - cros_ec_core-objs := cros_ec.o -diff -ENwbur a/drivers/misc/Kconfig b/drivers/misc/Kconfig ---- a/drivers/misc/Kconfig 2018-05-06 08:47:37.345344777 +0200 -+++ b/drivers/misc/Kconfig 2018-05-06 08:49:50.194736646 +0200 -@@ -506,6 +506,14 @@ +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -506,6 +506,14 @@ config PCI_ENDPOINT_TEST Enable this configuration option to enable the host side test driver for PCI Endpoint. - + +config NX_SCALER + tristate "Nexell s5pxx18 series memory to memory scaler" + default n @@ -114670,20 +115851,23 @@ diff -ENwbur a/drivers/misc/Kconfig b/drivers/misc/Kconfig source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" -diff -ENwbur a/drivers/misc/Makefile b/drivers/misc/Makefile ---- a/drivers/misc/Makefile 2018-05-06 08:47:37.345344777 +0200 -+++ b/drivers/misc/Makefile 2018-05-06 08:49:50.194736646 +0200 -@@ -56,6 +56,7 @@ +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -56,6 +56,7 @@ obj-$(CONFIG_CXL_BASE) += cxl/ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o +obj-$(CONFIG_NX_SCALER) += nx-scaler.o - + lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o -diff -ENwbur a/drivers/misc/nx-scaler.c b/drivers/misc/nx-scaler.c ---- a/drivers/misc/nx-scaler.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/misc/nx-scaler.c 2018-05-06 08:49:50.210737295 +0200 +diff --git a/drivers/misc/nx-scaler.c b/drivers/misc/nx-scaler.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/misc/nx-scaler.c @@ -0,0 +1,1405 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -116090,9 +117274,11 @@ diff -ENwbur a/drivers/misc/nx-scaler.c b/drivers/misc/nx-scaler.c +MODULE_DESCRIPTION("Scaler driver for Nexell"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:nx-scaler"); -diff -ENwbur a/drivers/misc/nx-scaler.h b/drivers/misc/nx-scaler.h ---- a/drivers/misc/nx-scaler.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/misc/nx-scaler.h 2018-05-06 08:49:50.210737295 +0200 +diff --git a/drivers/misc/nx-scaler.h b/drivers/misc/nx-scaler.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/misc/nx-scaler.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -116143,47 +117329,43 @@ diff -ENwbur a/drivers/misc/nx-scaler.h b/drivers/misc/nx-scaler.h + struct mutex mutex; +}; +#endif -diff -ENwbur a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c ---- a/drivers/mmc/host/dw_mmc.c 2018-05-06 08:47:37.373345913 +0200 -+++ b/drivers/mmc/host/dw_mmc.c 2018-05-06 08:49:50.226737943 +0200 -@@ -3222,6 +3222,15 @@ - goto err_clk_ciu; - } - -+ if (drv_data && drv_data->setup_clock) { -+ ret = drv_data->setup_clock(host); -+ if (ret) { -+ dev_err(host->dev, -+ "implementation specific clock setup failed\n"); -+ goto err_clk_ciu; -+ } -+ } +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -704,6 +704,15 @@ config MMC_DW_EXYNOS + Synopsys DesignWare Memory Card Interface driver. Select this option + for platforms based on Exynos4 and Exynos5 SoC's. + ++config MMC_DW_NEXELL ++ tristate "Nexell specific extensions for Synopsys DW Memory Card Interface" ++ depends on MMC_DW ++ select MMC_DW_PLTFM ++ help ++ This selects support for Nexell s5pxx18 SoC specific extensions to the ++ Synopsys DesignWare Memory Card Interface driver. Select this option ++ for platforms based on s5p6818 and s5p6818 SoC's. + - if (!IS_ERR(host->pdata->rstc)) { - reset_control_assert(host->pdata->rstc); - usleep_range(10, 50); -diff -ENwbur a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h ---- a/drivers/mmc/host/dw_mmc.h 2018-05-06 08:47:37.373345913 +0200 -+++ b/drivers/mmc/host/dw_mmc.h 2018-05-06 08:49:50.226737943 +0200 -@@ -544,6 +544,7 @@ - * @caps: mmc subsystem specified capabilities of the controller(s). - * @num_caps: number of capabilities specified by @caps. - * @init: early implementation specific initialization. -+ * @setup_clock: implementation specific clock configuration. - * @set_ios: handle bus specific extensions. - * @parse_dt: parse implementation specific device tree properties. - * @execute_tuning: implementation specific tuning procedure. -@@ -556,6 +557,7 @@ - unsigned long *caps; - u32 num_caps; - int (*init)(struct dw_mci *host); -+ int (*setup_clock)(struct dw_mci *host); - void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); - int (*parse_dt)(struct dw_mci *host); - int (*execute_tuning)(struct dw_mci_slot *slot, u32 opcode); -diff -ENwbur a/drivers/mmc/host/dw_mmc-nexell.c b/drivers/mmc/host/dw_mmc-nexell.c ---- a/drivers/mmc/host/dw_mmc-nexell.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/mmc/host/dw_mmc-nexell.c 2018-05-06 08:49:50.222737782 +0200 + config MMC_DW_K3 + tristate "K3 specific extensions for Synopsys DW Memory Card Interface" + depends on MMC_DW +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -55,6 +55,7 @@ obj-$(CONFIG_MMC_CAVIUM_THUNDERX) += thunderx-mmc.o + obj-$(CONFIG_MMC_DW) += dw_mmc.o + obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o + obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o ++obj-$(CONFIG_MMC_DW_NEXELL) += dw_mmc-nexell.o + obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o + obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o + obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o +diff --git a/drivers/mmc/host/dw_mmc-nexell.c b/drivers/mmc/host/dw_mmc-nexell.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/mmc/host/dw_mmc-nexell.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -116353,9 +117535,11 @@ diff -ENwbur a/drivers/mmc/host/dw_mmc-nexell.c b/drivers/mmc/host/dw_mmc-nexell +MODULE_AUTHOR("Youngbok Park setup_clock) { ++ ret = drv_data->setup_clock(host); ++ if (ret) { ++ dev_err(host->dev, ++ "implementation specific clock setup failed\n"); ++ goto err_clk_ciu; ++ } ++ } ++ + if (!IS_ERR(host->pdata->rstc)) { + reset_control_assert(host->pdata->rstc); + usleep_range(10, 50); +diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h +index 111111111111..222222222222 100644 +--- a/drivers/mmc/host/dw_mmc.h ++++ b/drivers/mmc/host/dw_mmc.h +@@ -544,6 +544,7 @@ struct dw_mci_slot { + * @caps: mmc subsystem specified capabilities of the controller(s). + * @num_caps: number of capabilities specified by @caps. + * @init: early implementation specific initialization. ++ * @setup_clock: implementation specific clock configuration. + * @set_ios: handle bus specific extensions. + * @parse_dt: parse implementation specific device tree properties. + * @execute_tuning: implementation specific tuning procedure. +@@ -556,6 +557,7 @@ struct dw_mci_drv_data { + unsigned long *caps; + u32 num_caps; + int (*init)(struct dw_mci *host); ++ int (*setup_clock)(struct dw_mci *host); + void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); + int (*parse_dt)(struct dw_mci *host); + int (*execute_tuning)(struct dw_mci_slot *slot, u32 opcode); +diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig ++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig +@@ -86,6 +86,16 @@ config DWMAC_MESON + the stmmac device driver. This driver is used for Meson6, + Meson8, Meson8b and GXBB SoCs. + ++config DWMAC_NEXELL ++ tristate "Nexell dwmac support" ++ default ARCH_S5P6818 ++ depends on OF + help -+ This selects support for Nexell s5pxx18 SoC specific extensions to the -+ Synopsys DesignWare Memory Card Interface driver. Select this option -+ for platforms based on s5p6818 and s5p6818 SoC's. ++ Support for Ethernet controller on Nexell SoCs. + - config MMC_DW_K3 - tristate "K3 specific extensions for Synopsys DW Memory Card Interface" - depends on MMC_DW -diff -ENwbur a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile ---- a/drivers/mmc/host/Makefile 2018-05-06 08:47:37.373345913 +0200 -+++ b/drivers/mmc/host/Makefile 2018-05-06 08:49:50.222737782 +0200 -@@ -55,6 +55,7 @@ - obj-$(CONFIG_MMC_DW) += dw_mmc.o - obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o - obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o -+obj-$(CONFIG_MMC_DW_NEXELL) += dw_mmc-nexell.o - obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o - obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o - obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o -diff -ENwbur a/drivers/net/ethernet/stmicro/stmmac/dwmac-nexell.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-nexell.c ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-nexell.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-nexell.c 2018-05-06 08:49:50.518749793 +0200 ++ This selects the Nexell SoC glue layer support for ++ the stmmac device driver. ++ + config DWMAC_OXNAS + tristate "Oxford Semiconductor OXNAS dwmac support" + default ARCH_OXNAS +diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/Makefile ++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile +@@ -12,6 +12,7 @@ obj-$(CONFIG_DWMAC_ANARION) += dwmac-anarion.o + obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o + obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o + obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o ++obj-$(CONFIG_DWMAC_NEXELL) += dwmac-nexell.o + obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o + obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o + obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-nexell.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-nexell.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-nexell.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -116588,44 +117817,14 @@ diff -ENwbur a/drivers/net/ethernet/stmicro/stmmac/dwmac-nexell.c b/drivers/net/ +MODULE_AUTHOR("Bon-gyu, KOO "); +MODULE_DESCRIPTION("Nexell DWMAC specific glue layer"); +MODULE_LICENSE("GPL"); -diff -ENwbur a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig ---- a/drivers/net/ethernet/stmicro/stmmac/Kconfig 2018-05-06 08:47:37.657357443 +0200 -+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig 2018-05-06 08:49:50.518749793 +0200 -@@ -86,6 +86,16 @@ - the stmmac device driver. This driver is used for Meson6, - Meson8, Meson8b and GXBB SoCs. - -+config DWMAC_NEXELL -+ tristate "Nexell dwmac support" -+ default ARCH_S5P6818 -+ depends on OF -+ help -+ Support for Ethernet controller on Nexell SoCs. -+ -+ This selects the Nexell SoC glue layer support for -+ the stmmac device driver. -+ - config DWMAC_OXNAS - tristate "Oxford Semiconductor OXNAS dwmac support" - default ARCH_OXNAS -diff -ENwbur a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile ---- a/drivers/net/ethernet/stmicro/stmmac/Makefile 2018-05-06 08:47:37.657357443 +0200 -+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile 2018-05-06 08:49:50.518749793 +0200 -@@ -12,6 +12,7 @@ - obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o - obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o - obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o -+obj-$(CONFIG_DWMAC_NEXELL) += dwmac-nexell.o - obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o - obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o - obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o -diff -ENwbur a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c 2018-05-06 08:47:37.661357606 +0200 -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c 2018-05-06 08:49:50.522749955 +0200 -@@ -628,6 +628,39 @@ +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +index 111111111111..222222222222 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +@@ -628,6 +628,39 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) struct stmmac_priv *priv = netdev_priv(dev); u32 support = WAKE_MAGIC | WAKE_UCAST; - + + if (priv->plat->set_wol) + { + int ret; @@ -116662,13 +117861,14 @@ diff -ENwbur a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/ne /* By default almost all GMAC devices support the WoL via * magic frame but we can disable it if the HW capability * register shows no support for pmt_magic_frame. */ -diff -ENwbur a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c 2018-05-06 08:47:37.661357606 +0200 -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c 2018-05-06 08:49:50.522749955 +0200 -@@ -459,6 +459,11 @@ +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +index 111111111111..222222222222 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +@@ -458,6 +458,11 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) plat->pmt = 1; } - + + if (of_device_is_compatible(np, "nexell,s5p6818-gmac")) { + of_property_read_u32(np, "snps,multicast-filter-bins", + &plat->multicast_filter_bins); @@ -116677,9 +117877,218 @@ diff -ENwbur a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/n if (of_device_is_compatible(np, "snps,dwmac-4.00") || of_device_is_compatible(np, "snps,dwmac-4.10a")) { plat->has_gmac4 = 1; -diff -ENwbur a/drivers/net/wireless/bcm4336/aiutils.c b/drivers/net/wireless/bcm4336/aiutils.c ---- a/drivers/net/wireless/bcm4336/aiutils.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/aiutils.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/net/wireless/Kconfig ++++ b/drivers/net/wireless/Kconfig +@@ -33,6 +33,7 @@ config WIRELESS_WDS + source "drivers/net/wireless/admtek/Kconfig" + source "drivers/net/wireless/ath/Kconfig" + source "drivers/net/wireless/atmel/Kconfig" ++source "drivers/net/wireless/bcm4336/Kconfig" + source "drivers/net/wireless/broadcom/Kconfig" + source "drivers/net/wireless/cisco/Kconfig" + source "drivers/net/wireless/intel/Kconfig" +diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/net/wireless/Makefile ++++ b/drivers/net/wireless/Makefile +@@ -6,6 +6,7 @@ + obj-$(CONFIG_WLAN_VENDOR_ADMTEK) += admtek/ + obj-$(CONFIG_WLAN_VENDOR_ATH) += ath/ + obj-$(CONFIG_WLAN_VENDOR_ATMEL) += atmel/ ++obj-$(CONFIG_BCMDHD) += bcm4336/ + obj-$(CONFIG_WLAN_VENDOR_BROADCOM) += broadcom/ + obj-$(CONFIG_WLAN_VENDOR_CISCO) += cisco/ + obj-$(CONFIG_WLAN_VENDOR_INTEL) += intel/ +diff --git a/drivers/net/wireless/bcm4336/Kconfig b/drivers/net/wireless/bcm4336/Kconfig +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/Kconfig +@@ -0,0 +1,65 @@ ++config BCMDHD ++ tristate "Broadcom FullMAC wireless cards support" ++ ---help--- ++ This module adds support for wireless adapters based on ++ Broadcom FullMAC chipset. ++ ++config BCMDHD_FW_PATH ++ depends on BCMDHD ++ string "Firmware path" ++ default "/system/etc/firmware/fw_bcmdhd.bin" ++ ---help--- ++ Path to the firmware file. ++ ++config BCMDHD_NVRAM_PATH ++ depends on BCMDHD ++ string "NVRAM path" ++ default "/system/etc/firmware/nvram.txt" ++ ---help--- ++ Path to the calibration file. ++ ++config BCMDHD_WEXT ++ bool "Enable WEXT support" ++ depends on BCMDHD && CFG80211 = n ++ select WIRELESS_EXT ++ select WEXT_PRIV ++ help ++ Enables WEXT support ++ ++choice ++ prompt "Enable Chip Interface" ++ depends on BCMDHD ++ default BCMDHD_SDIO ++ ---help--- ++ Enable Chip Interface. ++ ++config BCMDHD_SDIO ++ bool "SDIO bus interface support" ++ depends on BCMDHD && MMC ++ ++config BCMDHD_PCIE ++ bool "PCIe bus interface support" ++ depends on BCMDHD && PCI ++ ++endchoice ++ ++choice ++ depends on BCMDHD && BCMDHD_SDIO ++ prompt "Interrupt type" ++ default BCMDHD_OOB ++ ---help--- ++ Interrupt type ++ ++config BCMDHD_OOB ++ depends on BCMDHD && BCMDHD_SDIO ++ bool "Out-of-Band Interrupt" ++ ---help--- ++ Interrupt from WL_HOST_WAKE. ++ ++config BCMDHD_SDIO_IRQ ++ depends on BCMDHD && BCMDHD_SDIO ++ bool "In-Band Interrupt" ++ ---help--- ++ Interrupt from SDIO DAT[1] ++ ++endchoice +diff --git a/drivers/net/wireless/bcm4336/Makefile b/drivers/net/wireless/bcm4336/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/Makefile +@@ -0,0 +1,106 @@ ++# bcmdhd ++# 1. WL_IFACE_COMB_NUM_CHANNELS must be added if Android version is 4.4 with Kernel version 3.0~3.4, ++# otherwise please remove it. ++ ++#CONFIG_BCMDHD_SDIO := y ++#CONFIG_BCMDHD_PCIE := y ++ ++DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER -DSDTEST \ ++ -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE \ ++ -DDHDTHREAD -DDHD_DEBUG -DSHOW_EVENTS -DBCMDBG -DGET_OTP_MAC_ENABLE \ ++ -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DSUPPORT_PM2_ONLY \ ++ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DPNO_SUPPORT -DDHDTCPACK_SUPPRESS \ ++ -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DRXFRAME_THREAD \ ++ -DSET_RANDOM_MAC_SOFTAP \ ++ -DENABLE_INSMOD_NO_FW_LOAD \ ++ -Idrivers/net/wireless/bcm4336 -Idrivers/net/wireless/bcm4336/include ++ ++DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o \ ++ dhd_linux.o dhd_linux_platdev.o dhd_linux_sched.o dhd_pno.o \ ++ dhd_common.o dhd_ip.o dhd_linux_wq.o dhd_custom_gpio.o \ ++ bcmevent.o hndpmu.o linux_osl.o wldev_common.o wl_android.o \ ++ hnd_pktq.o hnd_pktpool.o dhd_config.o ++ ++ifneq ($(CONFIG_BCMDHD_SDIO),) ++DHDCFLAGS += \ ++ -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR \ ++ -DBDC -DPROP_TXSTATUS -DDHD_USE_IDLECOUNT -DBCMSDIOH_TXGLOM \ ++ -DCUSTOM_SDIO_F2_BLKSIZE=128 ++ ++DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o \ ++ dhd_sdio.o dhd_cdc.o dhd_wlfc.o ++ ++ifeq ($(CONFIG_BCMDHD_OOB),y) ++DHDCFLAGS += -DOOB_INTR_ONLY -DHW_OOB -DCUSTOMER_OOB ++ifeq ($(CONFIG_BCMDHD_DISABLE_WOWLAN),y) ++DHDCFLAGS += -DDISABLE_WOWLAN ++endif ++else ++DHDCFLAGS += -DSDIO_ISR_THREAD ++endif ++endif ++ ++ifneq ($(CONFIG_BCMDHD_PCIE),) ++DHDCFLAGS += \ ++ -DPCIE_FULL_DONGLE -DBCMPCIE -DSHOW_LOGTRACE -DDPCIE_TX_DEFERRAL \ ++ -DCUSTOM_DPC_PRIO_SETTING=-1 ++ ++DHDOFILES += dhd_pcie.o dhd_pcie_linux.o pcie_core.o dhd_flowring.o \ ++ dhd_msgbuf.o ++endif ++ ++obj-$(CONFIG_BCMDHD) += bcmdhd.o ++bcmdhd-objs += $(DHDOFILES) ++ ++ifeq ($(CONFIG_MACH_MINI2451),y) ++DHDOFILES += dhd_gpio.o ++DHDCFLAGS += -DCUSTOMER_HW -DDHD_OF_SUPPORT ++#DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI ++DHDCFLAGS += -DPOWERUP_MAX_RETRY=1 -DPOWERUP_WAIT_MS=1200 ++endif ++ ++ifeq ($(CONFIG_ARCH_S5P6818),y) ++DHDOFILES += dhd_gpio.o ++DHDCFLAGS += -DCUSTOMER_HW -DDHD_OF_SUPPORT ++#DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI ++DHDCFLAGS += -DPOWERUP_MAX_RETRY=1 -DPOWERUP_WAIT_MS=1200 ++DHDCFLAGS += -DPOWER_OFF_IN_SUSPEND ++DHDCFLAGS += -DDHD_PRINTF_LL=KERN_DEBUG ++endif ++ ++ifeq ($(CONFIG_BCMDHD_AG),y) ++DHDCFLAGS += -DBAND_AG ++endif ++ ++ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y) ++# add dhd_static_buf to kernel image build ++#obj-y += dhd_static_buf.o ++DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DENHANCED_STATIC_BUF ++endif ++ ++ifneq ($(CONFIG_WIRELESS_EXT),) ++bcmdhd-objs += wl_iw.o ++DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW ++endif ++ifneq ($(CONFIG_CFG80211),) ++bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o wl_cfg_btcoex.o ++bcmdhd-objs += dhd_cfg80211.o dhd_cfg_vendor.o ++DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT -DWL_ENABLE_P2P_IF ++DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS ++DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-65 ++DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=15 ++DHDCFLAGS += -DCUSTOM_KEEP_ALIVE_SETTING=28000 ++DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=7 ++DHDCFLAGS += -DWL_SUPPORT_AUTO_CHANNEL ++DHDCFLAGS += -DWL_SUPPORT_BACKPORTED_KPATCHES ++DHDCFLAGS += -DESCAN_RESULT_PATCH ++DHDCFLAGS += -DVSDB -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++DHDCFLAGS += -DWLTDLS -DMIRACAST_AMPDU_SIZE=8 -DPROP_TXSTATUS_VSDB ++endif ++EXTRA_CFLAGS = $(DHDCFLAGS) ++ifeq ($(CONFIG_BCMDHD),m) ++DHDCFLAGS += -DMULTIPLE_SUPPLICANT ++EXTRA_LDFLAGS += --strip-debug ++else ++DHDCFLAGS += -DBUILD_IN_KERNEL ++endif +diff --git a/drivers/net/wireless/bcm4336/aiutils.c b/drivers/net/wireless/bcm4336/aiutils.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/aiutils.c @@ -0,0 +1,1097 @@ +/* + * Misc utility routines for accessing chip-specific features @@ -117778,9 +119187,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/aiutils.c b/drivers/net/wireless/bcm + } +} +#endif -diff -ENwbur a/drivers/net/wireless/bcm4336/ap621x.h b/drivers/net/wireless/bcm4336/ap621x.h ---- a/drivers/net/wireless/bcm4336/ap621x.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/ap621x.h 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/ap621x.h b/drivers/net/wireless/bcm4336/ap621x.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/ap621x.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015 FriendlyARM (www.arm9.net) @@ -117861,9 +119272,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/ap621x.h b/drivers/net/wireless/bcm4 +#endif /* CONFIG_MACH_MINI2451 */ + +#endif /* __AP621X_H__ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/bcmevent.c b/drivers/net/wireless/bcm4336/bcmevent.c ---- a/drivers/net/wireless/bcm4336/bcmevent.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/bcmevent.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/bcmevent.c b/drivers/net/wireless/bcm4336/bcmevent.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/bcmevent.c @@ -0,0 +1,185 @@ +/* + * bcmevent read-only data shared by kernel or app layers @@ -118050,9 +119463,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/bcmevent.c b/drivers/net/wireless/bc + */ + return ((event_name) ? event_name : "Unknown Event"); +} -diff -ENwbur a/drivers/net/wireless/bcm4336/bcmsdh.c b/drivers/net/wireless/bcm4336/bcmsdh.c ---- a/drivers/net/wireless/bcm4336/bcmsdh.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/bcmsdh.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/bcmsdh.c b/drivers/net/wireless/bcm4336/bcmsdh.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/bcmsdh.c @@ -0,0 +1,698 @@ +/* + * BCMSDH interface glue @@ -118752,9 +120167,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/bcmsdh.c b/drivers/net/wireless/bcm4 + + return sdioh_gpioout(sd, gpio, enab); +} -diff -ENwbur a/drivers/net/wireless/bcm4336/bcmsdh_linux.c b/drivers/net/wireless/bcm4336/bcmsdh_linux.c ---- a/drivers/net/wireless/bcm4336/bcmsdh_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/bcmsdh_linux.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/bcmsdh_linux.c b/drivers/net/wireless/bcm4336/bcmsdh_linux.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/bcmsdh_linux.c @@ -0,0 +1,463 @@ +/* + * SDIO access interface for drivers - linux specific (pci only) @@ -119219,9 +120636,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/bcmsdh_linux.c b/drivers/net/wireles +EXPORT_SYMBOL(bcmsdh_chipinfo); + +#endif /* BCMSDH_MODULE */ -diff -ENwbur a/drivers/net/wireless/bcm4336/bcmsdh_sdmmc.c b/drivers/net/wireless/bcm4336/bcmsdh_sdmmc.c ---- a/drivers/net/wireless/bcm4336/bcmsdh_sdmmc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/bcmsdh_sdmmc.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/bcmsdh_sdmmc.c b/drivers/net/wireless/bcm4336/bcmsdh_sdmmc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/bcmsdh_sdmmc.c @@ -0,0 +1,1476 @@ +/* + * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel @@ -120699,9 +122118,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/bcmsdh_sdmmc.c b/drivers/net/wireles +{ + return SDIOH_API_RC_FAIL; +} -diff -ENwbur a/drivers/net/wireless/bcm4336/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcm4336/bcmsdh_sdmmc_linux.c ---- a/drivers/net/wireless/bcm4336/bcmsdh_sdmmc_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/bcmsdh_sdmmc_linux.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcm4336/bcmsdh_sdmmc_linux.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/bcmsdh_sdmmc_linux.c @@ -0,0 +1,412 @@ +/* + * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel @@ -121115,9 +122536,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/bcmsdh_sdmmc_linux.c b/drivers/net/w + kfree(gInstance); +#endif +} -diff -ENwbur a/drivers/net/wireless/bcm4336/bcmutils.c b/drivers/net/wireless/bcm4336/bcmutils.c ---- a/drivers/net/wireless/bcm4336/bcmutils.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/bcmutils.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/bcmutils.c b/drivers/net/wireless/bcm4336/bcmutils.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/bcmutils.c @@ -0,0 +1,3067 @@ +/* + * Driver O/S-independent utility routines @@ -123329,2409 +124752,3527 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/bcmutils.c b/drivers/net/wireless/bc + * BCM_MWBMAP_SHIFT_OP: Used in MOD, DIV and MUL operations. + * BCM_MWBMAP_INVALID_IDX: Value ~0U is treated as an invalid ID + * -+ * Design Notes: -+ * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many -+ * bits are computed each time on allocation and deallocation, requiring 4 -+ * array indexed access and 3 arithmetic operations. When not defined, a runtime -+ * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed. -+ * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation. -+ * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may -+ * be used by defining BCM_MWBMAP_USE_CNTSETBITS. ++ * Design Notes: ++ * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many ++ * bits are computed each time on allocation and deallocation, requiring 4 ++ * array indexed access and 3 arithmetic operations. When not defined, a runtime ++ * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed. ++ * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation. ++ * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may ++ * be used by defining BCM_MWBMAP_USE_CNTSETBITS. ++ * ++ * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array ++ * size is fixed. No intention to support larger than 4K indice allocation. ID ++ * allocators for ranges smaller than 4K will have a wastage of only 12Bytes ++ * with savings in not having to use an indirect access, had it been dynamically ++ * allocated. ++ */ ++#define BCM_MWBMAP_ITEMS_MAX (4 * 1024) /* May increase to 16K */ ++ ++#define BCM_MWBMAP_BITS_WORD (NBITS(uint32)) ++#define BCM_MWBMAP_WORDS_MAX (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD) ++#define BCM_MWBMAP_WDMAP_MAX (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD) ++#define BCM_MWBMAP_SHIFT_OP (5) ++#define BCM_MWBMAP_MODOP(ix) ((ix) & (BCM_MWBMAP_BITS_WORD - 1)) ++#define BCM_MWBMAP_DIVOP(ix) ((ix) >> BCM_MWBMAP_SHIFT_OP) ++#define BCM_MWBMAP_MULOP(ix) ((ix) << BCM_MWBMAP_SHIFT_OP) ++ ++/* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */ ++#define BCM_MWBMAP_PTR(hdl) ((struct bcm_mwbmap *)(hdl)) ++#define BCM_MWBMAP_HDL(ptr) ((void *)(ptr)) ++ ++#if defined(BCM_MWBMAP_DEBUG) ++#define BCM_MWBMAP_AUDIT(mwb) \ ++ do { \ ++ ASSERT((mwb != NULL) && \ ++ (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \ ++ bcm_mwbmap_audit(mwb); \ ++ } while (0) ++#define MWBMAP_ASSERT(exp) ASSERT(exp) ++#define MWBMAP_DBG(x) printf x ++#else /* !BCM_MWBMAP_DEBUG */ ++#define BCM_MWBMAP_AUDIT(mwb) do {} while (0) ++#define MWBMAP_ASSERT(exp) do {} while (0) ++#define MWBMAP_DBG(x) ++#endif /* !BCM_MWBMAP_DEBUG */ ++ ++ ++typedef struct bcm_mwbmap { /* Hierarchical multiword bitmap allocator */ ++ uint16 wmaps; /* Total number of words in free wd bitmap */ ++ uint16 imaps; /* Total number of words in free id bitmap */ ++ int16 ifree; /* Count of free indices. Used only in audits */ ++ uint16 total; /* Total indices managed by multiword bitmap */ ++ ++ void * magic; /* Audit handle parameter from user */ ++ ++ uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of */ ++#if !defined(BCM_MWBMAP_USE_CNTSETBITS) ++ int8 wd_count[BCM_MWBMAP_WORDS_MAX]; /* free id running count, 1st lvl */ ++#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ ++ uint32 id_bitmap[0]; /* Second level bitmap */ ++} bcm_mwbmap_t; ++ ++/* Incarnate a hierarchical multiword bitmap based small index allocator. */ ++struct bcm_mwbmap * ++bcm_mwbmap_init(osl_t *osh, uint32 items_max) ++{ ++ struct bcm_mwbmap * mwbmap_p; ++ uint32 wordix, size, words, extra; ++ ++ /* Implementation Constraint: Uses 32bit word bitmap */ ++ MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U); ++ MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U); ++ MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX)); ++ MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U); ++ ++ ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX); ++ ++ /* Determine the number of words needed in the multiword bitmap */ ++ extra = BCM_MWBMAP_MODOP(items_max); ++ words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U); ++ ++ /* Allocate runtime state of multiword bitmap */ ++ /* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */ ++ size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words); ++ mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size); ++ if (mwbmap_p == (bcm_mwbmap_t *)NULL) { ++ ASSERT(0); ++ goto error1; ++ } ++ memset(mwbmap_p, 0, size); ++ ++ /* Initialize runtime multiword bitmap state */ ++ mwbmap_p->imaps = (uint16)words; ++ mwbmap_p->ifree = (int16)items_max; ++ mwbmap_p->total = (uint16)items_max; ++ ++ /* Setup magic, for use in audit of handle */ ++ mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p); ++ ++ /* Setup the second level bitmap of free indices */ ++ /* Mark all indices as available */ ++ for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) { ++ mwbmap_p->id_bitmap[wordix] = (uint32)(~0U); ++#if !defined(BCM_MWBMAP_USE_CNTSETBITS) ++ mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD; ++#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ } ++ ++ /* Ensure that extra indices are tagged as un-available */ ++ if (extra) { /* fixup the free ids in last bitmap and wd_count */ ++ uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1]; ++ *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */ ++#if !defined(BCM_MWBMAP_USE_CNTSETBITS) ++ mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */ ++#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ } ++ ++ /* Setup the first level bitmap hierarchy */ ++ extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps); ++ words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U); ++ ++ mwbmap_p->wmaps = (uint16)words; ++ ++ for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++) ++ mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U); ++ if (extra) { ++ uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1]; ++ *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */ ++ } ++ ++ return mwbmap_p; ++ ++error1: ++ return BCM_MWBMAP_INVALID_HDL; ++} ++ ++/* Release resources used by multiword bitmap based small index allocator. */ ++void ++bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl) ++{ ++ bcm_mwbmap_t * mwbmap_p; ++ ++ BCM_MWBMAP_AUDIT(mwbmap_hdl); ++ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ ++ MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap) ++ + (sizeof(uint32) * mwbmap_p->imaps)); ++ return; ++} ++ ++/* Allocate a unique small index using a multiword bitmap index allocator. */ ++uint32 BCMFASTPATH ++bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl) ++{ ++ bcm_mwbmap_t * mwbmap_p; ++ uint32 wordix, bitmap; ++ ++ BCM_MWBMAP_AUDIT(mwbmap_hdl); ++ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ ++ /* Start with the first hierarchy */ ++ for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) { ++ ++ bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */ ++ ++ if (bitmap != 0U) { ++ ++ uint32 count, bitix, *bitmap_p; ++ ++ bitmap_p = &mwbmap_p->wd_bitmap[wordix]; ++ ++ /* clear all except trailing 1 */ ++ bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap)))); ++ MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) == ++ bcm_count_leading_zeros(bitmap)); ++ bitix = (BCM_MWBMAP_BITS_WORD - 1) ++ - bcm_count_leading_zeros(bitmap); /* use asm clz */ ++ wordix = BCM_MWBMAP_MULOP(wordix) + bitix; ++ ++ /* Clear bit if wd count is 0, without conditional branch */ ++#if defined(BCM_MWBMAP_USE_CNTSETBITS) ++ count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1; ++#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ mwbmap_p->wd_count[wordix]--; ++ count = mwbmap_p->wd_count[wordix]; ++ MWBMAP_ASSERT(count == ++ (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1)); ++#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ MWBMAP_ASSERT(count >= 0); ++ ++ /* clear wd_bitmap bit if id_map count is 0 */ ++ bitmap = (count == 0) << bitix; ++ ++ MWBMAP_DBG(( ++ "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d", ++ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count)); ++ ++ *bitmap_p ^= bitmap; ++ ++ /* Use bitix in the second hierarchy */ ++ bitmap_p = &mwbmap_p->id_bitmap[wordix]; ++ ++ bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */ ++ MWBMAP_ASSERT(bitmap != 0U); ++ ++ /* clear all except trailing 1 */ ++ bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap)))); ++ MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) == ++ bcm_count_leading_zeros(bitmap)); ++ bitix = BCM_MWBMAP_MULOP(wordix) ++ + (BCM_MWBMAP_BITS_WORD - 1) ++ - bcm_count_leading_zeros(bitmap); /* use asm clz */ ++ ++ mwbmap_p->ifree--; /* decrement system wide free count */ ++ MWBMAP_ASSERT(mwbmap_p->ifree >= 0); ++ ++ MWBMAP_DBG(( ++ "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d", ++ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, ++ mwbmap_p->ifree)); ++ ++ *bitmap_p ^= bitmap; /* mark as allocated = 1b0 */ ++ ++ return bitix; ++ } ++ } ++ ++ ASSERT(mwbmap_p->ifree == 0); ++ ++ return BCM_MWBMAP_INVALID_IDX; ++} ++ ++/* Force an index at a specified position to be in use */ ++void ++bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) ++{ ++ bcm_mwbmap_t * mwbmap_p; ++ uint32 count, wordix, bitmap, *bitmap_p; ++ ++ BCM_MWBMAP_AUDIT(mwbmap_hdl); ++ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ ++ ASSERT(bitix < mwbmap_p->total); ++ ++ /* Start with second hierarchy */ ++ wordix = BCM_MWBMAP_DIVOP(bitix); ++ bitmap = (uint32)(1U << BCM_MWBMAP_MODOP(bitix)); ++ bitmap_p = &mwbmap_p->id_bitmap[wordix]; ++ ++ ASSERT((*bitmap_p & bitmap) == bitmap); ++ ++ mwbmap_p->ifree--; /* update free count */ ++ ASSERT(mwbmap_p->ifree >= 0); ++ ++ MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d", ++ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, ++ mwbmap_p->ifree)); ++ ++ *bitmap_p ^= bitmap; /* mark as in use */ ++ ++ /* Update first hierarchy */ ++ bitix = wordix; ++ ++ wordix = BCM_MWBMAP_DIVOP(bitix); ++ bitmap_p = &mwbmap_p->wd_bitmap[wordix]; ++ ++#if defined(BCM_MWBMAP_USE_CNTSETBITS) ++ count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]); ++#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ mwbmap_p->wd_count[bitix]--; ++ count = mwbmap_p->wd_count[bitix]; ++ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix])); ++#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ MWBMAP_ASSERT(count >= 0); ++ ++ bitmap = (count == 0) << BCM_MWBMAP_MODOP(bitix); ++ ++ MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d", ++ BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap, ++ (*bitmap_p) ^ bitmap, count)); ++ ++ *bitmap_p ^= bitmap; /* mark as in use */ ++ ++ return; ++} ++ ++/* Free a previously allocated index back into the multiword bitmap allocator */ ++void BCMFASTPATH ++bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) ++{ ++ bcm_mwbmap_t * mwbmap_p; ++ uint32 wordix, bitmap, *bitmap_p; ++ ++ BCM_MWBMAP_AUDIT(mwbmap_hdl); ++ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ ++ ASSERT(bitix < mwbmap_p->total); ++ ++ /* Start with second level hierarchy */ ++ wordix = BCM_MWBMAP_DIVOP(bitix); ++ bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); ++ bitmap_p = &mwbmap_p->id_bitmap[wordix]; ++ ++ ASSERT((*bitmap_p & bitmap) == 0U); /* ASSERT not a double free */ ++ ++ mwbmap_p->ifree++; /* update free count */ ++ ASSERT(mwbmap_p->ifree <= mwbmap_p->total); ++ ++ MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d", ++ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, ++ mwbmap_p->ifree)); ++ ++ *bitmap_p |= bitmap; /* mark as available */ ++ ++ /* Now update first level hierarchy */ ++ ++ bitix = wordix; ++ ++ wordix = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */ ++ bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); ++ bitmap_p = &mwbmap_p->wd_bitmap[wordix]; ++ ++#if !defined(BCM_MWBMAP_USE_CNTSETBITS) ++ mwbmap_p->wd_count[bitix]++; ++#endif ++ ++#if defined(BCM_MWBMAP_DEBUG) ++ { ++ uint32 count; ++#if defined(BCM_MWBMAP_USE_CNTSETBITS) ++ count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]); ++#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ count = mwbmap_p->wd_count[bitix]; ++ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix])); ++#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ ++ MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD); ++ ++ MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d", ++ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count)); ++ } ++#endif /* BCM_MWBMAP_DEBUG */ ++ ++ *bitmap_p |= bitmap; ++ ++ return; ++} ++ ++/* Fetch the toal number of free indices in the multiword bitmap allocator */ ++uint32 ++bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl) ++{ ++ bcm_mwbmap_t * mwbmap_p; ++ ++ BCM_MWBMAP_AUDIT(mwbmap_hdl); ++ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ ++ ASSERT(mwbmap_p->ifree >= 0); ++ ++ return mwbmap_p->ifree; ++} ++ ++/* Determine whether an index is inuse or free */ ++bool ++bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) ++{ ++ bcm_mwbmap_t * mwbmap_p; ++ uint32 wordix, bitmap; ++ ++ BCM_MWBMAP_AUDIT(mwbmap_hdl); ++ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ ++ ASSERT(bitix < mwbmap_p->total); ++ ++ wordix = BCM_MWBMAP_DIVOP(bitix); ++ bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); ++ ++ return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U); ++} ++ ++/* Debug dump a multiword bitmap allocator */ ++void ++bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl) ++{ ++ uint32 ix, count; ++ bcm_mwbmap_t * mwbmap_p; ++ ++ BCM_MWBMAP_AUDIT(mwbmap_hdl); ++ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ ++ printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n", mwbmap_p, ++ mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total); ++ for (ix = 0U; ix < mwbmap_p->wmaps; ix++) { ++ printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]); ++ bcm_bitprint32(mwbmap_p->wd_bitmap[ix]); ++ printf("\n"); ++ } ++ for (ix = 0U; ix < mwbmap_p->imaps; ix++) { ++#if defined(BCM_MWBMAP_USE_CNTSETBITS) ++ count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]); ++#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ count = mwbmap_p->wd_count[ix]; ++ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix])); ++#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count); ++ bcm_bitprint32(mwbmap_p->id_bitmap[ix]); ++ printf("\n"); ++ } ++ ++ return; ++} ++ ++/* Audit a hierarchical multiword bitmap */ ++void ++bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl) ++{ ++ bcm_mwbmap_t * mwbmap_p; ++ uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p; ++ ++ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ ++ for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) { ++ ++ bitmap_p = &mwbmap_p->wd_bitmap[wordix]; ++ ++ for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) { ++ if ((*bitmap_p) & (1 << bitix)) { ++ idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix; ++#if defined(BCM_MWBMAP_USE_CNTSETBITS) ++ count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]); ++#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ count = mwbmap_p->wd_count[idmap_ix]; ++ ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix])); ++#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ ASSERT(count != 0U); ++ free_cnt += count; ++ } ++ } ++ } ++ ++ ASSERT((int)free_cnt == mwbmap_p->ifree); ++} ++/* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */ ++ ++/* Simple 16bit Id allocator using a stack implementation. */ ++typedef struct id16_map { ++ uint16 total; /* total number of ids managed by allocator */ ++ uint16 start; /* start value of 16bit ids to be managed */ ++ uint32 failures; /* count of failures */ ++ void *dbg; /* debug placeholder */ ++ int stack_idx; /* index into stack of available ids */ ++ uint16 stack[0]; /* stack of 16 bit ids */ ++} id16_map_t; ++ ++#define ID16_MAP_SZ(items) (sizeof(id16_map_t) + \ ++ (sizeof(uint16) * (items))) ++ ++#if defined(BCM_DBG) ++ ++/* Uncomment BCM_DBG_ID16 to debug double free */ ++/* #define BCM_DBG_ID16 */ ++ ++typedef struct id16_map_dbg { ++ uint16 total; ++ bool avail[0]; ++} id16_map_dbg_t; ++#define ID16_MAP_DBG_SZ(items) (sizeof(id16_map_dbg_t) + \ ++ (sizeof(bool) * (items))) ++#define ID16_MAP_MSG(x) print x ++#else ++#define ID16_MAP_MSG(x) ++#endif /* BCM_DBG */ ++ ++void * /* Construct an id16 allocator: [start_val16 .. start_val16+total_ids) */ ++id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16) ++{ ++ uint16 idx, val16; ++ id16_map_t * id16_map; ++ ++ ASSERT(total_ids > 0); ++ ASSERT((start_val16 + total_ids) < ID16_INVALID); ++ ++ id16_map = (id16_map_t *) MALLOC(osh, ID16_MAP_SZ(total_ids)); ++ if (id16_map == NULL) { ++ return NULL; ++ } ++ ++ id16_map->total = total_ids; ++ id16_map->start = start_val16; ++ id16_map->failures = 0; ++ id16_map->dbg = NULL; ++ ++ /* Populate stack with 16bit id values, commencing with start_val16 */ ++ id16_map->stack_idx = 0; ++ val16 = start_val16; ++ ++ for (idx = 0; idx < total_ids; idx++, val16++) { ++ id16_map->stack_idx = idx; ++ id16_map->stack[id16_map->stack_idx] = val16; ++ } ++ ++#if defined(BCM_DBG) && defined(BCM_DBG_ID16) ++ id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids)); ++ ++ if (id16_map->dbg) { ++ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; ++ ++ id16_map_dbg->total = total_ids; ++ for (idx = 0; idx < total_ids; idx++) { ++ id16_map_dbg->avail[idx] = TRUE; ++ } ++ } ++#endif /* BCM_DBG && BCM_DBG_ID16 */ ++ ++ return (void *)id16_map; ++} ++ ++void * /* Destruct an id16 allocator instance */ ++id16_map_fini(osl_t *osh, void * id16_map_hndl) ++{ ++ uint16 total_ids; ++ id16_map_t * id16_map; ++ ++ if (id16_map_hndl == NULL) ++ return NULL; ++ ++ id16_map = (id16_map_t *)id16_map_hndl; ++ ++ total_ids = id16_map->total; ++ ASSERT(total_ids > 0); ++ ++#if defined(BCM_DBG) && defined(BCM_DBG_ID16) ++ if (id16_map->dbg) { ++ MFREE(osh, id16_map->dbg, ID16_MAP_DBG_SZ(total_ids)); ++ id16_map->dbg = NULL; ++ } ++#endif /* BCM_DBG && BCM_DBG_ID16 */ ++ ++ id16_map->total = 0; ++ MFREE(osh, id16_map, ID16_MAP_SZ(total_ids)); ++ ++ return NULL; ++} ++ ++void ++id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16) ++{ ++ uint16 idx, val16; ++ id16_map_t * id16_map; ++ ++ ASSERT(total_ids > 0); ++ ASSERT((start_val16 + total_ids) < ID16_INVALID); ++ ++ id16_map = (id16_map_t *)id16_map_hndl; ++ if (id16_map == NULL) { ++ return; ++ } ++ ++ id16_map->total = total_ids; ++ id16_map->start = start_val16; ++ id16_map->failures = 0; ++ ++ /* Populate stack with 16bit id values, commencing with start_val16 */ ++ id16_map->stack_idx = 0; ++ val16 = start_val16; ++ ++ for (idx = 0; idx < total_ids; idx++, val16++) { ++ id16_map->stack_idx = idx; ++ id16_map->stack[id16_map->stack_idx] = val16; ++ } ++ ++#if defined(BCM_DBG) && defined(BCM_DBG_ID16) ++ if (id16_map->dbg) { ++ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; ++ ++ id16_map_dbg->total = total_ids; ++ for (idx = 0; idx < total_ids; idx++) { ++ id16_map_dbg->avail[idx] = TRUE; ++ } ++ } ++#endif /* BCM_DBG && BCM_DBG_ID16 */ ++} ++ ++uint16 BCMFASTPATH /* Allocate a unique 16bit id */ ++id16_map_alloc(void * id16_map_hndl) ++{ ++ uint16 val16; ++ id16_map_t * id16_map; ++ ++ ASSERT(id16_map_hndl != NULL); ++ ++ id16_map = (id16_map_t *)id16_map_hndl; ++ ++ ASSERT(id16_map->total > 0); ++ ++ if (id16_map->stack_idx < 0) { ++ id16_map->failures++; ++ return ID16_INVALID; ++ } ++ ++ val16 = id16_map->stack[id16_map->stack_idx]; ++ id16_map->stack_idx--; ++ ++#if defined(BCM_DBG) && defined(BCM_DBG_ID16) ++ ++ ASSERT(val16 < (id16_map->start + id16_map->total)); ++ ++ if (id16_map->dbg) { /* Validate val16 */ ++ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; ++ ++ ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == TRUE); ++ id16_map_dbg->avail[val16 - id16_map->start] = FALSE; ++ } ++#endif /* BCM_DBG && BCM_DBG_ID16 */ ++ ++ return val16; ++} ++ ++ ++void BCMFASTPATH /* Free a 16bit id value into the id16 allocator */ ++id16_map_free(void * id16_map_hndl, uint16 val16) ++{ ++ id16_map_t * id16_map; ++ ++ ASSERT(id16_map_hndl != NULL); ++ ++ id16_map = (id16_map_t *)id16_map_hndl; ++ ++#if defined(BCM_DBG) && defined(BCM_DBG_ID16) ++ ++ ASSERT(val16 < (id16_map->start + id16_map->total)); ++ ++ if (id16_map->dbg) { /* Validate val16 */ ++ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; ++ ++ ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == FALSE); ++ id16_map_dbg->avail[val16 - id16_map->start] = TRUE; ++ } ++#endif /* BCM_DBG && BCM_DBG_ID16 */ ++ ++ id16_map->stack_idx++; ++ id16_map->stack[id16_map->stack_idx] = val16; ++} ++ ++uint32 /* Returns number of failures to allocate an unique id16 */ ++id16_map_failures(void * id16_map_hndl) ++{ ++ ASSERT(id16_map_hndl != NULL); ++ return ((id16_map_t *)id16_map_hndl)->failures; ++} ++ ++bool ++id16_map_audit(void * id16_map_hndl) ++{ ++ int idx; ++ int insane = 0; ++ id16_map_t * id16_map; ++ ++ ASSERT(id16_map_hndl != NULL); ++ ++ id16_map = (id16_map_t *)id16_map_hndl; ++ ++ ASSERT((id16_map->stack_idx > 0) && (id16_map->stack_idx < id16_map->total)); ++ for (idx = 0; idx <= id16_map->stack_idx; idx++) { ++ ASSERT(id16_map->stack[idx] >= id16_map->start); ++ ASSERT(id16_map->stack[idx] < (id16_map->start + id16_map->total)); ++ ++#if defined(BCM_DBG) && defined(BCM_DBG_ID16) ++ if (id16_map->dbg) { ++ uint16 val16 = id16_map->stack[idx]; ++ if (((id16_map_dbg_t *)(id16_map->dbg))->avail[val16] != TRUE) { ++ insane |= 1; ++ ID16_MAP_MSG(("id16_map<%p>: stack_idx %u invalid val16 %u\n", ++ id16_map_hndl, idx, val16)); ++ } ++ } ++#endif /* BCM_DBG && BCM_DBG_ID16 */ ++ } ++ ++#if defined(BCM_DBG) && defined(BCM_DBG_ID16) ++ if (id16_map->dbg) { ++ uint16 avail = 0; /* Audit available ids counts */ ++ for (idx = 0; idx < id16_map_dbg->total; idx++) { ++ if (((id16_map_dbg_t *)(id16_map->dbg))->avail[idx16] == TRUE) ++ avail++; ++ } ++ if (avail && (avail != (id16_map->stack_idx + 1))) { ++ insane |= 1; ++ ID16_MAP_MSG(("id16_map<%p>: avail %u stack_idx %u\n", ++ id16_map_hndl, avail, id16_map->stack_idx)); ++ } ++ } ++#endif /* BCM_DBG && BCM_DBG_ID16 */ ++ ++ return (!!insane); ++} ++/* END: Simple id16 allocator */ ++ ++ ++#endif /* BCMDRIVER */ ++ ++/* calculate a >> b; and returns only lower 32 bits */ ++void ++bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b) ++{ ++ uint32 a1 = a_high, a0 = a_low, r0 = 0; ++ ++ if (b == 0) { ++ r0 = a_low; ++ *r = r0; ++ return; ++ } ++ ++ if (b < 32) { ++ a0 = a0 >> b; ++ a1 = a1 & ((1 << b) - 1); ++ a1 = a1 << (32 - b); ++ r0 = a0 | a1; ++ *r = r0; ++ return; ++ } else { ++ r0 = a1 >> (b - 32); ++ *r = r0; ++ return; ++ } ++ ++} ++ ++/* calculate a + b where a is a 64 bit number and b is a 32 bit number */ ++void ++bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset) ++{ ++ uint32 r1_lo = *r_lo; ++ (*r_lo) += offset; ++ if (*r_lo < r1_lo) ++ (*r_hi) ++; ++} ++ ++/* calculate a - b where a is a 64 bit number and b is a 32 bit number */ ++void ++bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset) ++{ ++ uint32 r1_lo = *r_lo; ++ (*r_lo) -= offset; ++ if (*r_lo > r1_lo) ++ (*r_hi) --; ++} ++ ++#ifdef DEBUG_COUNTER ++#if (OSL_SYSUPTIME_SUPPORT == TRUE) ++void counter_printlog(counter_tbl_t *ctr_tbl) ++{ ++ uint32 now; ++ ++ if (!ctr_tbl->enabled) ++ return; ++ ++ now = OSL_SYSUPTIME(); ++ ++ if (now - ctr_tbl->prev_log_print > ctr_tbl->log_print_interval) { ++ uint8 i = 0; ++ printf("counter_print(%s %d):", ctr_tbl->name, now - ctr_tbl->prev_log_print); ++ ++ for (i = 0; i < ctr_tbl->needed_cnt; i++) { ++ printf(" %u", ctr_tbl->cnt[i]); ++ } ++ printf("\n"); ++ ++ ctr_tbl->prev_log_print = now; ++ bzero(ctr_tbl->cnt, CNTR_TBL_MAX * sizeof(uint)); ++ } ++} ++#else ++/* OSL_SYSUPTIME is not supported so no way to get time */ ++#define counter_printlog(a) do {} while (0) ++#endif /* OSL_SYSUPTIME_SUPPORT == TRUE */ ++#endif /* DEBUG_COUNTER */ ++ ++#ifdef BCMDRIVER ++void ++dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size) ++{ ++ uint32 mem_size; ++ mem_size = sizeof(dll_pool_t) + (elems_max * elem_size); ++ if (pool) ++ MFREE(osh, pool, mem_size); ++} ++dll_pool_t * ++dll_pool_init(void * osh, uint16 elems_max, uint16 elem_size) ++{ ++ uint32 mem_size, i; ++ dll_pool_t * dll_pool_p; ++ dll_t * elem_p; ++ ++ ASSERT(elem_size > sizeof(dll_t)); ++ ++ mem_size = sizeof(dll_pool_t) + (elems_max * elem_size); ++ ++ if ((dll_pool_p = (dll_pool_t *)MALLOC(osh, mem_size)) == NULL) { ++ printf("dll_pool_init: elems_max<%u> elem_size<%u> malloc failure\n", ++ elems_max, elem_size); ++ ASSERT(0); ++ return dll_pool_p; ++ } ++ ++ bzero(dll_pool_p, mem_size); ++ ++ dll_init(&dll_pool_p->free_list); ++ dll_pool_p->elems_max = elems_max; ++ dll_pool_p->elem_size = elem_size; ++ ++ elem_p = dll_pool_p->elements; ++ for (i = 0; i < elems_max; i++) { ++ dll_append(&dll_pool_p->free_list, elem_p); ++ elem_p = (dll_t *)((uintptr)elem_p + elem_size); ++ } ++ ++ dll_pool_p->free_count = elems_max; ++ ++ return dll_pool_p; ++} ++ ++ ++void * ++dll_pool_alloc(dll_pool_t * dll_pool_p) ++{ ++ dll_t * elem_p; ++ ++ if (dll_pool_p->free_count == 0) { ++ ASSERT(dll_empty(&dll_pool_p->free_list)); ++ return NULL; ++ } ++ ++ elem_p = dll_head_p(&dll_pool_p->free_list); ++ dll_delete(elem_p); ++ dll_pool_p->free_count -= 1; ++ ++ return (void *)elem_p; ++} ++ ++void ++dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p) ++{ ++ dll_t * node_p = (dll_t *)elem_p; ++ dll_prepend(&dll_pool_p->free_list, node_p); ++ dll_pool_p->free_count += 1; ++} ++ ++ ++void ++dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p) ++{ ++ dll_t * node_p = (dll_t *)elem_p; ++ dll_append(&dll_pool_p->free_list, node_p); ++ dll_pool_p->free_count += 1; ++} ++ ++#endif /* BCMDRIVER */ +diff --git a/drivers/net/wireless/bcm4336/bcmwifi_channels.c b/drivers/net/wireless/bcm4336/bcmwifi_channels.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/bcmwifi_channels.c +@@ -0,0 +1,1211 @@ ++/* ++ * Misc utility routines used by kernel or app-level. ++ * Contents are wifi-specific, used by any kernel or app-level ++ * software that might want wifi things as it grows. ++ * ++ * $Copyright Open Broadcom Corporation$ ++ * $Id: bcmwifi_channels.c 309193 2012-01-19 00:03:57Z $ ++ */ ++ ++#include ++#include ++#include ++ ++#ifdef BCMDRIVER ++#include ++#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) ++#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) ++#else ++#include ++#include ++#include ++#ifndef ASSERT ++#define ASSERT(exp) ++#endif ++#endif /* BCMDRIVER */ ++ ++#include ++ ++#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL)) ++#include /* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */ ++#endif ++ ++/* Definitions for D11AC capable Chanspec type */ ++ ++/* Chanspec ASCII representation with 802.11ac capability: ++ * [ 'g'] ['/' []['/'<1st80channel>'-'<2nd80channel>]] ++ * ++ * : ++ * (optional) 2, 3, 4, 5 for 2.4GHz, 3GHz, 4GHz, and 5GHz respectively. ++ * Default value is 2g if channel <= 14, otherwise 5g. ++ * : ++ * channel number of the 5MHz, 10MHz, 20MHz channel, ++ * or primary channel of 40MHz, 80MHz, 160MHz, or 80+80MHz channel. ++ * : ++ * (optional) 5, 10, 20, 40, 80, 160, or 80+80. Default value is 20. ++ * : ++ * (only for 2.4GHz band 40MHz) U for upper sideband primary, L for lower. ++ * ++ * For 2.4GHz band 40MHz channels, the same primary channel may be the ++ * upper sideband for one 40MHz channel, and the lower sideband for an ++ * overlapping 40MHz channel. The U/L disambiguates which 40MHz channel ++ * is being specified. ++ * ++ * For 40MHz in the 5GHz band and all channel bandwidths greater than ++ * 40MHz, the U/L specificaion is not allowed since the channels are ++ * non-overlapping and the primary sub-band is derived from its ++ * position in the wide bandwidth channel. ++ * ++ * <1st80Channel>: ++ * <2nd80Channel>: ++ * Required for 80+80, otherwise not allowed. ++ * Specifies the center channel of the first and second 80MHz band. ++ * ++ * In its simplest form, it is a 20MHz channel number, with the implied band ++ * of 2.4GHz if channel number <= 14, and 5GHz otherwise. ++ * ++ * To allow for backward compatibility with scripts, the old form for ++ * 40MHz channels is also allowed: ++ * ++ * : ++ * primary channel of 40MHz, channel <= 14 is 2GHz, otherwise 5GHz ++ * : ++ * "U" for upper, "L" for lower (or lower case "u" "l") ++ * ++ * 5 GHz Examples: ++ * Chanspec BW Center Ch Channel Range Primary Ch ++ * 5g8 20MHz 8 - - ++ * 52 20MHz 52 - - ++ * 52/40 40MHz 54 52-56 52 ++ * 56/40 40MHz 54 52-56 56 ++ * 52/80 80MHz 58 52-64 52 ++ * 56/80 80MHz 58 52-64 56 ++ * 60/80 80MHz 58 52-64 60 ++ * 64/80 80MHz 58 52-64 64 ++ * 52/160 160MHz 50 36-64 52 ++ * 36/160 160MGz 50 36-64 36 ++ * 36/80+80/42-106 80+80MHz 42,106 36-48,100-112 36 + * -+ * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array -+ * size is fixed. No intention to support larger than 4K indice allocation. ID -+ * allocators for ranges smaller than 4K will have a wastage of only 12Bytes -+ * with savings in not having to use an indirect access, had it been dynamically -+ * allocated. ++ * 2 GHz Examples: ++ * Chanspec BW Center Ch Channel Range Primary Ch ++ * 2g8 20MHz 8 - - ++ * 8 20MHz 8 - - ++ * 6 20MHz 6 - - ++ * 6/40l 40MHz 8 6-10 6 ++ * 6l 40MHz 8 6-10 6 ++ * 6/40u 40MHz 4 2-6 6 ++ * 6u 40MHz 4 2-6 6 + */ -+#define BCM_MWBMAP_ITEMS_MAX (4 * 1024) /* May increase to 16K */ -+ -+#define BCM_MWBMAP_BITS_WORD (NBITS(uint32)) -+#define BCM_MWBMAP_WORDS_MAX (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD) -+#define BCM_MWBMAP_WDMAP_MAX (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD) -+#define BCM_MWBMAP_SHIFT_OP (5) -+#define BCM_MWBMAP_MODOP(ix) ((ix) & (BCM_MWBMAP_BITS_WORD - 1)) -+#define BCM_MWBMAP_DIVOP(ix) ((ix) >> BCM_MWBMAP_SHIFT_OP) -+#define BCM_MWBMAP_MULOP(ix) ((ix) << BCM_MWBMAP_SHIFT_OP) + -+/* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */ -+#define BCM_MWBMAP_PTR(hdl) ((struct bcm_mwbmap *)(hdl)) -+#define BCM_MWBMAP_HDL(ptr) ((void *)(ptr)) ++/* bandwidth ASCII string */ ++static const char *wf_chspec_bw_str[] = ++{ ++ "5", ++ "10", ++ "20", ++ "40", ++ "80", ++ "160", ++ "80+80", ++ "na" ++}; + -+#if defined(BCM_MWBMAP_DEBUG) -+#define BCM_MWBMAP_AUDIT(mwb) \ -+ do { \ -+ ASSERT((mwb != NULL) && \ -+ (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \ -+ bcm_mwbmap_audit(mwb); \ -+ } while (0) -+#define MWBMAP_ASSERT(exp) ASSERT(exp) -+#define MWBMAP_DBG(x) printf x -+#else /* !BCM_MWBMAP_DEBUG */ -+#define BCM_MWBMAP_AUDIT(mwb) do {} while (0) -+#define MWBMAP_ASSERT(exp) do {} while (0) -+#define MWBMAP_DBG(x) -+#endif /* !BCM_MWBMAP_DEBUG */ ++static const uint8 wf_chspec_bw_mhz[] = ++{5, 10, 20, 40, 80, 160, 160}; + ++#define WF_NUM_BW \ ++ (sizeof(wf_chspec_bw_mhz)/sizeof(uint8)) + -+typedef struct bcm_mwbmap { /* Hierarchical multiword bitmap allocator */ -+ uint16 wmaps; /* Total number of words in free wd bitmap */ -+ uint16 imaps; /* Total number of words in free id bitmap */ -+ int16 ifree; /* Count of free indices. Used only in audits */ -+ uint16 total; /* Total indices managed by multiword bitmap */ ++/* 40MHz channels in 5GHz band */ ++static const uint8 wf_5g_40m_chans[] = ++{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159}; ++#define WF_NUM_5G_40M_CHANS \ ++ (sizeof(wf_5g_40m_chans)/sizeof(uint8)) + -+ void * magic; /* Audit handle parameter from user */ ++/* 80MHz channels in 5GHz band */ ++static const uint8 wf_5g_80m_chans[] = ++{42, 58, 106, 122, 138, 155}; ++#define WF_NUM_5G_80M_CHANS \ ++ (sizeof(wf_5g_80m_chans)/sizeof(uint8)) + -+ uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of */ -+#if !defined(BCM_MWBMAP_USE_CNTSETBITS) -+ int8 wd_count[BCM_MWBMAP_WORDS_MAX]; /* free id running count, 1st lvl */ -+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++/* 160MHz channels in 5GHz band */ ++static const uint8 wf_5g_160m_chans[] = ++{50, 114}; ++#define WF_NUM_5G_160M_CHANS \ ++ (sizeof(wf_5g_160m_chans)/sizeof(uint8)) + -+ uint32 id_bitmap[0]; /* Second level bitmap */ -+} bcm_mwbmap_t; + -+/* Incarnate a hierarchical multiword bitmap based small index allocator. */ -+struct bcm_mwbmap * -+bcm_mwbmap_init(osl_t *osh, uint32 items_max) ++/* convert bandwidth from chanspec to MHz */ ++static uint ++bw_chspec_to_mhz(chanspec_t chspec) +{ -+ struct bcm_mwbmap * mwbmap_p; -+ uint32 wordix, size, words, extra; -+ -+ /* Implementation Constraint: Uses 32bit word bitmap */ -+ MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U); -+ MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U); -+ MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX)); -+ MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U); -+ -+ ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX); -+ -+ /* Determine the number of words needed in the multiword bitmap */ -+ extra = BCM_MWBMAP_MODOP(items_max); -+ words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U); ++ uint bw; + -+ /* Allocate runtime state of multiword bitmap */ -+ /* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */ -+ size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words); -+ mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size); -+ if (mwbmap_p == (bcm_mwbmap_t *)NULL) { -+ ASSERT(0); -+ goto error1; -+ } -+ memset(mwbmap_p, 0, size); ++ bw = (chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT; ++ return (bw >= WF_NUM_BW ? 0 : wf_chspec_bw_mhz[bw]); ++} + -+ /* Initialize runtime multiword bitmap state */ -+ mwbmap_p->imaps = (uint16)words; -+ mwbmap_p->ifree = (int16)items_max; -+ mwbmap_p->total = (uint16)items_max; ++/* bw in MHz, return the channel count from the center channel to the ++ * the channel at the edge of the band ++ */ ++static uint8 ++center_chan_to_edge(uint bw) ++{ ++ /* edge channels separated by BW - 10MHz on each side ++ * delta from cf to edge is half of that, ++ * MHz to channel num conversion is 5MHz/channel ++ */ ++ return (uint8)(((bw - 20) / 2) / 5); ++} + -+ /* Setup magic, for use in audit of handle */ -+ mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p); ++/* return channel number of the low edge of the band ++ * given the center channel and BW ++ */ ++static uint8 ++channel_low_edge(uint center_ch, uint bw) ++{ ++ return (uint8)(center_ch - center_chan_to_edge(bw)); ++} + -+ /* Setup the second level bitmap of free indices */ -+ /* Mark all indices as available */ -+ for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) { -+ mwbmap_p->id_bitmap[wordix] = (uint32)(~0U); -+#if !defined(BCM_MWBMAP_USE_CNTSETBITS) -+ mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD; -+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ -+ } ++/* return side band number given center channel and control channel ++ * return -1 on error ++ */ ++static int ++channel_to_sb(uint center_ch, uint ctl_ch, uint bw) ++{ ++ uint lowest = channel_low_edge(center_ch, bw); ++ uint sb; + -+ /* Ensure that extra indices are tagged as un-available */ -+ if (extra) { /* fixup the free ids in last bitmap and wd_count */ -+ uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1]; -+ *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */ -+#if !defined(BCM_MWBMAP_USE_CNTSETBITS) -+ mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */ -+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ if ((ctl_ch - lowest) % 4) { ++ /* bad ctl channel, not mult 4 */ ++ return -1; + } + -+ /* Setup the first level bitmap hierarchy */ -+ extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps); -+ words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U); -+ -+ mwbmap_p->wmaps = (uint16)words; ++ sb = ((ctl_ch - lowest) / 4); + -+ for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++) -+ mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U); -+ if (extra) { -+ uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1]; -+ *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */ ++ /* sb must be a index to a 20MHz channel in range */ ++ if (sb >= (bw / 20)) { ++ /* ctl_ch must have been too high for the center_ch */ ++ return -1; + } + -+ return mwbmap_p; -+ -+error1: -+ return BCM_MWBMAP_INVALID_HDL; ++ return sb; +} + -+/* Release resources used by multiword bitmap based small index allocator. */ -+void -+bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl) ++/* return control channel given center channel and side band */ ++static uint8 ++channel_to_ctl_chan(uint center_ch, uint bw, uint sb) +{ -+ bcm_mwbmap_t * mwbmap_p; -+ -+ BCM_MWBMAP_AUDIT(mwbmap_hdl); -+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); -+ -+ MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap) -+ + (sizeof(uint32) * mwbmap_p->imaps)); -+ return; ++ return (uint8)(channel_low_edge(center_ch, bw) + sb * 4); +} + -+/* Allocate a unique small index using a multiword bitmap index allocator. */ -+uint32 BCMFASTPATH -+bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl) ++/* return index of 80MHz channel from channel number ++ * return -1 on error ++ */ ++static int ++channel_80mhz_to_id(uint ch) +{ -+ bcm_mwbmap_t * mwbmap_p; -+ uint32 wordix, bitmap; -+ -+ BCM_MWBMAP_AUDIT(mwbmap_hdl); -+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ uint i; ++ for (i = 0; i < WF_NUM_5G_80M_CHANS; i ++) { ++ if (ch == wf_5g_80m_chans[i]) ++ return i; ++ } + -+ /* Start with the first hierarchy */ -+ for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) { ++ return -1; ++} + -+ bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */ ++/* wrapper function for wf_chspec_ntoa. In case of an error it puts ++ * the original chanspec in the output buffer, prepended with "invalid". ++ * Can be directly used in print routines as it takes care of null ++ */ ++char * ++wf_chspec_ntoa_ex(chanspec_t chspec, char *buf) ++{ ++ if (wf_chspec_ntoa(chspec, buf) == NULL) ++ snprintf(buf, CHANSPEC_STR_LEN, "invalid 0x%04x", chspec); ++ return buf; ++} + -+ if (bitmap != 0U) { ++/* given a chanspec and a string buffer, format the chanspec as a ++ * string, and return the original pointer a. ++ * Min buffer length must be CHANSPEC_STR_LEN. ++ * On error return NULL ++ */ ++char * ++wf_chspec_ntoa(chanspec_t chspec, char *buf) ++{ ++ const char *band; ++ uint ctl_chan; + -+ uint32 count, bitix, *bitmap_p; ++ if (wf_chspec_malformed(chspec)) ++ return NULL; + -+ bitmap_p = &mwbmap_p->wd_bitmap[wordix]; ++ band = ""; + -+ /* clear all except trailing 1 */ -+ bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap)))); -+ MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) == -+ bcm_count_leading_zeros(bitmap)); -+ bitix = (BCM_MWBMAP_BITS_WORD - 1) -+ - bcm_count_leading_zeros(bitmap); /* use asm clz */ -+ wordix = BCM_MWBMAP_MULOP(wordix) + bitix; ++ /* check for non-default band spec */ ++ if ((CHSPEC_IS2G(chspec) && CHSPEC_CHANNEL(chspec) > CH_MAX_2G_CHANNEL) || ++ (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL)) ++ band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g"; + -+ /* Clear bit if wd count is 0, without conditional branch */ -+#if defined(BCM_MWBMAP_USE_CNTSETBITS) -+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1; -+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ -+ mwbmap_p->wd_count[wordix]--; -+ count = mwbmap_p->wd_count[wordix]; -+ MWBMAP_ASSERT(count == -+ (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1)); -+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ -+ MWBMAP_ASSERT(count >= 0); ++ /* ctl channel */ ++ ctl_chan = wf_chspec_ctlchan(chspec); + -+ /* clear wd_bitmap bit if id_map count is 0 */ -+ bitmap = (count == 0) << bitix; ++ /* bandwidth and ctl sideband */ ++ if (CHSPEC_IS20(chspec)) { ++ snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan); ++ } else if (!CHSPEC_IS8080(chspec)) { ++ const char *bw; ++ const char *sb = ""; + -+ MWBMAP_DBG(( -+ "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d", -+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count)); ++ bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT]; + -+ *bitmap_p ^= bitmap; ++#ifdef CHANSPEC_NEW_40MHZ_FORMAT ++ /* ctl sideband string if needed for 2g 40MHz */ ++ if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) { ++ sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; ++ } + -+ /* Use bitix in the second hierarchy */ -+ bitmap_p = &mwbmap_p->id_bitmap[wordix]; ++ snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb); ++#else ++ /* ctl sideband string instead of BW for 40MHz */ ++ if (CHSPEC_IS40(chspec)) { ++ sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; ++ snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb); ++ } else { ++ snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw); ++ } ++#endif /* CHANSPEC_NEW_40MHZ_FORMAT */ + -+ bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */ -+ MWBMAP_ASSERT(bitmap != 0U); ++ } else { ++ /* 80+80 */ ++ uint chan1 = (chspec & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT; ++ uint chan2 = (chspec & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT; + -+ /* clear all except trailing 1 */ -+ bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap)))); -+ MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) == -+ bcm_count_leading_zeros(bitmap)); -+ bitix = BCM_MWBMAP_MULOP(wordix) -+ + (BCM_MWBMAP_BITS_WORD - 1) -+ - bcm_count_leading_zeros(bitmap); /* use asm clz */ ++ /* convert to channel number */ ++ chan1 = (chan1 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan1] : 0; ++ chan2 = (chan2 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan2] : 0; + -+ mwbmap_p->ifree--; /* decrement system wide free count */ -+ MWBMAP_ASSERT(mwbmap_p->ifree >= 0); ++ /* Outputs a max of CHANSPEC_STR_LEN chars including '\0' */ ++ snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", ctl_chan, chan1, chan2); ++ } + -+ MWBMAP_DBG(( -+ "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d", -+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, -+ mwbmap_p->ifree)); ++ return (buf); ++} + -+ *bitmap_p ^= bitmap; /* mark as allocated = 1b0 */ ++static int ++read_uint(const char **p, unsigned int *num) ++{ ++ unsigned long val; ++ char *endp = NULL; + -+ return bitix; -+ } -+ } ++ val = strtoul(*p, &endp, 10); ++ /* if endp is the initial pointer value, then a number was not read */ ++ if (endp == *p) ++ return 0; + -+ ASSERT(mwbmap_p->ifree == 0); ++ /* advance the buffer pointer to the end of the integer string */ ++ *p = endp; ++ /* return the parsed integer */ ++ *num = (unsigned int)val; + -+ return BCM_MWBMAP_INVALID_IDX; ++ return 1; +} + -+/* Force an index at a specified position to be in use */ -+void -+bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) ++/* given a chanspec string, convert to a chanspec. ++ * On error return 0 ++ */ ++chanspec_t ++wf_chspec_aton(const char *a) +{ -+ bcm_mwbmap_t * mwbmap_p; -+ uint32 count, wordix, bitmap, *bitmap_p; ++ chanspec_t chspec; ++ uint chspec_ch, chspec_band, bw, chspec_bw, chspec_sb; ++ uint num, ctl_ch; ++ uint ch1, ch2; ++ char c, sb_ul = '\0'; ++ int i; + -+ BCM_MWBMAP_AUDIT(mwbmap_hdl); -+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ bw = 20; ++ chspec_sb = 0; ++ chspec_ch = ch1 = ch2 = 0; + -+ ASSERT(bitix < mwbmap_p->total); ++ /* parse channel num or band */ ++ if (!read_uint(&a, &num)) ++ return 0; + -+ /* Start with second hierarchy */ -+ wordix = BCM_MWBMAP_DIVOP(bitix); -+ bitmap = (uint32)(1U << BCM_MWBMAP_MODOP(bitix)); -+ bitmap_p = &mwbmap_p->id_bitmap[wordix]; ++ /* if we are looking at a 'g', then the first number was a band */ ++ c = tolower((int)a[0]); ++ if (c == 'g') { ++ a ++; /* consume the char */ + -+ ASSERT((*bitmap_p & bitmap) == bitmap); ++ /* band must be "2" or "5" */ ++ if (num == 2) ++ chspec_band = WL_CHANSPEC_BAND_2G; ++ else if (num == 5) ++ chspec_band = WL_CHANSPEC_BAND_5G; ++ else ++ return 0; + -+ mwbmap_p->ifree--; /* update free count */ -+ ASSERT(mwbmap_p->ifree >= 0); ++ /* read the channel number */ ++ if (!read_uint(&a, &ctl_ch)) ++ return 0; + -+ MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d", -+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, -+ mwbmap_p->ifree)); ++ c = tolower((int)a[0]); ++ } ++ else { ++ /* first number is channel, use default for band */ ++ ctl_ch = num; ++ chspec_band = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? ++ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); ++ } + -+ *bitmap_p ^= bitmap; /* mark as in use */ ++ if (c == '\0') { ++ /* default BW of 20MHz */ ++ chspec_bw = WL_CHANSPEC_BW_20; ++ goto done_read; ++ } + -+ /* Update first hierarchy */ -+ bitix = wordix; ++ a ++; /* consume the 'u','l', or '/' */ + -+ wordix = BCM_MWBMAP_DIVOP(bitix); -+ bitmap_p = &mwbmap_p->wd_bitmap[wordix]; ++ /* check 'u'/'l' */ ++ if (c == 'u' || c == 'l') { ++ sb_ul = c; ++ chspec_bw = WL_CHANSPEC_BW_40; ++ goto done_read; ++ } + -+#if defined(BCM_MWBMAP_USE_CNTSETBITS) -+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]); -+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ -+ mwbmap_p->wd_count[bitix]--; -+ count = mwbmap_p->wd_count[bitix]; -+ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix])); -+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ -+ MWBMAP_ASSERT(count >= 0); ++ /* next letter must be '/' */ ++ if (c != '/') ++ return 0; + -+ bitmap = (count == 0) << BCM_MWBMAP_MODOP(bitix); ++ /* read bandwidth */ ++ if (!read_uint(&a, &bw)) ++ return 0; + -+ MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d", -+ BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap, -+ (*bitmap_p) ^ bitmap, count)); ++ /* convert to chspec value */ ++ if (bw == 20) { ++ chspec_bw = WL_CHANSPEC_BW_20; ++ } else if (bw == 40) { ++ chspec_bw = WL_CHANSPEC_BW_40; ++ } else if (bw == 80) { ++ chspec_bw = WL_CHANSPEC_BW_80; ++ } else if (bw == 160) { ++ chspec_bw = WL_CHANSPEC_BW_160; ++ } else { ++ return 0; ++ } + -+ *bitmap_p ^= bitmap; /* mark as in use */ ++ /* So far we have g/ ++ * Can now be followed by u/l if bw = 40, ++ * or '+80' if bw = 80, to make '80+80' bw. ++ */ + -+ return; -+} ++ c = tolower((int)a[0]); + -+/* Free a previously allocated index back into the multiword bitmap allocator */ -+void BCMFASTPATH -+bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) -+{ -+ bcm_mwbmap_t * mwbmap_p; -+ uint32 wordix, bitmap, *bitmap_p; ++ /* if we have a 2g/40 channel, we should have a l/u spec now */ ++ if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) { ++ if (c == 'u' || c == 'l') { ++ a ++; /* consume the u/l char */ ++ sb_ul = c; ++ goto done_read; ++ } ++ } + -+ BCM_MWBMAP_AUDIT(mwbmap_hdl); -+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ /* check for 80+80 */ ++ if (c == '+') { ++ /* 80+80 */ ++ static const char *plus80 = "80/"; + -+ ASSERT(bitix < mwbmap_p->total); ++ /* must be looking at '+80/' ++ * check and consume this string. ++ */ ++ chspec_bw = WL_CHANSPEC_BW_8080; + -+ /* Start with second level hierarchy */ -+ wordix = BCM_MWBMAP_DIVOP(bitix); -+ bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); -+ bitmap_p = &mwbmap_p->id_bitmap[wordix]; ++ a ++; /* consume the char '+' */ + -+ ASSERT((*bitmap_p & bitmap) == 0U); /* ASSERT not a double free */ ++ /* consume the '80/' string */ ++ for (i = 0; i < 3; i++) { ++ if (*a++ != *plus80++) { ++ return 0; ++ } ++ } + -+ mwbmap_p->ifree++; /* update free count */ -+ ASSERT(mwbmap_p->ifree <= mwbmap_p->total); ++ /* read primary 80MHz channel */ ++ if (!read_uint(&a, &ch1)) ++ return 0; + -+ MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d", -+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, -+ mwbmap_p->ifree)); ++ /* must followed by '-' */ ++ if (a[0] != '-') ++ return 0; ++ a ++; /* consume the char */ + -+ *bitmap_p |= bitmap; /* mark as available */ ++ /* read secondary 80MHz channel */ ++ if (!read_uint(&a, &ch2)) ++ return 0; ++ } + -+ /* Now update first level hierarchy */ ++done_read: ++ /* skip trailing white space */ ++ while (a[0] == ' ') { ++ a ++; ++ } + -+ bitix = wordix; ++ /* must be end of string */ ++ if (a[0] != '\0') ++ return 0; + -+ wordix = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */ -+ bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); -+ bitmap_p = &mwbmap_p->wd_bitmap[wordix]; ++ /* Now have all the chanspec string parts read; ++ * chspec_band, ctl_ch, chspec_bw, sb_ul, ch1, ch2. ++ * chspec_band and chspec_bw are chanspec values. ++ * Need to convert ctl_ch, sb_ul, and ch1,ch2 into ++ * a center channel (or two) and sideband. ++ */ + -+#if !defined(BCM_MWBMAP_USE_CNTSETBITS) -+ mwbmap_p->wd_count[bitix]++; -+#endif ++ /* if a sb u/l string was given, just use that, ++ * guaranteed to be bw = 40 by sting parse. ++ */ ++ if (sb_ul != '\0') { ++ if (sb_ul == 'l') { ++ chspec_ch = UPPER_20_SB(ctl_ch); ++ chspec_sb = WL_CHANSPEC_CTL_SB_LLL; ++ } else if (sb_ul == 'u') { ++ chspec_ch = LOWER_20_SB(ctl_ch); ++ chspec_sb = WL_CHANSPEC_CTL_SB_LLU; ++ } ++ } ++ /* if the bw is 20, center and sideband are trivial */ ++ else if (chspec_bw == WL_CHANSPEC_BW_20) { ++ chspec_ch = ctl_ch; ++ chspec_sb = WL_CHANSPEC_CTL_SB_NONE; ++ } ++ /* if the bw is 40/80/160, not 80+80, a single method ++ * can be used to to find the center and sideband ++ */ ++ else if (chspec_bw != WL_CHANSPEC_BW_8080) { ++ /* figure out ctl sideband based on ctl channel and bandwidth */ ++ const uint8 *center_ch = NULL; ++ int num_ch = 0; ++ int sb = -1; + -+#if defined(BCM_MWBMAP_DEBUG) -+ { -+ uint32 count; -+#if defined(BCM_MWBMAP_USE_CNTSETBITS) -+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]); -+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ -+ count = mwbmap_p->wd_count[bitix]; -+ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix])); -+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ ++ if (chspec_bw == WL_CHANSPEC_BW_40) { ++ center_ch = wf_5g_40m_chans; ++ num_ch = WF_NUM_5G_40M_CHANS; ++ } else if (chspec_bw == WL_CHANSPEC_BW_80) { ++ center_ch = wf_5g_80m_chans; ++ num_ch = WF_NUM_5G_80M_CHANS; ++ } else if (chspec_bw == WL_CHANSPEC_BW_160) { ++ center_ch = wf_5g_160m_chans; ++ num_ch = WF_NUM_5G_160M_CHANS; ++ } else { ++ return 0; ++ } + -+ MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD); ++ for (i = 0; i < num_ch; i ++) { ++ sb = channel_to_sb(center_ch[i], ctl_ch, bw); ++ if (sb >= 0) { ++ chspec_ch = center_ch[i]; ++ chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT; ++ break; ++ } ++ } + -+ MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d", -+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count)); ++ /* check for no matching sb/center */ ++ if (sb < 0) { ++ return 0; ++ } + } -+#endif /* BCM_MWBMAP_DEBUG */ ++ /* Otherwise, bw is 80+80. Figure out channel pair and sb */ ++ else { ++ int ch1_id = 0, ch2_id = 0; ++ int sb; + -+ *bitmap_p |= bitmap; ++ /* look up the channel ID for the specified channel numbers */ ++ ch1_id = channel_80mhz_to_id(ch1); ++ ch2_id = channel_80mhz_to_id(ch2); + -+ return; -+} ++ /* validate channels */ ++ if (ch1_id < 0 || ch2_id < 0) ++ return 0; + -+/* Fetch the toal number of free indices in the multiword bitmap allocator */ -+uint32 -+bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl) -+{ -+ bcm_mwbmap_t * mwbmap_p; ++ /* combine 2 channel IDs in channel field of chspec */ ++ chspec_ch = (((uint)ch1_id << WL_CHANSPEC_CHAN1_SHIFT) | ++ ((uint)ch2_id << WL_CHANSPEC_CHAN2_SHIFT)); + -+ BCM_MWBMAP_AUDIT(mwbmap_hdl); -+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ /* figure out primary 20 MHz sideband */ + -+ ASSERT(mwbmap_p->ifree >= 0); ++ /* is the primary channel contained in the 1st 80MHz channel? */ ++ sb = channel_to_sb(ch1, ctl_ch, bw); ++ if (sb < 0) { ++ /* no match for primary channel 'ctl_ch' in segment0 80MHz channel */ ++ return 0; ++ } + -+ return mwbmap_p->ifree; ++ chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT; ++ } ++ ++ chspec = (chspec_ch | chspec_band | chspec_bw | chspec_sb); ++ ++ if (wf_chspec_malformed(chspec)) ++ return 0; ++ ++ return chspec; +} + -+/* Determine whether an index is inuse or free */ ++/* ++ * Verify the chanspec is using a legal set of parameters, i.e. that the ++ * chanspec specified a band, bw, ctl_sb and channel and that the ++ * combination could be legal given any set of circumstances. ++ * RETURNS: TRUE is the chanspec is malformed, false if it looks good. ++ */ +bool -+bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) ++wf_chspec_malformed(chanspec_t chanspec) +{ -+ bcm_mwbmap_t * mwbmap_p; -+ uint32 wordix, bitmap; ++ uint chspec_bw = CHSPEC_BW(chanspec); ++ uint chspec_ch = CHSPEC_CHANNEL(chanspec); + -+ BCM_MWBMAP_AUDIT(mwbmap_hdl); -+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ /* must be 2G or 5G band */ ++ if (CHSPEC_IS2G(chanspec)) { ++ /* must be valid bandwidth */ ++ if (chspec_bw != WL_CHANSPEC_BW_20 && ++ chspec_bw != WL_CHANSPEC_BW_40) { ++ return TRUE; ++ } ++ } else if (CHSPEC_IS5G(chanspec)) { ++ if (chspec_bw == WL_CHANSPEC_BW_8080) { ++ uint ch1_id, ch2_id; + -+ ASSERT(bitix < mwbmap_p->total); ++ /* channel IDs in 80+80 must be in range */ ++ ch1_id = CHSPEC_CHAN1(chanspec); ++ ch2_id = CHSPEC_CHAN2(chanspec); ++ if (ch1_id >= WF_NUM_5G_80M_CHANS || ch2_id >= WF_NUM_5G_80M_CHANS) ++ return TRUE; + -+ wordix = BCM_MWBMAP_DIVOP(bitix); -+ bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); ++ } else if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40 || ++ chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_160) { + -+ return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U); ++ if (chspec_ch > MAXCHANNEL) { ++ return TRUE; ++ } ++ } else { ++ /* invalid bandwidth */ ++ return TRUE; ++ } ++ } else { ++ /* must be 2G or 5G band */ ++ return TRUE; ++ } ++ ++ /* side band needs to be consistent with bandwidth */ ++ if (chspec_bw == WL_CHANSPEC_BW_20) { ++ if (CHSPEC_CTL_SB(chanspec) != WL_CHANSPEC_CTL_SB_LLL) ++ return TRUE; ++ } else if (chspec_bw == WL_CHANSPEC_BW_40) { ++ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LLU) ++ return TRUE; ++ } else if (chspec_bw == WL_CHANSPEC_BW_80 || ++ chspec_bw == WL_CHANSPEC_BW_8080) { ++ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LUU) ++ return TRUE; ++ } ++ else if (chspec_bw == WL_CHANSPEC_BW_160) { ++ ASSERT(CHSPEC_CTL_SB(chanspec) <= WL_CHANSPEC_CTL_SB_UUU); ++ } ++ return FALSE; +} + -+/* Debug dump a multiword bitmap allocator */ -+void -+bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl) ++/* ++ * Verify the chanspec specifies a valid channel according to 802.11. ++ * RETURNS: TRUE if the chanspec is a valid 802.11 channel ++ */ ++bool ++wf_chspec_valid(chanspec_t chanspec) +{ -+ uint32 ix, count; -+ bcm_mwbmap_t * mwbmap_p; ++ uint chspec_bw = CHSPEC_BW(chanspec); ++ uint chspec_ch = CHSPEC_CHANNEL(chanspec); + -+ BCM_MWBMAP_AUDIT(mwbmap_hdl); -+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ if (wf_chspec_malformed(chanspec)) ++ return FALSE; + -+ printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n", mwbmap_p, -+ mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total); -+ for (ix = 0U; ix < mwbmap_p->wmaps; ix++) { -+ printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]); -+ bcm_bitprint32(mwbmap_p->wd_bitmap[ix]); -+ printf("\n"); -+ } -+ for (ix = 0U; ix < mwbmap_p->imaps; ix++) { -+#if defined(BCM_MWBMAP_USE_CNTSETBITS) -+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]); -+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ -+ count = mwbmap_p->wd_count[ix]; -+ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix])); -+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ -+ printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count); -+ bcm_bitprint32(mwbmap_p->id_bitmap[ix]); -+ printf("\n"); -+ } ++ if (CHSPEC_IS2G(chanspec)) { ++ /* must be valid bandwidth and channel range */ ++ if (chspec_bw == WL_CHANSPEC_BW_20) { ++ if (chspec_ch >= 1 && chspec_ch <= 14) ++ return TRUE; ++ } else if (chspec_bw == WL_CHANSPEC_BW_40) { ++ if (chspec_ch >= 3 && chspec_ch <= 11) ++ return TRUE; ++ } ++ } else if (CHSPEC_IS5G(chanspec)) { ++ if (chspec_bw == WL_CHANSPEC_BW_8080) { ++ uint16 ch1, ch2; + -+ return; -+} ++ ch1 = wf_5g_80m_chans[CHSPEC_CHAN1(chanspec)]; ++ ch2 = wf_5g_80m_chans[CHSPEC_CHAN2(chanspec)]; + -+/* Audit a hierarchical multiword bitmap */ -+void -+bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl) -+{ -+ bcm_mwbmap_t * mwbmap_p; -+ uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p; ++ /* the two channels must be separated by more than 80MHz by VHT req */ ++ if ((ch2 > ch1 + CH_80MHZ_APART) || ++ (ch1 > ch2 + CH_80MHZ_APART)) ++ return TRUE; ++ } else { ++ const uint8 *center_ch; ++ uint num_ch, i; + -+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); ++ if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40) { ++ center_ch = wf_5g_40m_chans; ++ num_ch = WF_NUM_5G_40M_CHANS; ++ } else if (chspec_bw == WL_CHANSPEC_BW_80) { ++ center_ch = wf_5g_80m_chans; ++ num_ch = WF_NUM_5G_80M_CHANS; ++ } else if (chspec_bw == WL_CHANSPEC_BW_160) { ++ center_ch = wf_5g_160m_chans; ++ num_ch = WF_NUM_5G_160M_CHANS; ++ } else { ++ /* invalid bandwidth */ ++ return FALSE; ++ } + -+ for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) { ++ /* check for a valid center channel */ ++ if (chspec_bw == WL_CHANSPEC_BW_20) { ++ /* We don't have an array of legal 20MHz 5G channels, but they are ++ * each side of the legal 40MHz channels. Check the chanspec ++ * channel against either side of the 40MHz channels. ++ */ ++ for (i = 0; i < num_ch; i ++) { ++ if (chspec_ch == (uint)LOWER_20_SB(center_ch[i]) || ++ chspec_ch == (uint)UPPER_20_SB(center_ch[i])) ++ break; /* match found */ ++ } + -+ bitmap_p = &mwbmap_p->wd_bitmap[wordix]; ++ if (i == num_ch) { ++ /* check for channel 165 which is not the side band ++ * of 40MHz 5G channel ++ */ ++ if (chspec_ch == 165) ++ i = 0; + -+ for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) { -+ if ((*bitmap_p) & (1 << bitix)) { -+ idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix; -+#if defined(BCM_MWBMAP_USE_CNTSETBITS) -+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]); -+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ -+ count = mwbmap_p->wd_count[idmap_ix]; -+ ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix])); -+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ -+ ASSERT(count != 0U); -+ free_cnt += count; ++ /* check for legacy JP channels on failure */ ++ if (chspec_ch == 34 || chspec_ch == 38 || ++ chspec_ch == 42 || chspec_ch == 46) ++ i = 0; ++ } ++ } else { ++ /* check the chanspec channel to each legal channel */ ++ for (i = 0; i < num_ch; i ++) { ++ if (chspec_ch == center_ch[i]) ++ break; /* match found */ ++ } ++ } ++ ++ if (i < num_ch) { ++ /* match found */ ++ return TRUE; + } + } + } + -+ ASSERT((int)free_cnt == mwbmap_p->ifree); ++ return FALSE; +} -+/* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */ -+ -+/* Simple 16bit Id allocator using a stack implementation. */ -+typedef struct id16_map { -+ uint16 total; /* total number of ids managed by allocator */ -+ uint16 start; /* start value of 16bit ids to be managed */ -+ uint32 failures; /* count of failures */ -+ void *dbg; /* debug placeholder */ -+ int stack_idx; /* index into stack of available ids */ -+ uint16 stack[0]; /* stack of 16 bit ids */ -+} id16_map_t; + -+#define ID16_MAP_SZ(items) (sizeof(id16_map_t) + \ -+ (sizeof(uint16) * (items))) ++/* ++ * This function returns the channel number that control traffic is being sent on, for 20MHz ++ * channels this is just the channel number, for 40MHZ, 80MHz, 160MHz channels it is the 20MHZ ++ * sideband depending on the chanspec selected ++ */ ++uint8 ++wf_chspec_ctlchan(chanspec_t chspec) ++{ ++ uint center_chan; ++ uint bw_mhz; ++ uint sb; + -+#if defined(BCM_DBG) ++ ASSERT(!wf_chspec_malformed(chspec)); + -+/* Uncomment BCM_DBG_ID16 to debug double free */ -+/* #define BCM_DBG_ID16 */ ++ /* Is there a sideband ? */ ++ if (CHSPEC_IS20(chspec)) { ++ return CHSPEC_CHANNEL(chspec); ++ } else { ++ sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT; + -+typedef struct id16_map_dbg { -+ uint16 total; -+ bool avail[0]; -+} id16_map_dbg_t; -+#define ID16_MAP_DBG_SZ(items) (sizeof(id16_map_dbg_t) + \ -+ (sizeof(bool) * (items))) -+#define ID16_MAP_MSG(x) print x -+#else -+#define ID16_MAP_MSG(x) -+#endif /* BCM_DBG */ ++ if (CHSPEC_IS8080(chspec)) { ++ /* For an 80+80 MHz channel, the sideband 'sb' field is an 80 MHz sideband ++ * (LL, LU, UL, LU) for the 80 MHz frequency segment 0. ++ */ ++ uint chan_id = CHSPEC_CHAN1(chspec); + -+void * /* Construct an id16 allocator: [start_val16 .. start_val16+total_ids) */ -+id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16) -+{ -+ uint16 idx, val16; -+ id16_map_t * id16_map; ++ bw_mhz = 80; + -+ ASSERT(total_ids > 0); -+ ASSERT((start_val16 + total_ids) < ID16_INVALID); ++ /* convert from channel index to channel number */ ++ center_chan = wf_5g_80m_chans[chan_id]; ++ } ++ else { ++ bw_mhz = bw_chspec_to_mhz(chspec); ++ center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT; ++ } + -+ id16_map = (id16_map_t *) MALLOC(osh, ID16_MAP_SZ(total_ids)); -+ if (id16_map == NULL) { -+ return NULL; ++ return (channel_to_ctl_chan(center_chan, bw_mhz, sb)); + } ++} + -+ id16_map->total = total_ids; -+ id16_map->start = start_val16; -+ id16_map->failures = 0; -+ id16_map->dbg = NULL; -+ -+ /* Populate stack with 16bit id values, commencing with start_val16 */ -+ id16_map->stack_idx = 0; -+ val16 = start_val16; -+ -+ for (idx = 0; idx < total_ids; idx++, val16++) { -+ id16_map->stack_idx = idx; -+ id16_map->stack[id16_map->stack_idx] = val16; -+ } ++/* given a chanspec, return the bandwidth string */ ++char * ++wf_chspec_to_bw_str(chanspec_t chspec) ++{ ++ return (char *)wf_chspec_bw_str[(CHSPEC_BW(chspec) >> WL_CHANSPEC_BW_SHIFT)]; ++} + -+#if defined(BCM_DBG) && defined(BCM_DBG_ID16) -+ id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids)); ++/* ++ * This function returns the chanspec of the control channel of a given chanspec ++ */ ++chanspec_t ++wf_chspec_ctlchspec(chanspec_t chspec) ++{ ++ chanspec_t ctl_chspec = chspec; ++ uint8 ctl_chan; + -+ if (id16_map->dbg) { -+ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; ++ ASSERT(!wf_chspec_malformed(chspec)); + -+ id16_map_dbg->total = total_ids; -+ for (idx = 0; idx < total_ids; idx++) { -+ id16_map_dbg->avail[idx] = TRUE; -+ } ++ /* Is there a sideband ? */ ++ if (!CHSPEC_IS20(chspec)) { ++ ctl_chan = wf_chspec_ctlchan(chspec); ++ ctl_chspec = ctl_chan | WL_CHANSPEC_BW_20; ++ ctl_chspec |= CHSPEC_BAND(chspec); + } -+#endif /* BCM_DBG && BCM_DBG_ID16 */ -+ -+ return (void *)id16_map; ++ return ctl_chspec; +} + -+void * /* Destruct an id16 allocator instance */ -+id16_map_fini(osl_t *osh, void * id16_map_hndl) ++/* return chanspec given control channel and bandwidth ++ * return 0 on error ++ */ ++uint16 ++wf_channel2chspec(uint ctl_ch, uint bw) +{ -+ uint16 total_ids; -+ id16_map_t * id16_map; ++ uint16 chspec; ++ const uint8 *center_ch = NULL; ++ int num_ch = 0; ++ int sb = -1; ++ int i = 0; + -+ if (id16_map_hndl == NULL) -+ return NULL; ++ chspec = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); + -+ id16_map = (id16_map_t *)id16_map_hndl; ++ chspec |= bw; + -+ total_ids = id16_map->total; -+ ASSERT(total_ids > 0); ++ if (bw == WL_CHANSPEC_BW_40) { ++ center_ch = wf_5g_40m_chans; ++ num_ch = WF_NUM_5G_40M_CHANS; ++ bw = 40; ++ } else if (bw == WL_CHANSPEC_BW_80) { ++ center_ch = wf_5g_80m_chans; ++ num_ch = WF_NUM_5G_80M_CHANS; ++ bw = 80; ++ } else if (bw == WL_CHANSPEC_BW_160) { ++ center_ch = wf_5g_160m_chans; ++ num_ch = WF_NUM_5G_160M_CHANS; ++ bw = 160; ++ } else if (bw == WL_CHANSPEC_BW_20) { ++ chspec |= ctl_ch; ++ return chspec; ++ } else { ++ return 0; ++ } + -+#if defined(BCM_DBG) && defined(BCM_DBG_ID16) -+ if (id16_map->dbg) { -+ MFREE(osh, id16_map->dbg, ID16_MAP_DBG_SZ(total_ids)); -+ id16_map->dbg = NULL; ++ for (i = 0; i < num_ch; i ++) { ++ sb = channel_to_sb(center_ch[i], ctl_ch, bw); ++ if (sb >= 0) { ++ chspec |= center_ch[i]; ++ chspec |= (sb << WL_CHANSPEC_CTL_SB_SHIFT); ++ break; ++ } ++ } ++ ++ /* check for no matching sb/center */ ++ if (sb < 0) { ++ return 0; + } -+#endif /* BCM_DBG && BCM_DBG_ID16 */ -+ -+ id16_map->total = 0; -+ MFREE(osh, id16_map, ID16_MAP_SZ(total_ids)); + -+ return NULL; ++ return chspec; +} + -+void -+id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16) ++/* ++ * This function returns the chanspec for the primary 40MHz of an 80MHz channel. ++ * The control sideband specifies the same 20MHz channel that the 80MHz channel is using ++ * as the primary 20MHz channel. ++ */ ++extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec) +{ -+ uint16 idx, val16; -+ id16_map_t * id16_map; ++ chanspec_t chspec40 = chspec; ++ uint center_chan; ++ uint sb; + -+ ASSERT(total_ids > 0); -+ ASSERT((start_val16 + total_ids) < ID16_INVALID); ++ ASSERT(!wf_chspec_malformed(chspec)); + -+ id16_map = (id16_map_t *)id16_map_hndl; -+ if (id16_map == NULL) { -+ return; ++ /* if the chanspec is > 80MHz, use the helper routine to find the primary 80 MHz channel */ ++ if (CHSPEC_IS8080(chspec) || CHSPEC_IS160(chspec)) { ++ chspec = wf_chspec_primary80_chspec(chspec); + } + -+ id16_map->total = total_ids; -+ id16_map->start = start_val16; -+ id16_map->failures = 0; ++ /* determine primary 40 MHz sub-channel of an 80 MHz chanspec */ ++ if (CHSPEC_IS80(chspec)) { ++ center_chan = CHSPEC_CHANNEL(chspec); ++ sb = CHSPEC_CTL_SB(chspec); + -+ /* Populate stack with 16bit id values, commencing with start_val16 */ -+ id16_map->stack_idx = 0; -+ val16 = start_val16; ++ if (sb < WL_CHANSPEC_CTL_SB_UL) { ++ /* Primary 40MHz is on lower side */ ++ center_chan -= CH_20MHZ_APART; ++ /* sideband bits are the same for LL/LU and L/U */ ++ } else { ++ /* Primary 40MHz is on upper side */ ++ center_chan += CH_20MHZ_APART; ++ /* sideband bits need to be adjusted by UL offset */ ++ sb -= WL_CHANSPEC_CTL_SB_UL; ++ } + -+ for (idx = 0; idx < total_ids; idx++, val16++) { -+ id16_map->stack_idx = idx; -+ id16_map->stack[id16_map->stack_idx] = val16; ++ /* Create primary 40MHz chanspec */ ++ chspec40 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_40 | ++ sb | center_chan); + } + -+#if defined(BCM_DBG) && defined(BCM_DBG_ID16) -+ if (id16_map->dbg) { -+ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; -+ -+ id16_map_dbg->total = total_ids; -+ for (idx = 0; idx < total_ids; idx++) { -+ id16_map_dbg->avail[idx] = TRUE; -+ } -+ } -+#endif /* BCM_DBG && BCM_DBG_ID16 */ ++ return chspec40; +} + -+uint16 BCMFASTPATH /* Allocate a unique 16bit id */ -+id16_map_alloc(void * id16_map_hndl) ++/* ++ * Return the channel number for a given frequency and base frequency. ++ * The returned channel number is relative to the given base frequency. ++ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for ++ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz. ++ * ++ * Frequency is specified in MHz. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for ++ * 2.4 GHz and 5 GHz bands. ++ * ++ * The returned channel will be in the range [1, 14] in the 2.4 GHz band ++ * and [0, 200] otherwise. ++ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the ++ * frequency is not a 2.4 GHz channel, or if the frequency is not and even ++ * multiple of 5 MHz from the base frequency to the base plus 1 GHz. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ */ ++int ++wf_mhz2channel(uint freq, uint start_factor) +{ -+ uint16 val16; -+ id16_map_t * id16_map; -+ -+ ASSERT(id16_map_hndl != NULL); -+ -+ id16_map = (id16_map_t *)id16_map_hndl; -+ -+ ASSERT(id16_map->total > 0); ++ int ch = -1; ++ uint base; ++ int offset; + -+ if (id16_map->stack_idx < 0) { -+ id16_map->failures++; -+ return ID16_INVALID; ++ /* take the default channel start frequency */ ++ if (start_factor == 0) { ++ if (freq >= 2400 && freq <= 2500) ++ start_factor = WF_CHAN_FACTOR_2_4_G; ++ else if (freq >= 5000 && freq <= 6000) ++ start_factor = WF_CHAN_FACTOR_5_G; + } + -+ val16 = id16_map->stack[id16_map->stack_idx]; -+ id16_map->stack_idx--; ++ if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G) ++ return 14; + -+#if defined(BCM_DBG) && defined(BCM_DBG_ID16) ++ base = start_factor / 2; + -+ ASSERT(val16 < (id16_map->start + id16_map->total)); ++ /* check that the frequency is in 1GHz range of the base */ ++ if ((freq < base) || (freq > base + 1000)) ++ return -1; + -+ if (id16_map->dbg) { /* Validate val16 */ -+ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; ++ offset = freq - base; ++ ch = offset / 5; + -+ ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == TRUE); -+ id16_map_dbg->avail[val16 - id16_map->start] = FALSE; -+ } -+#endif /* BCM_DBG && BCM_DBG_ID16 */ ++ /* check that frequency is a 5MHz multiple from the base */ ++ if (offset != (ch * 5)) ++ return -1; + -+ return val16; -+} ++ /* restricted channel range check for 2.4G */ ++ if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13)) ++ return -1; + ++ return ch; ++} + -+void BCMFASTPATH /* Free a 16bit id value into the id16 allocator */ -+id16_map_free(void * id16_map_hndl, uint16 val16) ++/* ++ * Return the center frequency in MHz of the given channel and base frequency. ++ * The channel number is interpreted relative to the given base frequency. ++ * ++ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise. ++ * The base frequency is specified as (start_factor * 500 kHz). ++ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_4_G, and WF_CHAN_FACTOR_5_G ++ * are defined for 2.4 GHz, 4 GHz, and 5 GHz bands. ++ * The channel range of [1, 14] is only checked for a start_factor of ++ * WF_CHAN_FACTOR_2_4_G (4814 = 2407 * 2). ++ * Odd start_factors produce channels on .5 MHz boundaries, in which case ++ * the answer is rounded down to an integral MHz. ++ * -1 is returned for an out of range channel. ++ * ++ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 ++ */ ++int ++wf_channel2mhz(uint ch, uint start_factor) +{ -+ id16_map_t * id16_map; ++ int freq; + -+ ASSERT(id16_map_hndl != NULL); ++ if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) || ++ (ch > 200)) ++ freq = -1; ++ else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14)) ++ freq = 2484; ++ else ++ freq = ch * 5 + start_factor / 2; + -+ id16_map = (id16_map_t *)id16_map_hndl; ++ return freq; ++} + -+#if defined(BCM_DBG) && defined(BCM_DBG_ID16) ++static const uint16 sidebands[] = { ++ WL_CHANSPEC_CTL_SB_LLL, WL_CHANSPEC_CTL_SB_LLU, ++ WL_CHANSPEC_CTL_SB_LUL, WL_CHANSPEC_CTL_SB_LUU, ++ WL_CHANSPEC_CTL_SB_ULL, WL_CHANSPEC_CTL_SB_ULU, ++ WL_CHANSPEC_CTL_SB_UUL, WL_CHANSPEC_CTL_SB_UUU ++}; + -+ ASSERT(val16 < (id16_map->start + id16_map->total)); ++/* ++ * Returns the chanspec 80Mhz channel corresponding to the following input ++ * parameters ++ * ++ * primary_channel - primary 20Mhz channel ++ * center_channel - center frequecny of the 80Mhz channel ++ * ++ * The center_channel can be one of {42, 58, 106, 122, 138, 155} ++ * ++ * returns INVCHANSPEC in case of error ++ */ ++chanspec_t ++wf_chspec_80(uint8 center_channel, uint8 primary_channel) ++{ + -+ if (id16_map->dbg) { /* Validate val16 */ -+ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; ++ chanspec_t chanspec = INVCHANSPEC; ++ chanspec_t chanspec_cur; ++ uint i; + -+ ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == FALSE); -+ id16_map_dbg->avail[val16 - id16_map->start] = TRUE; ++ for (i = 0; i < WF_NUM_SIDEBANDS_80MHZ; i++) { ++ chanspec_cur = CH80MHZ_CHSPEC(center_channel, sidebands[i]); ++ if (primary_channel == wf_chspec_ctlchan(chanspec_cur)) { ++ chanspec = chanspec_cur; ++ break; ++ } + } -+#endif /* BCM_DBG && BCM_DBG_ID16 */ -+ -+ id16_map->stack_idx++; -+ id16_map->stack[id16_map->stack_idx] = val16; -+} -+ -+uint32 /* Returns number of failures to allocate an unique id16 */ -+id16_map_failures(void * id16_map_hndl) -+{ -+ ASSERT(id16_map_hndl != NULL); -+ return ((id16_map_t *)id16_map_hndl)->failures; ++ /* If the loop ended early, we are good, otherwise we did not ++ * find a 80MHz chanspec with the given center_channel that had a primary channel ++ *matching the given primary_channel. ++ */ ++ return chanspec; +} + -+bool -+id16_map_audit(void * id16_map_hndl) ++/* ++ * Returns the 80+80 chanspec corresponding to the following input parameters ++ * ++ * primary_20mhz - Primary 20 MHz channel ++ * chan0 - center channel number of one frequency segment ++ * chan1 - center channel number of the other frequency segment ++ * ++ * Parameters chan0 and chan1 are channel numbers in {42, 58, 106, 122, 138, 155}. ++ * The primary channel must be contained in one of the 80MHz channels. This routine ++ * will determine which frequency segment is the primary 80 MHz segment. ++ * ++ * Returns INVCHANSPEC in case of error. ++ * ++ * Refer to IEEE802.11ac section 22.3.14 "Channelization". ++ */ ++chanspec_t ++wf_chspec_get8080_chspec(uint8 primary_20mhz, uint8 chan0, uint8 chan1) +{ -+ int idx; -+ int insane = 0; -+ id16_map_t * id16_map; -+ -+ ASSERT(id16_map_hndl != NULL); ++ int sb = 0; ++ uint16 chanspec = 0; ++ int chan0_id = 0, chan1_id = 0; ++ int seg0, seg1; + -+ id16_map = (id16_map_t *)id16_map_hndl; ++ chan0_id = channel_80mhz_to_id(chan0); ++ chan1_id = channel_80mhz_to_id(chan1); + -+ ASSERT((id16_map->stack_idx > 0) && (id16_map->stack_idx < id16_map->total)); -+ for (idx = 0; idx <= id16_map->stack_idx; idx++) { -+ ASSERT(id16_map->stack[idx] >= id16_map->start); -+ ASSERT(id16_map->stack[idx] < (id16_map->start + id16_map->total)); ++ /* make sure the channel numbers were valid */ ++ if (chan0_id == -1 || chan1_id == -1) ++ return INVCHANSPEC; + -+#if defined(BCM_DBG) && defined(BCM_DBG_ID16) -+ if (id16_map->dbg) { -+ uint16 val16 = id16_map->stack[idx]; -+ if (((id16_map_dbg_t *)(id16_map->dbg))->avail[val16] != TRUE) { -+ insane |= 1; -+ ID16_MAP_MSG(("id16_map<%p>: stack_idx %u invalid val16 %u\n", -+ id16_map_hndl, idx, val16)); -+ } ++ /* does the primary channel fit with the 1st 80MHz channel ? */ ++ sb = channel_to_sb(chan0, primary_20mhz, 80); ++ if (sb >= 0) { ++ /* yes, so chan0 is frequency segment 0, and chan1 is seg 1 */ ++ seg0 = chan0_id; ++ seg1 = chan1_id; ++ } else { ++ /* no, so does the primary channel fit with the 2nd 80MHz channel ? */ ++ sb = channel_to_sb(chan1, primary_20mhz, 80); ++ if (sb < 0) { ++ /* no match for ctl_ch to either 80MHz center channel */ ++ return INVCHANSPEC; + } -+#endif /* BCM_DBG && BCM_DBG_ID16 */ ++ /* swapped, so chan1 is frequency segment 0, and chan0 is seg 1 */ ++ seg0 = chan1_id; ++ seg1 = chan0_id; + } + -+#if defined(BCM_DBG) && defined(BCM_DBG_ID16) -+ if (id16_map->dbg) { -+ uint16 avail = 0; /* Audit available ids counts */ -+ for (idx = 0; idx < id16_map_dbg->total; idx++) { -+ if (((id16_map_dbg_t *)(id16_map->dbg))->avail[idx16] == TRUE) -+ avail++; -+ } -+ if (avail && (avail != (id16_map->stack_idx + 1))) { -+ insane |= 1; -+ ID16_MAP_MSG(("id16_map<%p>: avail %u stack_idx %u\n", -+ id16_map_hndl, avail, id16_map->stack_idx)); -+ } -+ } -+#endif /* BCM_DBG && BCM_DBG_ID16 */ ++ chanspec = ((seg0 << WL_CHANSPEC_CHAN1_SHIFT) | ++ (seg1 << WL_CHANSPEC_CHAN2_SHIFT) | ++ (sb << WL_CHANSPEC_CTL_SB_SHIFT) | ++ WL_CHANSPEC_BW_8080 | ++ WL_CHANSPEC_BAND_5G); + -+ return (!!insane); ++ return chanspec; +} -+/* END: Simple id16 allocator */ + ++/* ++ * This function returns the 80Mhz channel for the given id. ++ */ ++static uint8 ++wf_chspec_get80Mhz_ch(uint8 chan_80Mhz_id) ++{ ++ if (chan_80Mhz_id < WF_NUM_5G_80M_CHANS) ++ return wf_5g_80m_chans[chan_80Mhz_id]; + -+#endif /* BCMDRIVER */ ++ return 0; ++} + -+/* calculate a >> b; and returns only lower 32 bits */ -+void -+bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b) ++/* ++ * Returns the primary 80 Mhz channel for the provided chanspec ++ * ++ * chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved ++ * ++ * returns -1 in case the provided channel is 20/40 Mhz chanspec ++ */ ++ ++uint8 ++wf_chspec_primary80_channel(chanspec_t chanspec) +{ -+ uint32 a1 = a_high, a0 = a_low, r0 = 0; ++ uint8 primary80_chan; + -+ if (b == 0) { -+ r0 = a_low; -+ *r = r0; -+ return; ++ if (CHSPEC_IS80(chanspec)) { ++ primary80_chan = CHSPEC_CHANNEL(chanspec); + } -+ -+ if (b < 32) { -+ a0 = a0 >> b; -+ a1 = a1 & ((1 << b) - 1); -+ a1 = a1 << (32 - b); -+ r0 = a0 | a1; -+ *r = r0; -+ return; -+ } else { -+ r0 = a1 >> (b - 32); -+ *r = r0; -+ return; ++ else if (CHSPEC_IS8080(chanspec)) { ++ /* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */ ++ primary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chanspec)); + } ++ else if (CHSPEC_IS160(chanspec)) { ++ uint8 center_chan = CHSPEC_CHANNEL(chanspec); ++ uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT; + ++ /* based on the sb value primary 80 channel can be retrieved ++ * if sb is in range 0 to 3 the lower band is the 80Mhz primary band ++ */ ++ if (sb < 4) { ++ primary80_chan = center_chan - CH_40MHZ_APART; ++ } ++ /* if sb is in range 4 to 7 the upper band is the 80Mhz primary band */ ++ else ++ { ++ primary80_chan = center_chan + CH_40MHZ_APART; ++ } ++ } ++ else { ++ /* for 20 and 40 Mhz */ ++ primary80_chan = -1; ++ } ++ return primary80_chan; +} + -+/* calculate a + b where a is a 64 bit number and b is a 32 bit number */ -+void -+bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset) -+{ -+ uint32 r1_lo = *r_lo; -+ (*r_lo) += offset; -+ if (*r_lo < r1_lo) -+ (*r_hi) ++; -+} -+ -+/* calculate a - b where a is a 64 bit number and b is a 32 bit number */ -+void -+bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset) -+{ -+ uint32 r1_lo = *r_lo; -+ (*r_lo) -= offset; -+ if (*r_lo > r1_lo) -+ (*r_hi) --; -+} -+ -+#ifdef DEBUG_COUNTER -+#if (OSL_SYSUPTIME_SUPPORT == TRUE) -+void counter_printlog(counter_tbl_t *ctr_tbl) ++/* ++ * Returns the secondary 80 Mhz channel for the provided chanspec ++ * ++ * chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved ++ * ++ * returns -1 in case the provided channel is 20/40/80 Mhz chanspec ++ */ ++uint8 ++wf_chspec_secondary80_channel(chanspec_t chanspec) +{ -+ uint32 now; -+ -+ if (!ctr_tbl->enabled) -+ return; -+ -+ now = OSL_SYSUPTIME(); ++ uint8 secondary80_chan; + -+ if (now - ctr_tbl->prev_log_print > ctr_tbl->log_print_interval) { -+ uint8 i = 0; -+ printf("counter_print(%s %d):", ctr_tbl->name, now - ctr_tbl->prev_log_print); ++ if (CHSPEC_IS8080(chanspec)) { ++ secondary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chanspec)); ++ } ++ else if (CHSPEC_IS160(chanspec)) { ++ uint8 center_chan = CHSPEC_CHANNEL(chanspec); ++ uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT; + -+ for (i = 0; i < ctr_tbl->needed_cnt; i++) { -+ printf(" %u", ctr_tbl->cnt[i]); ++ /* based on the sb value secondary 80 channel can be retrieved ++ * if sb is in range 0 to 3 upper band is the secondary 80Mhz band ++ */ ++ if (sb < 4) { ++ secondary80_chan = center_chan + CH_40MHZ_APART; + } -+ printf("\n"); -+ -+ ctr_tbl->prev_log_print = now; -+ bzero(ctr_tbl->cnt, CNTR_TBL_MAX * sizeof(uint)); ++ /* if sb is in range 4 to 7 the lower band is the secondary 80Mhz band */ ++ else ++ { ++ secondary80_chan = center_chan - CH_40MHZ_APART; ++ } ++ } ++ else { ++ /* for 20, 40, and 80 Mhz */ ++ secondary80_chan = -1; + } ++ return secondary80_chan; +} -+#else -+/* OSL_SYSUPTIME is not supported so no way to get time */ -+#define counter_printlog(a) do {} while (0) -+#endif /* OSL_SYSUPTIME_SUPPORT == TRUE */ -+#endif /* DEBUG_COUNTER */ + -+#ifdef BCMDRIVER -+void -+dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size) -+{ -+ uint32 mem_size; -+ mem_size = sizeof(dll_pool_t) + (elems_max * elem_size); -+ if (pool) -+ MFREE(osh, pool, mem_size); -+} -+dll_pool_t * -+dll_pool_init(void * osh, uint16 elems_max, uint16 elem_size) ++/* ++ * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel. ++ * ++ * chanspec - Input chanspec for which the primary 80Mhz chanspec has to be retreived ++ * ++ * returns the input chanspec in case the provided chanspec is an 80 MHz chanspec ++ * returns INVCHANSPEC in case the provided channel is 20/40 MHz chanspec ++ */ ++chanspec_t ++wf_chspec_primary80_chspec(chanspec_t chspec) +{ -+ uint32 mem_size, i; -+ dll_pool_t * dll_pool_p; -+ dll_t * elem_p; -+ -+ ASSERT(elem_size > sizeof(dll_t)); -+ -+ mem_size = sizeof(dll_pool_t) + (elems_max * elem_size); ++ chanspec_t chspec80; ++ uint center_chan; ++ uint sb; + -+ if ((dll_pool_p = (dll_pool_t *)MALLOC(osh, mem_size)) == NULL) { -+ printf("dll_pool_init: elems_max<%u> elem_size<%u> malloc failure\n", -+ elems_max, elem_size); -+ ASSERT(0); -+ return dll_pool_p; ++ ASSERT(!wf_chspec_malformed(chspec)); ++ if (CHSPEC_IS80(chspec)) { ++ chspec80 = chspec; + } ++ else if (CHSPEC_IS8080(chspec)) { + -+ bzero(dll_pool_p, mem_size); ++ /* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */ ++ center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec)); + -+ dll_init(&dll_pool_p->free_list); -+ dll_pool_p->elems_max = elems_max; -+ dll_pool_p->elem_size = elem_size; ++ sb = CHSPEC_CTL_SB(chspec); + -+ elem_p = dll_pool_p->elements; -+ for (i = 0; i < elems_max; i++) { -+ dll_append(&dll_pool_p->free_list, elem_p); -+ elem_p = (dll_t *)((uintptr)elem_p + elem_size); ++ /* Create primary 80MHz chanspec */ ++ chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan); + } ++ else if (CHSPEC_IS160(chspec)) { ++ center_chan = CHSPEC_CHANNEL(chspec); ++ sb = CHSPEC_CTL_SB(chspec); + -+ dll_pool_p->free_count = elems_max; -+ -+ return dll_pool_p; -+} -+ -+ -+void * -+dll_pool_alloc(dll_pool_t * dll_pool_p) -+{ -+ dll_t * elem_p; -+ -+ if (dll_pool_p->free_count == 0) { -+ ASSERT(dll_empty(&dll_pool_p->free_list)); -+ return NULL; ++ if (sb < WL_CHANSPEC_CTL_SB_ULL) { ++ /* Primary 80MHz is on lower side */ ++ center_chan -= CH_40MHZ_APART; ++ } ++ else { ++ /* Primary 80MHz is on upper side */ ++ center_chan += CH_40MHZ_APART; ++ sb -= WL_CHANSPEC_CTL_SB_ULL; ++ } ++ /* Create primary 80MHz chanspec */ ++ chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan); ++ } ++ else { ++ chspec80 = INVCHANSPEC; + } + -+ elem_p = dll_head_p(&dll_pool_p->free_list); -+ dll_delete(elem_p); -+ dll_pool_p->free_count -= 1; -+ -+ return (void *)elem_p; -+} -+ -+void -+dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p) -+{ -+ dll_t * node_p = (dll_t *)elem_p; -+ dll_prepend(&dll_pool_p->free_list, node_p); -+ dll_pool_p->free_count += 1; ++ return chspec80; +} + -+ -+void -+dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p) ++#ifdef WL11AC_80P80 ++uint8 ++wf_chspec_channel(chanspec_t chspec) +{ -+ dll_t * node_p = (dll_t *)elem_p; -+ dll_append(&dll_pool_p->free_list, node_p); -+ dll_pool_p->free_count += 1; ++ if (CHSPEC_IS8080(chspec)) { ++ return wf_chspec_primary80_channel(chspec); ++ } ++ else { ++ return ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)); ++ } +} -+ -+#endif /* BCMDRIVER */ -diff -ENwbur a/drivers/net/wireless/bcm4336/bcmwifi_channels.c b/drivers/net/wireless/bcm4336/bcmwifi_channels.c ---- a/drivers/net/wireless/bcm4336/bcmwifi_channels.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/bcmwifi_channels.c 2018-05-06 08:49:50.618753851 +0200 -@@ -0,0 +1,1211 @@ -+/* -+ * Misc utility routines used by kernel or app-level. -+ * Contents are wifi-specific, used by any kernel or app-level -+ * software that might want wifi things as it grows. ++#endif /* WL11AC_80P80 */ +diff --git a/drivers/net/wireless/bcm4336/circularbuf.c b/drivers/net/wireless/bcm4336/circularbuf.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/circularbuf.c +@@ -0,0 +1,324 @@ ++/** @file circularbuf.c ++ * ++ * PCIe host driver and dongle firmware need to communicate with each other. The mechanism consists ++ * of multiple circular buffers located in (DMA'able) host memory. A circular buffer is either used ++ * for host -> dongle (h2d) or dongle -> host communication. Both host driver and firmware make use ++ * of this source file. This source file contains functions to manage such a set of circular ++ * buffers, but does not contain the code to read or write the data itself into the buffers. It ++ * leaves that up to the software layer that uses this file, which can be implemented either using ++ * pio or DMA transfers. It also leaves the format of the data that is written and read to a higher ++ * layer. Typically the data is in the form of so-called 'message buffers'. + * + * $Copyright Open Broadcom Corporation$ -+ * $Id: bcmwifi_channels.c 309193 2012-01-19 00:03:57Z $ ++ * ++ * $Id: circularbuf.c 467150 2014-04-02 17:30:43Z $ + */ + -+#include -+#include -+#include -+ -+#ifdef BCMDRIVER ++#include ++#include +#include -+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) -+#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) -+#else -+#include -+#include -+#include -+#ifndef ASSERT -+#define ASSERT(exp) -+#endif -+#endif /* BCMDRIVER */ + -+#include ++#define CIRCULARBUF_READ_SPACE_AT_END(x) \ ++ ((x->w_ptr >= x->rp_ptr) ? (x->w_ptr - x->rp_ptr) : (x->e_ptr - x->rp_ptr)) + -+#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL)) -+#include /* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */ -+#endif ++#define CIRCULARBUF_READ_SPACE_AVAIL(x) \ ++ (((CIRCULARBUF_READ_SPACE_AT_END(x) == 0) && (x->w_ptr < x->rp_ptr)) ? \ ++ x->w_ptr : CIRCULARBUF_READ_SPACE_AT_END(x)) + -+/* Definitions for D11AC capable Chanspec type */ ++int cbuf_msg_level = CBUF_ERROR_VAL | CBUF_TRACE_VAL | CBUF_INFORM_VAL; + -+/* Chanspec ASCII representation with 802.11ac capability: -+ * [ 'g'] ['/' []['/'<1st80channel>'-'<2nd80channel>]] -+ * -+ * : -+ * (optional) 2, 3, 4, 5 for 2.4GHz, 3GHz, 4GHz, and 5GHz respectively. -+ * Default value is 2g if channel <= 14, otherwise 5g. -+ * : -+ * channel number of the 5MHz, 10MHz, 20MHz channel, -+ * or primary channel of 40MHz, 80MHz, 160MHz, or 80+80MHz channel. -+ * : -+ * (optional) 5, 10, 20, 40, 80, 160, or 80+80. Default value is 20. -+ * : -+ * (only for 2.4GHz band 40MHz) U for upper sideband primary, L for lower. -+ * -+ * For 2.4GHz band 40MHz channels, the same primary channel may be the -+ * upper sideband for one 40MHz channel, and the lower sideband for an -+ * overlapping 40MHz channel. The U/L disambiguates which 40MHz channel -+ * is being specified. -+ * -+ * For 40MHz in the 5GHz band and all channel bandwidths greater than -+ * 40MHz, the U/L specificaion is not allowed since the channels are -+ * non-overlapping and the primary sub-band is derived from its -+ * position in the wide bandwidth channel. -+ * -+ * <1st80Channel>: -+ * <2nd80Channel>: -+ * Required for 80+80, otherwise not allowed. -+ * Specifies the center channel of the first and second 80MHz band. ++/* #define CBUF_DEBUG */ ++#ifdef CBUF_DEBUG ++#define CBUF_DEBUG_CHECK(x) x ++#else ++#define CBUF_DEBUG_CHECK(x) ++#endif /* CBUF_DEBUG */ ++ ++/** ++ * ----------------------------------------------------------------------------- ++ * Function : circularbuf_init ++ * Description: + * -+ * In its simplest form, it is a 20MHz channel number, with the implied band -+ * of 2.4GHz if channel number <= 14, and 5GHz otherwise. + * -+ * To allow for backward compatibility with scripts, the old form for -+ * 40MHz channels is also allowed: ++ * Input Args : buf_base_addr: address of DMA'able host memory provided by caller + * -+ * : -+ * primary channel of 40MHz, channel <= 14 is 2GHz, otherwise 5GHz -+ * : -+ * "U" for upper, "L" for lower (or lower case "u" "l") + * -+ * 5 GHz Examples: -+ * Chanspec BW Center Ch Channel Range Primary Ch -+ * 5g8 20MHz 8 - - -+ * 52 20MHz 52 - - -+ * 52/40 40MHz 54 52-56 52 -+ * 56/40 40MHz 54 52-56 56 -+ * 52/80 80MHz 58 52-64 52 -+ * 56/80 80MHz 58 52-64 56 -+ * 60/80 80MHz 58 52-64 60 -+ * 64/80 80MHz 58 52-64 64 -+ * 52/160 160MHz 50 36-64 52 -+ * 36/160 160MGz 50 36-64 36 -+ * 36/80+80/42-106 80+80MHz 42,106 36-48,100-112 36 ++ * Return Values : + * -+ * 2 GHz Examples: -+ * Chanspec BW Center Ch Channel Range Primary Ch -+ * 2g8 20MHz 8 - - -+ * 8 20MHz 8 - - -+ * 6 20MHz 6 - - -+ * 6/40l 40MHz 8 6-10 6 -+ * 6l 40MHz 8 6-10 6 -+ * 6/40u 40MHz 4 2-6 6 -+ * 6u 40MHz 4 2-6 6 ++ * ----------------------------------------------------------------------------- + */ -+ -+/* bandwidth ASCII string */ -+static const char *wf_chspec_bw_str[] = ++void ++circularbuf_init(circularbuf_t *handle, void *buf_base_addr, uint16 total_buf_len) +{ -+ "5", -+ "10", -+ "20", -+ "40", -+ "80", -+ "160", -+ "80+80", -+ "na" -+}; -+ -+static const uint8 wf_chspec_bw_mhz[] = -+{5, 10, 20, 40, 80, 160, 160}; -+ -+#define WF_NUM_BW \ -+ (sizeof(wf_chspec_bw_mhz)/sizeof(uint8)) -+ -+/* 40MHz channels in 5GHz band */ -+static const uint8 wf_5g_40m_chans[] = -+{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159}; -+#define WF_NUM_5G_40M_CHANS \ -+ (sizeof(wf_5g_40m_chans)/sizeof(uint8)) -+ -+/* 80MHz channels in 5GHz band */ -+static const uint8 wf_5g_80m_chans[] = -+{42, 58, 106, 122, 138, 155}; -+#define WF_NUM_5G_80M_CHANS \ -+ (sizeof(wf_5g_80m_chans)/sizeof(uint8)) -+ -+/* 160MHz channels in 5GHz band */ -+static const uint8 wf_5g_160m_chans[] = -+{50, 114}; -+#define WF_NUM_5G_160M_CHANS \ -+ (sizeof(wf_5g_160m_chans)/sizeof(uint8)) ++ handle->buf_addr = buf_base_addr; + ++ handle->depth = handle->e_ptr = HTOL32(total_buf_len); + -+/* convert bandwidth from chanspec to MHz */ -+static uint -+bw_chspec_to_mhz(chanspec_t chspec) -+{ -+ uint bw; ++ /* Initialize Read and Write pointers */ ++ handle->w_ptr = handle->r_ptr = handle->wp_ptr = handle->rp_ptr = HTOL32(0); ++ handle->mb_ring_bell = NULL; ++ handle->mb_ctx = NULL; + -+ bw = (chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT; -+ return (bw >= WF_NUM_BW ? 0 : wf_chspec_bw_mhz[bw]); ++ return; +} + -+/* bw in MHz, return the channel count from the center channel to the -+ * the channel at the edge of the band ++/** ++ * When an item is added to the circular buffer by the producing party, the consuming party has to ++ * be notified by means of a 'door bell' or 'ring'. This function allows the caller to register a ++ * 'ring' function that will be called when a 'write complete' occurs. + */ -+static uint8 -+center_chan_to_edge(uint bw) ++void ++circularbuf_register_cb(circularbuf_t *handle, mb_ring_t mb_ring_func, void *ctx) +{ -+ /* edge channels separated by BW - 10MHz on each side -+ * delta from cf to edge is half of that, -+ * MHz to channel num conversion is 5MHz/channel -+ */ -+ return (uint8)(((bw - 20) / 2) / 5); ++ handle->mb_ring_bell = mb_ring_func; ++ handle->mb_ctx = ctx; +} + -+/* return channel number of the low edge of the band -+ * given the center channel and BW -+ */ -+static uint8 -+channel_low_edge(uint center_ch, uint bw) ++#ifdef CBUF_DEBUG ++static void ++circularbuf_check_sanity(circularbuf_t *handle) +{ -+ return (uint8)(center_ch - center_chan_to_edge(bw)); ++ if ((handle->e_ptr > handle->depth) || ++ (handle->r_ptr > handle->e_ptr) || ++ (handle->rp_ptr > handle->e_ptr) || ++ (handle->w_ptr > handle->e_ptr)) ++ { ++ printf("%s:%d: Pointers are corrupted.\n", __FUNCTION__, __LINE__); ++ circularbuf_debug_print(handle); ++ ASSERT(0); ++ } ++ return; +} ++#endif /* CBUF_DEBUG */ + -+/* return side band number given center channel and control channel -+ * return -1 on error ++/** ++ * ----------------------------------------------------------------------------- ++ * Function : circularbuf_reserve_for_write ++ * ++ * Description: ++ * This function reserves N bytes for write in the circular buffer. The circularbuf ++ * implementation will only reserve space in the circular buffer and return ++ * the pointer to the address where the new data can be written. ++ * The actual write implementation (bcopy/dma) is outside the scope of ++ * circularbuf implementation. ++ * ++ * Input Args : ++ * size - No. of bytes to reserve for write ++ * ++ * Return Values : ++ * void * : Pointer to the reserved location. This is the address ++ * that will be used for write (dma/bcopy) ++ * ++ * ----------------------------------------------------------------------------- + */ -+static int -+channel_to_sb(uint center_ch, uint ctl_ch, uint bw) ++void * BCMFASTPATH ++circularbuf_reserve_for_write(circularbuf_t *handle, uint16 size) +{ -+ uint lowest = channel_low_edge(center_ch, bw); -+ uint sb; ++ int16 avail_space; ++ void *ret_ptr = NULL; + -+ if ((ctl_ch - lowest) % 4) { -+ /* bad ctl channel, not mult 4 */ -+ return -1; -+ } ++ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle)); ++ ASSERT(size < handle->depth); + -+ sb = ((ctl_ch - lowest) / 4); ++ if (handle->wp_ptr >= handle->r_ptr) ++ avail_space = handle->depth - handle->wp_ptr; ++ else ++ avail_space = handle->r_ptr - handle->wp_ptr; + -+ /* sb must be a index to a 20MHz channel in range */ -+ if (sb >= (bw / 20)) { -+ /* ctl_ch must have been too high for the center_ch */ -+ return -1; ++ ASSERT(avail_space <= handle->depth); ++ if (avail_space > size) ++ { ++ /* Great. We have enough space. */ ++ ret_ptr = CIRCULARBUF_START(handle) + handle->wp_ptr; ++ ++ /* ++ * We need to update the wp_ptr for the next guy to write. ++ * ++ * Please Note : We are not updating the write pointer here. This can be ++ * done only after write is complete (In case of DMA, we can only schedule ++ * the DMA. Actual completion will be known only on DMA complete interrupt). ++ */ ++ handle->wp_ptr += size; ++ return ret_ptr; + } + -+ return sb; -+} ++ /* ++ * If there is no available space, we should check if there is some space left ++ * in the beginning of the circular buffer. Wrap-around case, where there is ++ * not enough space in the end of the circular buffer. But, there might be ++ * room in the beginning of the buffer. ++ */ ++ if (handle->wp_ptr >= handle->r_ptr) ++ { ++ avail_space = handle->r_ptr; ++ if (avail_space > size) ++ { ++ /* OK. There is room in the beginning. Let's go ahead and use that. ++ * But, before that, we have left a hole at the end of the circular ++ * buffer as that was not sufficient to accomodate the requested ++ * size. Let's make sure this is updated in the circularbuf structure ++ * so that consumer does not use the hole. ++ */ ++ handle->e_ptr = handle->wp_ptr; ++ handle->wp_ptr = size; + -+/* return control channel given center channel and side band */ -+static uint8 -+channel_to_ctl_chan(uint center_ch, uint bw, uint sb) -+{ -+ return (uint8)(channel_low_edge(center_ch, bw) + sb * 4); ++ return CIRCULARBUF_START(handle); ++ } ++ } ++ ++ /* We have tried enough to accomodate the new packet. There is no room for now. */ ++ return NULL; +} + -+/* return index of 80MHz channel from channel number -+ * return -1 on error ++/** ++ * ----------------------------------------------------------------------------- ++ * Function : circularbuf_write_complete ++ * ++ * Description: ++ * This function has to be called by the producer end of circularbuf to indicate to ++ * the circularbuf layer that data has been written and the write pointer can be ++ * updated. In the process, if there was a doorbell callback registered, that ++ * function would also be invoked as to notify the consuming party. ++ * ++ * Input Args : ++ * dest_addr : Address where the data was written. This would be the ++ * same address that was reserved earlier. ++ * bytes_written : Length of data written ++ * ++ * ----------------------------------------------------------------------------- + */ -+static int -+channel_80mhz_to_id(uint ch) ++void BCMFASTPATH ++circularbuf_write_complete(circularbuf_t *handle, uint16 bytes_written) +{ -+ uint i; -+ for (i = 0; i < WF_NUM_5G_80M_CHANS; i ++) { -+ if (ch == wf_5g_80m_chans[i]) -+ return i; ++ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle)); ++ ++ /* Update the write pointer */ ++ if ((handle->w_ptr + bytes_written) >= handle->depth) { ++ OSL_CACHE_FLUSH((void *) CIRCULARBUF_START(handle), bytes_written); ++ handle->w_ptr = bytes_written; ++ } else { ++ OSL_CACHE_FLUSH((void *) (CIRCULARBUF_START(handle) + handle->w_ptr), ++ bytes_written); ++ handle->w_ptr += bytes_written; + } + -+ return -1; ++ /* And ring the door bell (mail box interrupt) to indicate to the peer that ++ * message is available for consumption. ++ */ ++ if (handle->mb_ring_bell) ++ handle->mb_ring_bell(handle->mb_ctx); +} + -+/* wrapper function for wf_chspec_ntoa. In case of an error it puts -+ * the original chanspec in the output buffer, prepended with "invalid". -+ * Can be directly used in print routines as it takes care of null ++/** ++ * ----------------------------------------------------------------------------- ++ * Function : circularbuf_get_read_ptr ++ * ++ * Description: ++ * This function will be called by the consumer of circularbuf for reading data from ++ * the circular buffer. This will typically be invoked when the consumer gets a ++ * doorbell interrupt. ++ * Please note that the function only returns the pointer (and length) from ++ * where the data can be read. Actual read implementation is up to the ++ * consumer. It could be a bcopy or dma. ++ * ++ * Input Args : ++ * void * : Address from where the data can be read. ++ * available_len : Length of data available for read. ++ * ++ * ----------------------------------------------------------------------------- + */ -+char * -+wf_chspec_ntoa_ex(chanspec_t chspec, char *buf) ++void * BCMFASTPATH ++circularbuf_get_read_ptr(circularbuf_t *handle, uint16 *available_len) +{ -+ if (wf_chspec_ntoa(chspec, buf) == NULL) -+ snprintf(buf, CHANSPEC_STR_LEN, "invalid 0x%04x", chspec); -+ return buf; -+} ++ uint8 *ret_addr; + -+/* given a chanspec and a string buffer, format the chanspec as a -+ * string, and return the original pointer a. -+ * Min buffer length must be CHANSPEC_STR_LEN. -+ * On error return NULL -+ */ -+char * -+wf_chspec_ntoa(chanspec_t chspec, char *buf) -+{ -+ const char *band; -+ uint ctl_chan; ++ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle)); + -+ if (wf_chspec_malformed(chspec)) ++ /* First check if there is any data available in the circular buffer */ ++ *available_len = CIRCULARBUF_READ_SPACE_AVAIL(handle); ++ if (*available_len == 0) + return NULL; + -+ band = ""; -+ -+ /* check for non-default band spec */ -+ if ((CHSPEC_IS2G(chspec) && CHSPEC_CHANNEL(chspec) > CH_MAX_2G_CHANNEL) || -+ (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL)) -+ band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g"; -+ -+ /* ctl channel */ -+ ctl_chan = wf_chspec_ctlchan(chspec); ++ /* ++ * Although there might be data in the circular buffer for read, in ++ * cases of write wrap-around and read still in the end of the circular ++ * buffer, we might have to wrap around the read pending pointer also. ++ */ ++ if (CIRCULARBUF_READ_SPACE_AT_END(handle) == 0) ++ handle->rp_ptr = 0; + -+ /* bandwidth and ctl sideband */ -+ if (CHSPEC_IS20(chspec)) { -+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan); -+ } else if (!CHSPEC_IS8080(chspec)) { -+ const char *bw; -+ const char *sb = ""; ++ ret_addr = CIRCULARBUF_START(handle) + handle->rp_ptr; + -+ bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT]; ++ /* ++ * Please note that we do not update the read pointer here. Only ++ * read pending pointer is updated, so that next reader knows where ++ * to read data from. ++ * read pointer can only be updated when the read is complete. ++ */ ++ handle->rp_ptr = (uint16)(ret_addr - CIRCULARBUF_START(handle) + *available_len); + -+#ifdef CHANSPEC_NEW_40MHZ_FORMAT -+ /* ctl sideband string if needed for 2g 40MHz */ -+ if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) { -+ sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; -+ } ++ ASSERT(*available_len <= handle->depth); + -+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb); -+#else -+ /* ctl sideband string instead of BW for 40MHz */ -+ if (CHSPEC_IS40(chspec)) { -+ sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; -+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb); -+ } else { -+ snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw); -+ } -+#endif /* CHANSPEC_NEW_40MHZ_FORMAT */ ++ OSL_CACHE_INV((void *) ret_addr, *available_len); + -+ } else { -+ /* 80+80 */ -+ uint chan1 = (chspec & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT; -+ uint chan2 = (chspec & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT; ++ return ret_addr; ++} + -+ /* convert to channel number */ -+ chan1 = (chan1 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan1] : 0; -+ chan2 = (chan2 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan2] : 0; ++/** ++ * ----------------------------------------------------------------------------- ++ * Function : circularbuf_read_complete ++ * Description: ++ * This function has to be called by the consumer end of circularbuf to indicate ++ * that data has been consumed and the read pointer can be updated, so the producing side ++ * can can use the freed space for new entries. ++ * ++ * ++ * Input Args : ++ * bytes_read : No. of bytes consumed by the consumer. This has to match ++ * the length returned by circularbuf_get_read_ptr ++ * ++ * Return Values : ++ * CIRCULARBUF_SUCCESS : Otherwise ++ * ++ * ----------------------------------------------------------------------------- ++ */ ++circularbuf_ret_t BCMFASTPATH ++circularbuf_read_complete(circularbuf_t *handle, uint16 bytes_read) ++{ ++ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle)); ++ ASSERT(bytes_read < handle->depth); + -+ /* Outputs a max of CHANSPEC_STR_LEN chars including '\0' */ -+ snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", ctl_chan, chan1, chan2); -+ } ++ /* Update the read pointer */ ++ if ((handle->w_ptr < handle->e_ptr) && (handle->r_ptr + bytes_read) > handle->e_ptr) ++ handle->r_ptr = bytes_read; ++ else ++ handle->r_ptr += bytes_read; + -+ return (buf); ++ return CIRCULARBUF_SUCCESS; +} + -+static int -+read_uint(const char **p, unsigned int *num) ++/** ++ * ----------------------------------------------------------------------------- ++ * Function : circularbuf_revert_rp_ptr ++ * ++ * Description: ++ * The rp_ptr update during circularbuf_get_read_ptr() is done to reflect the amount of data ++ * that is sent out to be read by the consumer. But the consumer may not always read the ++ * entire data. In such a case, the rp_ptr needs to be reverted back by 'left' bytes, where ++ * 'left' is the no. of bytes left unread. ++ * ++ * Input args: ++ * bytes : The no. of bytes left unread by the consumer ++ * ++ * ----------------------------------------------------------------------------- ++ */ ++circularbuf_ret_t ++circularbuf_revert_rp_ptr(circularbuf_t *handle, uint16 bytes) +{ -+ unsigned long val; -+ char *endp = NULL; -+ -+ val = strtoul(*p, &endp, 10); -+ /* if endp is the initial pointer value, then a number was not read */ -+ if (endp == *p) -+ return 0; ++ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle)); ++ ASSERT(bytes < handle->depth); + -+ /* advance the buffer pointer to the end of the integer string */ -+ *p = endp; -+ /* return the parsed integer */ -+ *num = (unsigned int)val; ++ handle->rp_ptr -= bytes; + -+ return 1; ++ return CIRCULARBUF_SUCCESS; +} +diff --git a/drivers/net/wireless/bcm4336/dhd.h b/drivers/net/wireless/bcm4336/dhd.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd.h +@@ -0,0 +1,1106 @@ ++/* ++ * Header file describing the internal (inter-module) DHD interfaces. ++ * ++ * Provides type definitions and function prototypes used to link the ++ * DHD OS, bus, and protocol modules. ++ * ++ * $Copyright Open Broadcom Corporation$ ++ * ++ * $Id: dhd.h 504503 2014-09-24 11:28:56Z $ ++ */ + -+/* given a chanspec string, convert to a chanspec. -+ * On error return 0 ++/**************** ++ * Common types * + */ -+chanspec_t -+wf_chspec_aton(const char *a) -+{ -+ chanspec_t chspec; -+ uint chspec_ch, chspec_band, bw, chspec_bw, chspec_sb; -+ uint num, ctl_ch; -+ uint ch1, ch2; -+ char c, sb_ul = '\0'; -+ int i; + -+ bw = 20; -+ chspec_sb = 0; -+ chspec_ch = ch1 = ch2 = 0; ++#ifndef _dhd_h_ ++#define _dhd_h_ + -+ /* parse channel num or band */ -+ if (!read_uint(&a, &num)) -+ return 0; ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) ++#include ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ ++/* The kernel threading is sdio-specific */ ++struct task_struct; ++struct sched_param; ++int setScheduler(struct task_struct *p, int policy, struct sched_param *param); ++int get_scheduler_policy(struct task_struct *p); ++#define MAX_EVENT 16 + -+ /* if we are looking at a 'g', then the first number was a band */ -+ c = tolower((int)a[0]); -+ if (c == 'g') { -+ a ++; /* consume the char */ ++#define ALL_INTERFACES 0xff + -+ /* band must be "2" or "5" */ -+ if (num == 2) -+ chspec_band = WL_CHANSPEC_BAND_2G; -+ else if (num == 5) -+ chspec_band = WL_CHANSPEC_BAND_5G; -+ else -+ return 0; ++#include ++#include ++#include + -+ /* read the channel number */ -+ if (!read_uint(&a, &ctl_ch)) -+ return 0; ++#if defined(BCMWDF) ++#include ++#include ++#endif /* (BCMWDF) */ + -+ c = tolower((int)a[0]); -+ } -+ else { -+ /* first number is channel, use default for band */ -+ ctl_ch = num; -+ chspec_band = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? -+ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); -+ } ++#if defined(WL11U) && !defined(MFP) ++#define MFP /* Applying interaction with MFP by spec HS2.0 REL2 */ ++#endif /* WL11U */ + -+ if (c == '\0') { -+ /* default BW of 20MHz */ -+ chspec_bw = WL_CHANSPEC_BW_20; -+ goto done_read; -+ } ++#if defined(KEEP_ALIVE) ++/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ ++#define KEEP_ALIVE_PERIOD 55000 ++#define NULL_PKT_STR "null_pkt" ++#endif /* KEEP_ALIVE */ ++/* Forward decls */ ++struct dhd_bus; ++struct dhd_prot; ++struct dhd_info; ++struct dhd_ioctl; + -+ a ++; /* consume the 'u','l', or '/' */ ++/* The level of bus communication with the dongle */ ++enum dhd_bus_state { ++ DHD_BUS_DOWN, /* Not ready for frame transfers */ ++ DHD_BUS_LOAD, /* Download access only (CPU reset) */ ++ DHD_BUS_DATA, /* Ready for frame transfers */ ++ DHD_BUS_SUSPEND, /* Bus has been suspended */ ++}; + -+ /* check 'u'/'l' */ -+ if (c == 'u' || c == 'l') { -+ sb_ul = c; -+ chspec_bw = WL_CHANSPEC_BW_40; -+ goto done_read; -+ } ++#if defined(NDISVER) ++#if (NDISVER >= 0x0600) ++/* Firmware requested operation mode */ ++#define STA_MASK 0x0001 ++#define HOSTAPD_MASK 0x0002 ++#define WFD_MASK 0x0004 ++#define SOFTAP_FW_MASK 0x0008 ++#define P2P_GO_ENABLED 0x0010 ++#define P2P_GC_ENABLED 0x0020 ++#define CONCURENT_MASK 0x00F0 ++#endif /* (NDISVER >= 0x0600) */ ++#endif /* #if defined(NDISVER) */ + -+ /* next letter must be '/' */ -+ if (c != '/') -+ return 0; ++#define DHD_IF_ROLE_STA(role) (role == WLC_E_IF_ROLE_STA ||\ ++ role == WLC_E_IF_ROLE_P2P_CLIENT) + -+ /* read bandwidth */ -+ if (!read_uint(&a, &bw)) -+ return 0; ++/* For supporting multiple interfaces */ ++#define DHD_MAX_IFS 16 ++#define DHD_DEL_IF -0xE ++#define DHD_BAD_IF -0xF + -+ /* convert to chspec value */ -+ if (bw == 20) { -+ chspec_bw = WL_CHANSPEC_BW_20; -+ } else if (bw == 40) { -+ chspec_bw = WL_CHANSPEC_BW_40; -+ } else if (bw == 80) { -+ chspec_bw = WL_CHANSPEC_BW_80; -+ } else if (bw == 160) { -+ chspec_bw = WL_CHANSPEC_BW_160; -+ } else { -+ return 0; -+ } ++enum dhd_op_flags { ++/* Firmware requested operation mode */ ++ DHD_FLAG_STA_MODE = (1 << (0)), /* STA only */ ++ DHD_FLAG_HOSTAP_MODE = (1 << (1)), /* SOFTAP only */ ++ DHD_FLAG_P2P_MODE = (1 << (2)), /* P2P Only */ ++ /* STA + P2P */ ++ DHD_FLAG_CONCURR_SINGLE_CHAN_MODE = (DHD_FLAG_STA_MODE | DHD_FLAG_P2P_MODE), ++ DHD_FLAG_CONCURR_MULTI_CHAN_MODE = (1 << (4)), /* STA + P2P */ ++ /* Current P2P mode for P2P connection */ ++ DHD_FLAG_P2P_GC_MODE = (1 << (5)), ++ DHD_FLAG_P2P_GO_MODE = (1 << (6)), ++ DHD_FLAG_MBSS_MODE = (1 << (7)), /* MBSS in future */ ++ DHD_FLAG_IBSS_MODE = (1 << (8)), ++ DHD_FLAG_MFG_MODE = (1 << (9)) ++}; + -+ /* So far we have g/ -+ * Can now be followed by u/l if bw = 40, -+ * or '+80' if bw = 80, to make '80+80' bw. -+ */ ++/* Max sequential TX/RX Control timeouts to set HANG event */ ++#ifndef MAX_CNTL_TX_TIMEOUT ++#define MAX_CNTL_TX_TIMEOUT 2 ++#endif /* MAX_CNTL_TX_TIMEOUT */ ++#ifndef MAX_CNTL_RX_TIMEOUT ++#define MAX_CNTL_RX_TIMEOUT 1 ++#endif /* MAX_CNTL_RX_TIMEOUT */ + -+ c = tolower((int)a[0]); ++#define DHD_SCAN_ASSOC_ACTIVE_TIME 40 /* ms: Embedded default Active setting from DHD */ ++#define DHD_SCAN_UNASSOC_ACTIVE_TIME 80 /* ms: Embedded def. Unassoc Active setting from DHD */ ++#define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD */ + -+ /* if we have a 2g/40 channel, we should have a l/u spec now */ -+ if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) { -+ if (c == 'u' || c == 'l') { -+ a ++; /* consume the u/l char */ -+ sb_ul = c; -+ goto done_read; -+ } -+ } ++#ifndef POWERUP_MAX_RETRY ++#define POWERUP_MAX_RETRY 3 /* how many times we retry to power up the chip */ ++#endif ++#ifndef POWERUP_WAIT_MS ++#define POWERUP_WAIT_MS 2000 /* ms: time out in waiting wifi to come up */ ++#endif + -+ /* check for 80+80 */ -+ if (c == '+') { -+ /* 80+80 */ -+ static const char *plus80 = "80/"; ++enum dhd_bus_wake_state { ++ WAKE_LOCK_OFF, ++ WAKE_LOCK_PRIV, ++ WAKE_LOCK_DPC, ++ WAKE_LOCK_IOCTL, ++ WAKE_LOCK_DOWNLOAD, ++ WAKE_LOCK_TMOUT, ++ WAKE_LOCK_WATCHDOG, ++ WAKE_LOCK_LINK_DOWN_TMOUT, ++ WAKE_LOCK_PNO_FIND_TMOUT, ++ WAKE_LOCK_SOFTAP_SET, ++ WAKE_LOCK_SOFTAP_STOP, ++ WAKE_LOCK_SOFTAP_START, ++ WAKE_LOCK_SOFTAP_THREAD ++}; + -+ /* must be looking at '+80/' -+ * check and consume this string. -+ */ -+ chspec_bw = WL_CHANSPEC_BW_8080; ++enum dhd_prealloc_index { ++ DHD_PREALLOC_PROT = 0, ++ DHD_PREALLOC_RXBUF, ++ DHD_PREALLOC_DATABUF, ++ DHD_PREALLOC_OSL_BUF, ++#if defined(STATIC_WL_PRIV_STRUCT) ++ DHD_PREALLOC_WIPHY_ESCAN0 = 5, ++#endif /* STATIC_WL_PRIV_STRUCT */ ++ DHD_PREALLOC_DHD_INFO = 7, ++ DHD_PREALLOC_DHD_WLFC_INFO = 8, ++ DHD_PREALLOC_IF_FLOW_LKUP = 9, ++ DHD_PREALLOC_FLOWRING = 10 ++}; + -+ a ++; /* consume the char '+' */ ++/* Packet alignment for most efficient SDIO (can change based on platform) */ ++#ifndef DHD_SDALIGN ++#define DHD_SDALIGN 32 ++#endif + -+ /* consume the '80/' string */ -+ for (i = 0; i < 3; i++) { -+ if (*a++ != *plus80++) { -+ return 0; -+ } -+ } ++/* host reordering packts logic */ ++/* followed the structure to hold the reorder buffers (void **p) */ ++typedef struct reorder_info { ++ void **p; ++ uint8 flow_id; ++ uint8 cur_idx; ++ uint8 exp_idx; ++ uint8 max_idx; ++ uint8 pend_pkts; ++} reorder_info_t; + -+ /* read primary 80MHz channel */ -+ if (!read_uint(&a, &ch1)) -+ return 0; ++#ifdef DHDTCPACK_SUPPRESS + -+ /* must followed by '-' */ -+ if (a[0] != '-') -+ return 0; -+ a ++; /* consume the char */ ++enum { ++ /* TCPACK suppress off */ ++ TCPACK_SUP_OFF, ++ /* Replace TCPACK in txq when new coming one has higher ACK number. */ ++ TCPACK_SUP_REPLACE, ++ /* TCPACK_SUP_REPLACE + delayed TCPACK TX unless ACK to PSH DATA. ++ * This will give benefits to Half-Duplex bus interface(e.g. SDIO) that ++ * 1. we are able to read TCP DATA packets first from the bus ++ * 2. TCPACKs that don't need to hurry delivered remains longer in TXQ so can be suppressed. ++ */ ++ TCPACK_SUP_DELAYTX, ++ TCPACK_SUP_HOLD, ++ TCPACK_SUP_LAST_MODE ++}; ++#endif /* DHDTCPACK_SUPPRESS */ + -+ /* read secondary 80MHz channel */ -+ if (!read_uint(&a, &ch2)) -+ return 0; -+ } + -+done_read: -+ /* skip trailing white space */ -+ while (a[0] == ' ') { -+ a ++; -+ } ++/* DMA'ing r/w indices for rings supported */ ++#ifdef BCM_INDX_TCM /* FW gets r/w indices in TCM */ ++#define DMA_INDX_ENAB(dma_indxsup) 0 ++#elif defined BCM_INDX_DMA /* FW gets r/w indices from Host memory */ ++#define DMA_INDX_ENAB(dma_indxsup) 1 ++#else /* r/w indices in TCM or host memory based on FW/Host agreement */ ++#define DMA_INDX_ENAB(dma_indxsup) dma_indxsup ++#endif /* BCM_INDX_TCM */ + -+ /* must be end of string */ -+ if (a[0] != '\0') -+ return 0; ++#if defined(WLTDLS) && defined(PCIE_FULL_DONGLE) ++struct tdls_peer_node { ++ uint8 addr[ETHER_ADDR_LEN]; ++ struct tdls_peer_node *next; ++}; ++typedef struct tdls_peer_node tdls_peer_node_t; ++typedef struct { ++ tdls_peer_node_t *node; ++ uint8 tdls_peer_count; ++} tdls_peer_tbl_t; ++#endif /* defined(WLTDLS) && defined(PCIE_FULL_DONGLE) */ + -+ /* Now have all the chanspec string parts read; -+ * chspec_band, ctl_ch, chspec_bw, sb_ul, ch1, ch2. -+ * chspec_band and chspec_bw are chanspec values. -+ * Need to convert ctl_ch, sb_ul, and ch1,ch2 into -+ * a center channel (or two) and sideband. -+ */ ++/* Common structure for module and instance linkage */ ++typedef struct dhd_pub { ++ /* Linkage ponters */ ++ osl_t *osh; /* OSL handle */ ++ struct dhd_bus *bus; /* Bus module handle */ ++ struct dhd_prot *prot; /* Protocol module handle */ ++ struct dhd_info *info; /* Info module handle */ + -+ /* if a sb u/l string was given, just use that, -+ * guaranteed to be bw = 40 by sting parse. -+ */ -+ if (sb_ul != '\0') { -+ if (sb_ul == 'l') { -+ chspec_ch = UPPER_20_SB(ctl_ch); -+ chspec_sb = WL_CHANSPEC_CTL_SB_LLL; -+ } else if (sb_ul == 'u') { -+ chspec_ch = LOWER_20_SB(ctl_ch); -+ chspec_sb = WL_CHANSPEC_CTL_SB_LLU; -+ } -+ } -+ /* if the bw is 20, center and sideband are trivial */ -+ else if (chspec_bw == WL_CHANSPEC_BW_20) { -+ chspec_ch = ctl_ch; -+ chspec_sb = WL_CHANSPEC_CTL_SB_NONE; -+ } -+ /* if the bw is 40/80/160, not 80+80, a single method -+ * can be used to to find the center and sideband ++ /* to NDIS developer, the structure dhd_common is redundant, ++ * please do NOT merge it back from other branches !!! + */ -+ else if (chspec_bw != WL_CHANSPEC_BW_8080) { -+ /* figure out ctl sideband based on ctl channel and bandwidth */ -+ const uint8 *center_ch = NULL; -+ int num_ch = 0; -+ int sb = -1; -+ -+ if (chspec_bw == WL_CHANSPEC_BW_40) { -+ center_ch = wf_5g_40m_chans; -+ num_ch = WF_NUM_5G_40M_CHANS; -+ } else if (chspec_bw == WL_CHANSPEC_BW_80) { -+ center_ch = wf_5g_80m_chans; -+ num_ch = WF_NUM_5G_80M_CHANS; -+ } else if (chspec_bw == WL_CHANSPEC_BW_160) { -+ center_ch = wf_5g_160m_chans; -+ num_ch = WF_NUM_5G_160M_CHANS; -+ } else { -+ return 0; -+ } + -+ for (i = 0; i < num_ch; i ++) { -+ sb = channel_to_sb(center_ch[i], ctl_ch, bw); -+ if (sb >= 0) { -+ chspec_ch = center_ch[i]; -+ chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT; -+ break; -+ } -+ } + -+ /* check for no matching sb/center */ -+ if (sb < 0) { -+ return 0; -+ } -+ } -+ /* Otherwise, bw is 80+80. Figure out channel pair and sb */ -+ else { -+ int ch1_id = 0, ch2_id = 0; -+ int sb; ++ /* Internal dhd items */ ++ bool up; /* Driver up/down (to OS) */ ++ bool txoff; /* Transmit flow-controlled */ ++ bool dongle_reset; /* TRUE = DEVRESET put dongle into reset */ ++ enum dhd_bus_state busstate; ++ uint hdrlen; /* Total DHD header length (proto + bus) */ ++ uint maxctl; /* Max size rxctl request from proto to bus */ ++ uint rxsz; /* Rx buffer size bus module should use */ ++ uint8 wme_dp; /* wme discard priority */ + -+ /* look up the channel ID for the specified channel numbers */ -+ ch1_id = channel_80mhz_to_id(ch1); -+ ch2_id = channel_80mhz_to_id(ch2); ++ /* Dongle media info */ ++ bool iswl; /* Dongle-resident driver is wl */ ++ ulong drv_version; /* Version of dongle-resident driver */ ++ struct ether_addr mac; /* MAC address obtained from dongle */ ++ dngl_stats_t dstats; /* Stats for dongle-based data */ + -+ /* validate channels */ -+ if (ch1_id < 0 || ch2_id < 0) -+ return 0; ++ /* Additional stats for the bus level */ ++ ulong tx_packets; /* Data packets sent to dongle */ ++ ulong tx_dropped; /* Data packets dropped in dhd */ ++ ulong tx_multicast; /* Multicast data packets sent to dongle */ ++ ulong tx_errors; /* Errors in sending data to dongle */ ++ ulong tx_ctlpkts; /* Control packets sent to dongle */ ++ ulong tx_ctlerrs; /* Errors sending control frames to dongle */ ++ ulong rx_packets; /* Packets sent up the network interface */ ++ ulong rx_multicast; /* Multicast packets sent up the network interface */ ++ ulong rx_errors; /* Errors processing rx data packets */ ++ ulong rx_ctlpkts; /* Control frames processed from dongle */ ++ ulong rx_ctlerrs; /* Errors in processing rx control frames */ ++ ulong rx_dropped; /* Packets dropped locally (no memory) */ ++ ulong rx_flushed; /* Packets flushed due to unscheduled sendup thread */ ++ ulong wd_dpc_sched; /* Number of times dhd dpc scheduled by watchdog timer */ + -+ /* combine 2 channel IDs in channel field of chspec */ -+ chspec_ch = (((uint)ch1_id << WL_CHANSPEC_CHAN1_SHIFT) | -+ ((uint)ch2_id << WL_CHANSPEC_CHAN2_SHIFT)); ++ ulong rx_readahead_cnt; /* Number of packets where header read-ahead was used. */ ++ ulong tx_realloc; /* Number of tx packets we had to realloc for headroom */ ++ ulong fc_packets; /* Number of flow control pkts recvd */ + -+ /* figure out primary 20 MHz sideband */ ++ /* Last error return */ ++ int bcmerror; ++ uint tickcnt; + -+ /* is the primary channel contained in the 1st 80MHz channel? */ -+ sb = channel_to_sb(ch1, ctl_ch, bw); -+ if (sb < 0) { -+ /* no match for primary channel 'ctl_ch' in segment0 80MHz channel */ -+ return 0; -+ } ++ /* Last error from dongle */ ++ int dongle_error; + -+ chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT; -+ } ++ uint8 country_code[WLC_CNTRY_BUF_SZ]; + -+ chspec = (chspec_ch | chspec_band | chspec_bw | chspec_sb); ++ /* Suspend disable flag and "in suspend" flag */ ++ int suspend_disable_flag; /* "1" to disable all extra powersaving during suspend */ ++ int in_suspend; /* flag set to 1 when early suspend called */ ++#ifdef PNO_SUPPORT ++ int pno_enable; /* pno status : "1" is pno enable */ ++ int pno_suspend; /* pno suspend status : "1" is pno suspended */ ++#endif /* PNO_SUPPORT */ ++ /* DTIM skip value, default 0(or 1) means wake each DTIM ++ * 3 means skip 2 DTIMs and wake up 3rd DTIM(9th beacon when AP DTIM is 3) ++ */ ++ int suspend_bcn_li_dtim; /* bcn_li_dtim value in suspend mode */ ++#ifdef PKT_FILTER_SUPPORT ++ int early_suspended; /* Early suspend status */ ++ int dhcp_in_progress; /* DHCP period */ ++#endif + -+ if (wf_chspec_malformed(chspec)) -+ return 0; ++ /* Pkt filter defination */ ++ char * pktfilter[100]; ++ int pktfilter_count; + -+ return chspec; -+} ++ wl_country_t dhd_cspec; /* Current Locale info */ ++ char eventmask[WL_EVENTING_MASK_LEN]; ++ int op_mode; /* STA, HostAPD, WFD, SoftAP */ + -+/* -+ * Verify the chanspec is using a legal set of parameters, i.e. that the -+ * chanspec specified a band, bw, ctl_sb and channel and that the -+ * combination could be legal given any set of circumstances. -+ * RETURNS: TRUE is the chanspec is malformed, false if it looks good. ++/* Set this to 1 to use a seperate interface (p2p0) for p2p operations. ++ * For ICS MR1 releases it should be disable to be compatable with ICS MR1 Framework ++ * see target dhd-cdc-sdmmc-panda-cfg80211-icsmr1-gpl-debug in Makefile + */ -+bool -+wf_chspec_malformed(chanspec_t chanspec) -+{ -+ uint chspec_bw = CHSPEC_BW(chanspec); -+ uint chspec_ch = CHSPEC_CHANNEL(chanspec); -+ -+ /* must be 2G or 5G band */ -+ if (CHSPEC_IS2G(chanspec)) { -+ /* must be valid bandwidth */ -+ if (chspec_bw != WL_CHANSPEC_BW_20 && -+ chspec_bw != WL_CHANSPEC_BW_40) { -+ return TRUE; -+ } -+ } else if (CHSPEC_IS5G(chanspec)) { -+ if (chspec_bw == WL_CHANSPEC_BW_8080) { -+ uint ch1_id, ch2_id; -+ -+ /* channel IDs in 80+80 must be in range */ -+ ch1_id = CHSPEC_CHAN1(chanspec); -+ ch2_id = CHSPEC_CHAN2(chanspec); -+ if (ch1_id >= WF_NUM_5G_80M_CHANS || ch2_id >= WF_NUM_5G_80M_CHANS) -+ return TRUE; -+ -+ } else if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40 || -+ chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_160) { ++/* #define WL_ENABLE_P2P_IF 1 */ + -+ if (chspec_ch > MAXCHANNEL) { -+ return TRUE; -+ } -+ } else { -+ /* invalid bandwidth */ -+ return TRUE; -+ } -+ } else { -+ /* must be 2G or 5G band */ -+ return TRUE; -+ } ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ struct mutex wl_start_stop_lock; /* lock/unlock for Android start/stop */ ++ struct mutex wl_softap_lock; /* lock/unlock for any SoftAP/STA settings */ ++#endif + -+ /* side band needs to be consistent with bandwidth */ -+ if (chspec_bw == WL_CHANSPEC_BW_20) { -+ if (CHSPEC_CTL_SB(chanspec) != WL_CHANSPEC_CTL_SB_LLL) -+ return TRUE; -+ } else if (chspec_bw == WL_CHANSPEC_BW_40) { -+ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LLU) -+ return TRUE; -+ } else if (chspec_bw == WL_CHANSPEC_BW_80 || -+ chspec_bw == WL_CHANSPEC_BW_8080) { -+ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LUU) -+ return TRUE; -+ } -+ else if (chspec_bw == WL_CHANSPEC_BW_160) { -+ ASSERT(CHSPEC_CTL_SB(chanspec) <= WL_CHANSPEC_CTL_SB_UUU); -+ } -+ return FALSE; -+} ++#ifdef WLBTAMP ++ uint16 maxdatablks; ++#endif /* WLBTAMP */ ++#ifdef PROP_TXSTATUS ++ bool wlfc_enabled; ++ int wlfc_mode; ++ void* wlfc_state; ++ /* ++ Mode in which the dhd flow control shall operate. Must be set before ++ traffic starts to the device. ++ 0 - Do not do any proptxtstatus flow control ++ 1 - Use implied credit from a packet status ++ 2 - Use explicit credit ++ 3 - Only AMPDU hostreorder used. no wlfc. ++ */ ++ uint8 proptxstatus_mode; ++ bool proptxstatus_txoff; ++ bool proptxstatus_module_ignore; ++ bool proptxstatus_credit_ignore; ++ bool proptxstatus_txstatus_ignore; + -+/* -+ * Verify the chanspec specifies a valid channel according to 802.11. -+ * RETURNS: TRUE if the chanspec is a valid 802.11 channel -+ */ -+bool -+wf_chspec_valid(chanspec_t chanspec) -+{ -+ uint chspec_bw = CHSPEC_BW(chanspec); -+ uint chspec_ch = CHSPEC_CHANNEL(chanspec); ++ bool wlfc_rxpkt_chk; ++ /* ++ * implement below functions in each platform if needed. ++ */ ++ /* platform specific function whether to skip flow control */ ++ bool (*skip_fc)(void); ++ /* platform specific function for wlfc_enable and wlfc_deinit */ ++ void (*plat_init)(void *dhd); ++ void (*plat_deinit)(void *dhd); ++#endif /* PROP_TXSTATUS */ ++#ifdef PNO_SUPPORT ++ void *pno_state; ++#endif ++ bool dongle_isolation; ++ bool dongle_trap_occured; /* flag for sending HANG event to upper layer */ ++ int hang_was_sent; ++ int rxcnt_timeout; /* counter rxcnt timeout to send HANG */ ++ int txcnt_timeout; /* counter txcnt timeout to send HANG */ ++ bool hang_report; /* enable hang report by default */ ++#ifdef WLMEDIA_HTSF ++ uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */ ++#endif ++#ifdef WLTDLS ++ bool tdls_enable; ++#endif ++ struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS]; ++ char fw_capabilities[WLC_IOCTL_SMLEN]; ++ #define MAXSKBPEND 1024 ++ void *skbbuf[MAXSKBPEND]; ++ uint32 store_idx; ++ uint32 sent_idx; ++#ifdef DHDTCPACK_SUPPRESS ++ uint8 tcpack_sup_mode; /* TCPACK suppress mode */ ++ void *tcpack_sup_module; /* TCPACK suppress module */ ++ uint32 tcpack_sup_ratio; ++ uint32 tcpack_sup_delay; ++#endif /* DHDTCPACK_SUPPRESS */ ++#if defined(ARP_OFFLOAD_SUPPORT) ++ uint32 arp_version; ++#endif ++#if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X) ++ bool fw_4way_handshake; /* Whether firmware will to do the 4way handshake. */ ++#endif ++#if defined(CUSTOM_PLATFORM_NV_TEGRA) ++#ifdef PKT_FILTER_SUPPORT ++ uint pkt_filter_mode; ++ uint pkt_filter_ports_count; ++ uint16 pkt_filter_ports[WL_PKT_FILTER_PORTS_MAX]; ++#endif /* PKT_FILTER_SUPPORT */ ++#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */ ++#ifdef CUSTOM_SET_CPUCORE ++ struct task_struct * current_dpc; ++ struct task_struct * current_rxf; ++ int chan_isvht80; ++#endif /* CUSTOM_SET_CPUCORE */ + -+ if (wf_chspec_malformed(chanspec)) -+ return FALSE; ++ void *sta_pool; /* pre-allocated pool of sta objects */ ++ void *staid_allocator; /* allocator of sta indexes */ + -+ if (CHSPEC_IS2G(chanspec)) { -+ /* must be valid bandwidth and channel range */ -+ if (chspec_bw == WL_CHANSPEC_BW_20) { -+ if (chspec_ch >= 1 && chspec_ch <= 14) -+ return TRUE; -+ } else if (chspec_bw == WL_CHANSPEC_BW_40) { -+ if (chspec_ch >= 3 && chspec_ch <= 11) -+ return TRUE; -+ } -+ } else if (CHSPEC_IS5G(chanspec)) { -+ if (chspec_bw == WL_CHANSPEC_BW_8080) { -+ uint16 ch1, ch2; ++ void *flowid_allocator; /* unique flowid allocator */ ++ void *flow_ring_table; /* flow ring table, include prot and bus info */ ++ void *if_flow_lkup; /* per interface flowid lkup hash table */ ++ void *flowid_lock; /* per os lock for flowid info protection */ ++ uint32 num_flow_rings; + -+ ch1 = wf_5g_80m_chans[CHSPEC_CHAN1(chanspec)]; -+ ch2 = wf_5g_80m_chans[CHSPEC_CHAN2(chanspec)]; ++ uint32 d2h_sync_mode; /* D2H DMA completion sync mode */ + -+ /* the two channels must be separated by more than 80MHz by VHT req */ -+ if ((ch2 > ch1 + CH_80MHZ_APART) || -+ (ch1 > ch2 + CH_80MHZ_APART)) -+ return TRUE; -+ } else { -+ const uint8 *center_ch; -+ uint num_ch, i; ++ uint8 flow_prio_map[NUMPRIO]; ++ uint8 flow_prio_map_type; ++ char enable_log[MAX_EVENT]; ++ bool dma_d2h_ring_upd_support; ++ bool dma_h2d_ring_upd_support; ++#ifdef DHD_WMF ++ bool wmf_ucast_igmp; ++#ifdef DHD_IGMP_UCQUERY ++ bool wmf_ucast_igmp_query; ++#endif ++#ifdef DHD_UCAST_UPNP ++ bool wmf_ucast_upnp; ++#endif ++#endif /* DHD_WMF */ ++#ifdef DHD_UNICAST_DHCP ++ bool dhcp_unicast; ++#endif /* DHD_UNICAST_DHCP */ ++#ifdef DHD_L2_FILTER ++ bool block_ping; ++#endif ++#if defined(WLTDLS) && defined(PCIE_FULL_DONGLE) ++ tdls_peer_tbl_t peer_tbl; ++#endif /* defined(WLTDLS) && defined(PCIE_FULL_DONGLE) */ ++ char *conf_path; /* module_param: path to config vars file */ ++ struct dhd_conf *conf; /* Bus module handle */ ++} dhd_pub_t; + -+ if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40) { -+ center_ch = wf_5g_40m_chans; -+ num_ch = WF_NUM_5G_40M_CHANS; -+ } else if (chspec_bw == WL_CHANSPEC_BW_80) { -+ center_ch = wf_5g_80m_chans; -+ num_ch = WF_NUM_5G_80M_CHANS; -+ } else if (chspec_bw == WL_CHANSPEC_BW_160) { -+ center_ch = wf_5g_160m_chans; -+ num_ch = WF_NUM_5G_160M_CHANS; -+ } else { -+ /* invalid bandwidth */ -+ return FALSE; -+ } ++#if defined(BCMWDF) ++typedef struct { ++ dhd_pub_t *dhd_pub; ++} dhd_workitem_context_t; + -+ /* check for a valid center channel */ -+ if (chspec_bw == WL_CHANSPEC_BW_20) { -+ /* We don't have an array of legal 20MHz 5G channels, but they are -+ * each side of the legal 40MHz channels. Check the chanspec -+ * channel against either side of the 40MHz channels. -+ */ -+ for (i = 0; i < num_ch; i ++) { -+ if (chspec_ch == (uint)LOWER_20_SB(center_ch[i]) || -+ chspec_ch == (uint)UPPER_20_SB(center_ch[i])) -+ break; /* match found */ -+ } ++WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(dhd_workitem_context_t, dhd_get_dhd_workitem_context) ++#endif /* (BCMWDF) */ + -+ if (i == num_ch) { -+ /* check for channel 165 which is not the side band -+ * of 40MHz 5G channel -+ */ -+ if (chspec_ch == 165) -+ i = 0; ++ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) + -+ /* check for legacy JP channels on failure */ -+ if (chspec_ch == 34 || chspec_ch == 38 || -+ chspec_ch == 42 || chspec_ch == 46) -+ i = 0; -+ } -+ } else { -+ /* check the chanspec channel to each legal channel */ -+ for (i = 0; i < num_ch; i ++) { -+ if (chspec_ch == center_ch[i]) -+ break; /* match found */ -+ } -+ } ++ #define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); ++ #define _DHD_PM_RESUME_WAIT(a, b) do {\ ++ int retry = 0; \ ++ SMP_RD_BARRIER_DEPENDS(); \ ++ while (dhd_mmc_suspend && retry++ != b) { \ ++ SMP_RD_BARRIER_DEPENDS(); \ ++ wait_event_interruptible_timeout(a, !dhd_mmc_suspend, 1); \ ++ } \ ++ } while (0) ++ #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 200) ++ #define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0) ++ #ifdef CUSTOMER_HW4 ++ #define DHD_PM_RESUME_RETURN_ERROR(a) do { \ ++ if (dhd_mmc_suspend) { \ ++ printf("%s[%d]: mmc is still in suspend state!!!\n", \ ++ __FUNCTION__, __LINE__); \ ++ return a; \ ++ } \ ++ } while (0) ++ #else ++ #define DHD_PM_RESUME_RETURN_ERROR(a) do { \ ++ if (dhd_mmc_suspend) return a; } while (0) ++ #endif ++ #define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0) + -+ if (i < num_ch) { -+ /* match found */ -+ return TRUE; -+ } -+ } -+ } ++ #define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); ++ #define SPINWAIT_SLEEP(a, exp, us) do { \ ++ uint countdown = (us) + 9999; \ ++ while ((exp) && (countdown >= 10000)) { \ ++ wait_event_interruptible_timeout(a, FALSE, 1); \ ++ countdown -= 10000; \ ++ } \ ++ } while (0) + -+ return FALSE; -+} ++ #else + -+/* -+ * This function returns the channel number that control traffic is being sent on, for 20MHz -+ * channels this is just the channel number, for 40MHZ, 80MHz, 160MHz channels it is the 20MHZ -+ * sideband depending on the chanspec selected -+ */ -+uint8 -+wf_chspec_ctlchan(chanspec_t chspec) -+{ -+ uint center_chan; -+ uint bw_mhz; -+ uint sb; ++ #define DHD_PM_RESUME_WAIT_INIT(a) ++ #define DHD_PM_RESUME_WAIT(a) ++ #define DHD_PM_RESUME_WAIT_FOREVER(a) ++ #define DHD_PM_RESUME_RETURN_ERROR(a) ++ #define DHD_PM_RESUME_RETURN + -+ ASSERT(!wf_chspec_malformed(chspec)); ++ #define DHD_SPINWAIT_SLEEP_INIT(a) ++ #define SPINWAIT_SLEEP(a, exp, us) do { \ ++ uint countdown = (us) + 9; \ ++ while ((exp) && (countdown >= 10)) { \ ++ OSL_DELAY(10); \ ++ countdown -= 10; \ ++ } \ ++ } while (0) + -+ /* Is there a sideband ? */ -+ if (CHSPEC_IS20(chspec)) { -+ return CHSPEC_CHANNEL(chspec); -+ } else { -+ sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT; ++ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ + -+ if (CHSPEC_IS8080(chspec)) { -+ /* For an 80+80 MHz channel, the sideband 'sb' field is an 80 MHz sideband -+ * (LL, LU, UL, LU) for the 80 MHz frequency segment 0. -+ */ -+ uint chan_id = CHSPEC_CHAN1(chspec); ++#ifndef OSL_SLEEP ++#define OSL_SLEEP(ms) OSL_DELAY(ms*1000) ++#endif /* OSL_SLEEP */ + -+ bw_mhz = 80; ++#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */ + -+ /* convert from channel index to channel number */ -+ center_chan = wf_5g_80m_chans[chan_id]; -+ } -+ else { -+ bw_mhz = bw_chspec_to_mhz(chspec); -+ center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT; -+ } ++#ifdef PNO_SUPPORT ++int dhd_pno_clean(dhd_pub_t *dhd); ++#endif /* PNO_SUPPORT */ ++/* ++ * Wake locks are an Android power management concept. They are used by applications and services ++ * to request CPU resources. ++ */ ++extern int dhd_os_wake_lock(dhd_pub_t *pub); ++extern int dhd_os_wake_unlock(dhd_pub_t *pub); ++extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub); ++extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val); ++extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val); ++extern int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub); ++extern int dhd_os_wd_wake_lock(dhd_pub_t *pub); ++extern int dhd_os_wd_wake_unlock(dhd_pub_t *pub); ++#ifdef BCMPCIE_OOB_HOST_WAKE ++extern int dhd_os_oob_irq_wake_lock_timeout(dhd_pub_t *pub, int val); ++extern int dhd_os_oob_irq_wake_unlock(dhd_pub_t *pub); ++#endif /* BCMPCIE_OOB_HOST_WAKE */ ++extern int dhd_os_wake_lock_waive(dhd_pub_t *pub); ++extern int dhd_os_wake_lock_restore(dhd_pub_t *pub); + -+ return (channel_to_ctl_chan(center_chan, bw_mhz, sb)); -+ } ++inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp) ++{ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ mutex_init(&dhdp->wl_softap_lock); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ +} + -+/* given a chanspec, return the bandwidth string */ -+char * -+wf_chspec_to_bw_str(chanspec_t chspec) ++inline static void MUTEX_LOCK_SOFTAP_SET(dhd_pub_t * dhdp) +{ -+ return (char *)wf_chspec_bw_str[(CHSPEC_BW(chspec) >> WL_CHANSPEC_BW_SHIFT)]; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ mutex_lock(&dhdp->wl_softap_lock); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ +} + -+/* -+ * This function returns the chanspec of the control channel of a given chanspec -+ */ -+chanspec_t -+wf_chspec_ctlchspec(chanspec_t chspec) ++inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) +{ -+ chanspec_t ctl_chspec = chspec; -+ uint8 ctl_chan; -+ -+ ASSERT(!wf_chspec_malformed(chspec)); -+ -+ /* Is there a sideband ? */ -+ if (!CHSPEC_IS20(chspec)) { -+ ctl_chan = wf_chspec_ctlchan(chspec); -+ ctl_chspec = ctl_chan | WL_CHANSPEC_BW_20; -+ ctl_chspec |= CHSPEC_BAND(chspec); -+ } -+ return ctl_chspec; ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ mutex_unlock(&dhdp->wl_softap_lock); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ +} + -+/* return chanspec given control channel and bandwidth -+ * return 0 on error -+ */ -+uint16 -+wf_channel2chspec(uint ctl_ch, uint bw) -+{ -+ uint16 chspec; -+ const uint8 *center_ch = NULL; -+ int num_ch = 0; -+ int sb = -1; -+ int i = 0; ++#define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub) ++#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub) ++#define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub) ++#define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) \ ++ dhd_os_wake_lock_rx_timeout_enable(pub, val) ++#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) \ ++ dhd_os_wake_lock_ctrl_timeout_enable(pub, val) ++#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL(pub) \ ++ dhd_os_wake_lock_ctrl_timeout_cancel(pub) ++#define DHD_OS_WAKE_LOCK_WAIVE(pub) dhd_os_wake_lock_waive(pub) ++#define DHD_OS_WAKE_LOCK_RESTORE(pub) dhd_os_wake_lock_restore(pub) + -+ chspec = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); ++#define DHD_OS_WD_WAKE_LOCK(pub) dhd_os_wd_wake_lock(pub) ++#define DHD_OS_WD_WAKE_UNLOCK(pub) dhd_os_wd_wake_unlock(pub) ++#ifdef BCMPCIE_OOB_HOST_WAKE ++#define OOB_WAKE_LOCK_TIMEOUT 500 ++#define DHD_OS_OOB_IRQ_WAKE_LOCK_TIMEOUT(pub, val) dhd_os_oob_irq_wake_lock_timeout(pub, val) ++#define DHD_OS_OOB_IRQ_WAKE_UNLOCK(pub) dhd_os_oob_irq_wake_unlock(pub) ++#endif /* BCMPCIE_OOB_HOST_WAKE */ ++#define DHD_PACKET_TIMEOUT_MS 500 ++#define DHD_EVENT_TIMEOUT_MS 1500 + -+ chspec |= bw; + -+ if (bw == WL_CHANSPEC_BW_40) { -+ center_ch = wf_5g_40m_chans; -+ num_ch = WF_NUM_5G_40M_CHANS; -+ bw = 40; -+ } else if (bw == WL_CHANSPEC_BW_80) { -+ center_ch = wf_5g_80m_chans; -+ num_ch = WF_NUM_5G_80M_CHANS; -+ bw = 80; -+ } else if (bw == WL_CHANSPEC_BW_160) { -+ center_ch = wf_5g_160m_chans; -+ num_ch = WF_NUM_5G_160M_CHANS; -+ bw = 160; -+ } else if (bw == WL_CHANSPEC_BW_20) { -+ chspec |= ctl_ch; -+ return chspec; -+ } else { -+ return 0; -+ } ++/* interface operations (register, remove) should be atomic, use this lock to prevent race ++ * condition among wifi on/off and interface operation functions ++ */ ++void dhd_net_if_lock(struct net_device *dev); ++void dhd_net_if_unlock(struct net_device *dev); + -+ for (i = 0; i < num_ch; i ++) { -+ sb = channel_to_sb(center_ch[i], ctl_ch, bw); -+ if (sb >= 0) { -+ chspec |= center_ch[i]; -+ chspec |= (sb << WL_CHANSPEC_CTL_SB_SHIFT); -+ break; -+ } -+ } ++#if defined(MULTIPLE_SUPPLICANT) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++extern struct mutex _dhd_sdio_mutex_lock_; ++#endif ++#endif /* MULTIPLE_SUPPLICANT */ + -+ /* check for no matching sb/center */ -+ if (sb < 0) { -+ return 0; -+ } ++typedef enum dhd_attach_states ++{ ++ DHD_ATTACH_STATE_INIT = 0x0, ++ DHD_ATTACH_STATE_NET_ALLOC = 0x1, ++ DHD_ATTACH_STATE_DHD_ALLOC = 0x2, ++ DHD_ATTACH_STATE_ADD_IF = 0x4, ++ DHD_ATTACH_STATE_PROT_ATTACH = 0x8, ++ DHD_ATTACH_STATE_WL_ATTACH = 0x10, ++ DHD_ATTACH_STATE_THREADS_CREATED = 0x20, ++ DHD_ATTACH_STATE_WAKELOCKS_INIT = 0x40, ++ DHD_ATTACH_STATE_CFG80211 = 0x80, ++ DHD_ATTACH_STATE_EARLYSUSPEND_DONE = 0x100, ++ DHD_ATTACH_STATE_DONE = 0x200 ++} dhd_attach_states_t; + -+ return chspec; -+} ++/* Value -1 means we are unsuccessful in creating the kthread. */ ++#define DHD_PID_KT_INVALID -1 ++/* Value -2 means we are unsuccessful in both creating the kthread and tasklet */ ++#define DHD_PID_KT_TL_INVALID -2 + +/* -+ * This function returns the chanspec for the primary 40MHz of an 80MHz channel. -+ * The control sideband specifies the same 20MHz channel that the 80MHz channel is using -+ * as the primary 20MHz channel. ++ * Exported from dhd OS modules (dhd_linux/dhd_ndis) + */ -+extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec) -+{ -+ chanspec_t chspec40 = chspec; -+ uint center_chan; -+ uint sb; + -+ ASSERT(!wf_chspec_malformed(chspec)); ++/* Indication from bus module regarding presence/insertion of dongle. ++ * Return dhd_pub_t pointer, used as handle to OS module in later calls. ++ * Returned structure should have bus and prot pointers filled in. ++ * bus_hdrlen specifies required headroom for bus module header. ++ */ ++extern dhd_pub_t *dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen); ++#if defined(WLP2P) && defined(WL_CFG80211) ++/* To allow attach/detach calls corresponding to p2p0 interface */ ++extern int dhd_attach_p2p(dhd_pub_t *); ++extern int dhd_detach_p2p(dhd_pub_t *); ++#endif /* WLP2P && WL_CFG80211 */ ++extern int dhd_register_if(dhd_pub_t *dhdp, int idx, bool need_rtnl_lock); ++ ++/* Indication from bus module regarding removal/absence of dongle */ ++extern void dhd_detach(dhd_pub_t *dhdp); ++extern void dhd_free(dhd_pub_t *dhdp); ++extern void dhd_clear(dhd_pub_t *dhdp); ++ ++/* Indication from bus module to change flow-control state */ ++extern void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool on); + -+ /* if the chanspec is > 80MHz, use the helper routine to find the primary 80 MHz channel */ -+ if (CHSPEC_IS8080(chspec) || CHSPEC_IS160(chspec)) { -+ chspec = wf_chspec_primary80_chspec(chspec); -+ } ++/* Store the status of a connection attempt for later retrieval by an iovar */ ++extern void dhd_store_conn_status(uint32 event, uint32 status, uint32 reason); + -+ /* determine primary 40 MHz sub-channel of an 80 MHz chanspec */ -+ if (CHSPEC_IS80(chspec)) { -+ center_chan = CHSPEC_CHANNEL(chspec); -+ sb = CHSPEC_CTL_SB(chspec); ++extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec); + -+ if (sb < WL_CHANSPEC_CTL_SB_UL) { -+ /* Primary 40MHz is on lower side */ -+ center_chan -= CH_20MHZ_APART; -+ /* sideband bits are the same for LL/LU and L/U */ -+ } else { -+ /* Primary 40MHz is on upper side */ -+ center_chan += CH_20MHZ_APART; -+ /* sideband bits need to be adjusted by UL offset */ -+ sb -= WL_CHANSPEC_CTL_SB_UL; -+ } ++/* Receive frame for delivery to OS. Callee disposes of rxp. */ ++extern void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *rxp, int numpkt, uint8 chan); + -+ /* Create primary 40MHz chanspec */ -+ chspec40 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_40 | -+ sb | center_chan); -+ } ++/* Return pointer to interface name */ ++extern char *dhd_ifname(dhd_pub_t *dhdp, int idx); + -+ return chspec40; -+} ++/* Request scheduling of the bus dpc */ ++extern void dhd_sched_dpc(dhd_pub_t *dhdp); + -+/* -+ * Return the channel number for a given frequency and base frequency. -+ * The returned channel number is relative to the given base frequency. -+ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for -+ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz. -+ * -+ * Frequency is specified in MHz. -+ * The base frequency is specified as (start_factor * 500 kHz). -+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for -+ * 2.4 GHz and 5 GHz bands. -+ * -+ * The returned channel will be in the range [1, 14] in the 2.4 GHz band -+ * and [0, 200] otherwise. -+ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the -+ * frequency is not a 2.4 GHz channel, or if the frequency is not and even -+ * multiple of 5 MHz from the base frequency to the base plus 1 GHz. -+ * -+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 -+ */ -+int -+wf_mhz2channel(uint freq, uint start_factor) -+{ -+ int ch = -1; -+ uint base; -+ int offset; ++/* Notify tx completion */ ++extern void dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success); + -+ /* take the default channel start frequency */ -+ if (start_factor == 0) { -+ if (freq >= 2400 && freq <= 2500) -+ start_factor = WF_CHAN_FACTOR_2_4_G; -+ else if (freq >= 5000 && freq <= 6000) -+ start_factor = WF_CHAN_FACTOR_5_G; -+ } ++/* OS independent layer functions */ ++extern int dhd_os_proto_block(dhd_pub_t * pub); ++extern int dhd_os_proto_unblock(dhd_pub_t * pub); ++extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition, bool * pending); ++extern int dhd_os_ioctl_resp_wake(dhd_pub_t * pub); ++extern unsigned int dhd_os_get_ioctl_resp_timeout(void); ++extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec); + -+ if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G) -+ return 14; ++extern int dhd_os_get_image_block(char * buf, int len, void * image); ++extern void * dhd_os_open_image(char * filename); ++extern void dhd_os_close_image(void * image); ++extern void dhd_os_wd_timer(void *bus, uint wdtick); ++extern void dhd_os_sdlock(dhd_pub_t * pub); ++extern void dhd_os_sdunlock(dhd_pub_t * pub); ++extern void dhd_os_sdlock_txq(dhd_pub_t * pub); ++extern void dhd_os_sdunlock_txq(dhd_pub_t * pub); ++extern void dhd_os_sdlock_rxq(dhd_pub_t * pub); ++extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub); ++extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub); ++#ifdef DHDTCPACK_SUPPRESS ++extern void dhd_os_tcpacklock(dhd_pub_t *pub); ++extern void dhd_os_tcpackunlock(dhd_pub_t *pub); ++#endif /* DHDTCPACK_SUPPRESS */ + -+ base = start_factor / 2; ++extern int dhd_customer_oob_irq_map(void *adapter, unsigned long *irq_flags_ptr); ++extern int dhd_customer_gpio_wlan_ctrl(void *adapter, int onoff); ++extern int dhd_custom_get_mac_address(void *adapter, unsigned char *buf); ++extern void get_customized_country_code(void *adapter, char *country_iso_code, wl_country_t *cspec); ++extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub); ++extern void dhd_os_sdlock_eventq(dhd_pub_t * pub); ++extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub); ++extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret); ++extern int dhd_os_send_hang_message(dhd_pub_t *dhdp); ++extern void dhd_set_version_info(dhd_pub_t *pub, char *fw); ++extern bool dhd_os_check_if_up(dhd_pub_t *pub); ++extern int dhd_os_check_wakelock(dhd_pub_t *pub); ++extern int dhd_os_check_wakelock_all(dhd_pub_t *pub); ++extern int dhd_get_instance(dhd_pub_t *pub); ++#ifdef CUSTOM_SET_CPUCORE ++extern void dhd_set_cpucore(dhd_pub_t *dhd, int set); ++#endif /* CUSTOM_SET_CPUCORE */ + -+ /* check that the frequency is in 1GHz range of the base */ -+ if ((freq < base) || (freq > base + 1000)) -+ return -1; ++#if defined(KEEP_ALIVE) ++extern int dhd_keep_alive_onoff(dhd_pub_t *dhd); ++#endif /* KEEP_ALIVE */ + -+ offset = freq - base; -+ ch = offset / 5; ++#ifdef SUPPORT_AP_POWERSAVE ++extern int dhd_set_ap_powersave(dhd_pub_t *dhdp, int ifidx, int enable); ++#endif + -+ /* check that frequency is a 5MHz multiple from the base */ -+ if (offset != (ch * 5)) -+ return -1; + -+ /* restricted channel range check for 2.4G */ -+ if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13)) -+ return -1; ++#ifdef PKT_FILTER_SUPPORT ++#define DHD_UNICAST_FILTER_NUM 0 ++#define DHD_BROADCAST_FILTER_NUM 1 ++#define DHD_MULTICAST4_FILTER_NUM 2 ++#define DHD_MULTICAST6_FILTER_NUM 3 ++#define DHD_MDNS_FILTER_NUM 4 ++#define DHD_ARP_FILTER_NUM 5 + -+ return ch; -+} ++#if defined(CUSTOM_PLATFORM_NV_TEGRA) ++/* Port based packet filtering command actions */ ++#define PKT_FILTER_PORTS_CLEAR 0 ++#define PKT_FILTER_PORTS_ADD 1 ++#define PKT_FILTER_PORTS_DEL 2 ++#define PKT_FILTER_PORTS_LOOPBACK 3 ++#define PKT_FILTER_PORTS_MAX PKT_FILTER_PORTS_LOOPBACK ++#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */ + -+/* -+ * Return the center frequency in MHz of the given channel and base frequency. -+ * The channel number is interpreted relative to the given base frequency. -+ * -+ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise. -+ * The base frequency is specified as (start_factor * 500 kHz). -+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_4_G, and WF_CHAN_FACTOR_5_G -+ * are defined for 2.4 GHz, 4 GHz, and 5 GHz bands. -+ * The channel range of [1, 14] is only checked for a start_factor of -+ * WF_CHAN_FACTOR_2_4_G (4814 = 2407 * 2). -+ * Odd start_factors produce channels on .5 MHz boundaries, in which case -+ * the answer is rounded down to an integral MHz. -+ * -1 is returned for an out of range channel. -+ * -+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 -+ */ -+int -+wf_channel2mhz(uint ch, uint start_factor) -+{ -+ int freq; ++extern int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val); ++extern void dhd_enable_packet_filter(int value, dhd_pub_t *dhd); ++extern int net_os_enable_packet_filter(struct net_device *dev, int val); ++extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); ++#if defined(CUSTOM_PLATFORM_NV_TEGRA) ++extern void dhd_set_packet_filter_mode(struct net_device *dev, char *command); ++extern int dhd_set_packet_filter_ports(struct net_device *dev, char *command); ++#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */ ++#endif /* PKT_FILTER_SUPPORT */ + -+ if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) || -+ (ch > 200)) -+ freq = -1; -+ else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14)) -+ freq = 2484; -+ else -+ freq = ch * 5 + start_factor / 2; ++extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd); ++extern bool dhd_support_sta_mode(dhd_pub_t *dhd); + -+ return freq; -+} ++#ifdef DHD_DEBUG ++extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size); ++#endif /* DHD_DEBUG */ + -+static const uint16 sidebands[] = { -+ WL_CHANSPEC_CTL_SB_LLL, WL_CHANSPEC_CTL_SB_LLU, -+ WL_CHANSPEC_CTL_SB_LUL, WL_CHANSPEC_CTL_SB_LUU, -+ WL_CHANSPEC_CTL_SB_ULL, WL_CHANSPEC_CTL_SB_ULU, -+ WL_CHANSPEC_CTL_SB_UUL, WL_CHANSPEC_CTL_SB_UUU -+}; ++typedef struct { ++ uint32 limit; /* Expiration time (usec) */ ++ uint32 increment; /* Current expiration increment (usec) */ ++ uint32 elapsed; /* Current elapsed time (usec) */ ++ uint32 tick; /* O/S tick time (usec) */ ++} dhd_timeout_t; + -+/* -+ * Returns the chanspec 80Mhz channel corresponding to the following input -+ * parameters -+ * -+ * primary_channel - primary 20Mhz channel -+ * center_channel - center frequecny of the 80Mhz channel -+ * -+ * The center_channel can be one of {42, 58, 106, 122, 138, 155} -+ * -+ * returns INVCHANSPEC in case of error -+ */ -+chanspec_t -+wf_chspec_80(uint8 center_channel, uint8 primary_channel) -+{ ++#ifdef SHOW_LOGTRACE ++typedef struct { ++ int num_fmts; ++ char **fmts; ++ char *raw_fmts; ++} dhd_event_log_t; ++#endif /* SHOW_LOGTRACE */ + -+ chanspec_t chanspec = INVCHANSPEC; -+ chanspec_t chanspec_cur; -+ uint i; ++extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec); ++extern int dhd_timeout_expired(dhd_timeout_t *tmo); + -+ for (i = 0; i < WF_NUM_SIDEBANDS_80MHZ; i++) { -+ chanspec_cur = CH80MHZ_CHSPEC(center_channel, sidebands[i]); -+ if (primary_channel == wf_chspec_ctlchan(chanspec_cur)) { -+ chanspec = chanspec_cur; -+ break; -+ } -+ } -+ /* If the loop ended early, we are good, otherwise we did not -+ * find a 80MHz chanspec with the given center_channel that had a primary channel -+ *matching the given primary_channel. -+ */ -+ return chanspec; -+} ++extern int dhd_ifname2idx(struct dhd_info *dhd, char *name); ++extern int dhd_ifidx2hostidx(struct dhd_info *dhd, int ifidx); ++extern int dhd_net2idx(struct dhd_info *dhd, struct net_device *net); ++extern struct net_device * dhd_idx2net(void *pub, int ifidx); ++extern int net_os_send_hang_message(struct net_device *dev); ++extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata, ++ wl_event_msg_t *, void **data_ptr, void *); ++extern void wl_event_to_host_order(wl_event_msg_t * evt); + -+/* -+ * Returns the 80+80 chanspec corresponding to the following input parameters -+ * -+ * primary_20mhz - Primary 20 MHz channel -+ * chan0 - center channel number of one frequency segment -+ * chan1 - center channel number of the other frequency segment -+ * -+ * Parameters chan0 and chan1 are channel numbers in {42, 58, 106, 122, 138, 155}. -+ * The primary channel must be contained in one of the 80MHz channels. This routine -+ * will determine which frequency segment is the primary 80 MHz segment. -+ * -+ * Returns INVCHANSPEC in case of error. -+ * -+ * Refer to IEEE802.11ac section 22.3.14 "Channelization". -+ */ -+chanspec_t -+wf_chspec_get8080_chspec(uint8 primary_20mhz, uint8 chan0, uint8 chan1) -+{ -+ int sb = 0; -+ uint16 chanspec = 0; -+ int chan0_id = 0, chan1_id = 0; -+ int seg0, seg1; ++extern int dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len); ++extern int dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, ++ int ifindex); ++extern void dhd_common_init(osl_t *osh); + -+ chan0_id = channel_80mhz_to_id(chan0); -+ chan1_id = channel_80mhz_to_id(chan1); ++extern int dhd_do_driver_init(struct net_device *net); ++extern int dhd_event_ifadd(struct dhd_info *dhd, struct wl_event_data_if *ifevent, ++ char *name, uint8 *mac); ++extern int dhd_event_ifdel(struct dhd_info *dhd, struct wl_event_data_if *ifevent, ++ char *name, uint8 *mac); ++extern struct net_device* dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, char *name, ++ uint8 *mac, uint8 bssidx, bool need_rtnl_lock); ++extern int dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock); ++extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char * name); ++extern void dhd_vif_del(struct dhd_info *dhd, int ifidx); ++extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx); ++extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, uchar *cp, int len); + -+ /* make sure the channel numbers were valid */ -+ if (chan0_id == -1 || chan1_id == -1) -+ return INVCHANSPEC; ++/* Send packet to dongle via data channel */ ++extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pkt); + -+ /* does the primary channel fit with the 1st 80MHz channel ? */ -+ sb = channel_to_sb(chan0, primary_20mhz, 80); -+ if (sb >= 0) { -+ /* yes, so chan0 is frequency segment 0, and chan1 is seg 1 */ -+ seg0 = chan0_id; -+ seg1 = chan1_id; -+ } else { -+ /* no, so does the primary channel fit with the 2nd 80MHz channel ? */ -+ sb = channel_to_sb(chan1, primary_20mhz, 80); -+ if (sb < 0) { -+ /* no match for ctl_ch to either 80MHz center channel */ -+ return INVCHANSPEC; -+ } -+ /* swapped, so chan1 is frequency segment 0, and chan0 is seg 1 */ -+ seg0 = chan1_id; -+ seg1 = chan0_id; -+ } ++/* send up locally generated event */ ++extern void dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data); ++/* Send event to host */ ++extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data); ++#ifdef LOG_INTO_TCPDUMP ++extern void dhd_sendup_log(dhd_pub_t *dhdp, void *data, int len); ++#endif /* LOG_INTO_TCPDUMP */ ++extern int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag); ++extern uint dhd_bus_status(dhd_pub_t *dhdp); ++extern int dhd_bus_start(dhd_pub_t *dhdp); ++extern int dhd_bus_suspend(dhd_pub_t *dhdpub); ++extern int dhd_bus_resume(dhd_pub_t *dhdpub, int stage); ++extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size); ++extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line); ++extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval); ++#if defined(BCMSDIO) || defined(BCMPCIE) ++extern uint dhd_bus_chip_id(dhd_pub_t *dhdp); ++extern uint dhd_bus_chiprev_id(dhd_pub_t *dhdp); ++extern uint dhd_bus_chippkg_id(dhd_pub_t *dhdp); ++#endif /* defined(BCMSDIO) || defined(BCMPCIE) */ + -+ chanspec = ((seg0 << WL_CHANSPEC_CHAN1_SHIFT) | -+ (seg1 << WL_CHANSPEC_CHAN2_SHIFT) | -+ (sb << WL_CHANSPEC_CTL_SB_SHIFT) | -+ WL_CHANSPEC_BW_8080 | -+ WL_CHANSPEC_BAND_5G); ++#if defined(KEEP_ALIVE) ++extern int dhd_keep_alive_onoff(dhd_pub_t *dhd); ++#endif /* KEEP_ALIVE */ + -+ return chanspec; -+} ++/* OS spin lock API */ ++extern void *dhd_os_spin_lock_init(osl_t *osh); ++extern void dhd_os_spin_lock_deinit(osl_t *osh, void *lock); ++extern unsigned long dhd_os_spin_lock(void *lock); ++void dhd_os_spin_unlock(void *lock, unsigned long flags); + +/* -+ * This function returns the 80Mhz channel for the given id. ++ * Manage sta objects in an interface. Interface is identified by an ifindex and ++ * sta(s) within an interfaces are managed using a MacAddress of the sta. + */ -+static uint8 -+wf_chspec_get80Mhz_ch(uint8 chan_80Mhz_id) -+{ -+ if (chan_80Mhz_id < WF_NUM_5G_80M_CHANS) -+ return wf_5g_80m_chans[chan_80Mhz_id]; ++struct dhd_sta; ++extern struct dhd_sta *dhd_findadd_sta(void *pub, int ifidx, void *ea); ++extern void dhd_del_sta(void *pub, int ifidx, void *ea); ++extern int dhd_get_ap_isolate(dhd_pub_t *dhdp, uint32 idx); ++extern int dhd_set_ap_isolate(dhd_pub_t *dhdp, uint32 idx, int val); ++extern int dhd_bssidx2idx(dhd_pub_t *dhdp, uint32 bssidx); + -+ return 0; -+} ++extern bool dhd_is_concurrent_mode(dhd_pub_t *dhd); ++extern int dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set); ++typedef enum cust_gpio_modes { ++ WLAN_RESET_ON, ++ WLAN_RESET_OFF, ++ WLAN_POWER_ON, ++ WLAN_POWER_OFF ++} cust_gpio_modes_t; + ++extern int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag); ++extern int wl_iw_send_priv_event(struct net_device *dev, char *flag); +/* -+ * Returns the primary 80 Mhz channel for the provided chanspec -+ * -+ * chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved -+ * -+ * returns -1 in case the provided channel is 20/40 Mhz chanspec ++ * Insmod parameters for debug/test + */ + -+uint8 -+wf_chspec_primary80_channel(chanspec_t chanspec) -+{ -+ uint8 primary80_chan; ++/* Watchdog timer interval */ ++extern uint dhd_watchdog_ms; + -+ if (CHSPEC_IS80(chanspec)) { -+ primary80_chan = CHSPEC_CHANNEL(chanspec); -+ } -+ else if (CHSPEC_IS8080(chanspec)) { -+ /* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */ -+ primary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chanspec)); -+ } -+ else if (CHSPEC_IS160(chanspec)) { -+ uint8 center_chan = CHSPEC_CHANNEL(chanspec); -+ uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT; ++#if defined(DHD_DEBUG) ++/* Console output poll interval */ ++extern uint dhd_console_ms; ++#endif /* defined(DHD_DEBUG) */ ++extern uint android_msg_level; ++extern uint config_msg_level; ++extern uint sd_msglevel; ++#ifdef WL_WIRELESS_EXT ++extern uint iw_msg_level; ++#endif ++#ifdef WL_CFG80211 ++extern uint wl_dbg_level; ++#endif + -+ /* based on the sb value primary 80 channel can be retrieved -+ * if sb is in range 0 to 3 the lower band is the 80Mhz primary band -+ */ -+ if (sb < 4) { -+ primary80_chan = center_chan - CH_40MHZ_APART; -+ } -+ /* if sb is in range 4 to 7 the upper band is the 80Mhz primary band */ -+ else -+ { -+ primary80_chan = center_chan + CH_40MHZ_APART; -+ } -+ } -+ else { -+ /* for 20 and 40 Mhz */ -+ primary80_chan = -1; -+ } -+ return primary80_chan; -+} ++#ifdef CUSTOMER_HW ++struct wifi_platform_data { ++ int (*set_power)(bool val); ++ int (*set_carddetect)(bool val); ++ void *(*mem_prealloc)(int section, unsigned long size); ++ int (*get_mac_addr)(unsigned char *buf); ++ void *(*get_country_code)(char *ccode); ++}; ++#endif + -+/* -+ * Returns the secondary 80 Mhz channel for the provided chanspec -+ * -+ * chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved -+ * -+ * returns -1 in case the provided channel is 20/40/80 Mhz chanspec -+ */ -+uint8 -+wf_chspec_secondary80_channel(chanspec_t chanspec) -+{ -+ uint8 secondary80_chan; ++extern uint dhd_slpauto; + -+ if (CHSPEC_IS8080(chanspec)) { -+ secondary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chanspec)); -+ } -+ else if (CHSPEC_IS160(chanspec)) { -+ uint8 center_chan = CHSPEC_CHANNEL(chanspec); -+ uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT; ++/* Use interrupts */ ++extern uint dhd_intr; + -+ /* based on the sb value secondary 80 channel can be retrieved -+ * if sb is in range 0 to 3 upper band is the secondary 80Mhz band -+ */ -+ if (sb < 4) { -+ secondary80_chan = center_chan + CH_40MHZ_APART; -+ } -+ /* if sb is in range 4 to 7 the lower band is the secondary 80Mhz band */ -+ else -+ { -+ secondary80_chan = center_chan - CH_40MHZ_APART; -+ } -+ } -+ else { -+ /* for 20, 40, and 80 Mhz */ -+ secondary80_chan = -1; -+ } -+ return secondary80_chan; -+} ++/* Use polling */ ++extern uint dhd_poll; + -+/* -+ * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel. -+ * -+ * chanspec - Input chanspec for which the primary 80Mhz chanspec has to be retreived -+ * -+ * returns the input chanspec in case the provided chanspec is an 80 MHz chanspec -+ * returns INVCHANSPEC in case the provided channel is 20/40 MHz chanspec -+ */ -+chanspec_t -+wf_chspec_primary80_chspec(chanspec_t chspec) -+{ -+ chanspec_t chspec80; -+ uint center_chan; -+ uint sb; ++/* ARP offload agent mode */ ++extern uint dhd_arp_mode; + -+ ASSERT(!wf_chspec_malformed(chspec)); -+ if (CHSPEC_IS80(chspec)) { -+ chspec80 = chspec; -+ } -+ else if (CHSPEC_IS8080(chspec)) { ++/* ARP offload enable */ ++extern uint dhd_arp_enable; + -+ /* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */ -+ center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec)); ++/* Pkt filte enable control */ ++extern uint dhd_pkt_filter_enable; + -+ sb = CHSPEC_CTL_SB(chspec); ++/* Pkt filter init setup */ ++extern uint dhd_pkt_filter_init; + -+ /* Create primary 80MHz chanspec */ -+ chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan); -+ } -+ else if (CHSPEC_IS160(chspec)) { -+ center_chan = CHSPEC_CHANNEL(chspec); -+ sb = CHSPEC_CTL_SB(chspec); ++/* Pkt filter mode control */ ++extern uint dhd_master_mode; + -+ if (sb < WL_CHANSPEC_CTL_SB_ULL) { -+ /* Primary 80MHz is on lower side */ -+ center_chan -= CH_40MHZ_APART; -+ } -+ else { -+ /* Primary 80MHz is on upper side */ -+ center_chan += CH_40MHZ_APART; -+ sb -= WL_CHANSPEC_CTL_SB_ULL; -+ } -+ /* Create primary 80MHz chanspec */ -+ chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan); -+ } -+ else { -+ chspec80 = INVCHANSPEC; -+ } ++/* Roaming mode control */ ++extern uint dhd_roam_disable; + -+ return chspec80; -+} ++/* Roaming mode control */ ++extern uint dhd_radio_up; + -+#ifdef WL11AC_80P80 -+uint8 -+wf_chspec_channel(chanspec_t chspec) -+{ -+ if (CHSPEC_IS8080(chspec)) { -+ return wf_chspec_primary80_channel(chspec); -+ } -+ else { -+ return ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)); -+ } -+} -+#endif /* WL11AC_80P80 */ -diff -ENwbur a/drivers/net/wireless/bcm4336/circularbuf.c b/drivers/net/wireless/bcm4336/circularbuf.c ---- a/drivers/net/wireless/bcm4336/circularbuf.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/circularbuf.c 2018-05-06 08:49:50.618753851 +0200 -@@ -0,0 +1,324 @@ -+/** @file circularbuf.c -+ * -+ * PCIe host driver and dongle firmware need to communicate with each other. The mechanism consists -+ * of multiple circular buffers located in (DMA'able) host memory. A circular buffer is either used -+ * for host -> dongle (h2d) or dongle -> host communication. Both host driver and firmware make use -+ * of this source file. This source file contains functions to manage such a set of circular -+ * buffers, but does not contain the code to read or write the data itself into the buffers. It -+ * leaves that up to the software layer that uses this file, which can be implemented either using -+ * pio or DMA transfers. It also leaves the format of the data that is written and read to a higher -+ * layer. Typically the data is in the form of so-called 'message buffers'. -+ * -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * $Id: circularbuf.c 467150 2014-04-02 17:30:43Z $ -+ */ ++/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */ ++extern int dhd_idletime; ++#ifdef DHD_USE_IDLECOUNT ++#define DHD_IDLETIME_TICKS 5 ++#else ++#define DHD_IDLETIME_TICKS 1 ++#endif /* DHD_USE_IDLECOUNT */ + -+#include -+#include -+#include ++/* SDIO Drive Strength */ ++extern uint dhd_sdiod_drive_strength; + -+#define CIRCULARBUF_READ_SPACE_AT_END(x) \ -+ ((x->w_ptr >= x->rp_ptr) ? (x->w_ptr - x->rp_ptr) : (x->e_ptr - x->rp_ptr)) ++/* Override to force tx queueing all the time */ ++extern uint dhd_force_tx_queueing; ++/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ ++#define DEFAULT_KEEP_ALIVE_VALUE 55000 /* msec */ ++#ifndef CUSTOM_KEEP_ALIVE_SETTING ++#define CUSTOM_KEEP_ALIVE_SETTING DEFAULT_KEEP_ALIVE_VALUE ++#endif /* DEFAULT_KEEP_ALIVE_VALUE */ + -+#define CIRCULARBUF_READ_SPACE_AVAIL(x) \ -+ (((CIRCULARBUF_READ_SPACE_AT_END(x) == 0) && (x->w_ptr < x->rp_ptr)) ? \ -+ x->w_ptr : CIRCULARBUF_READ_SPACE_AT_END(x)) ++#define NULL_PKT_STR "null_pkt" + -+int cbuf_msg_level = CBUF_ERROR_VAL | CBUF_TRACE_VAL | CBUF_INFORM_VAL; ++/* hooks for custom glom setting option via Makefile */ ++#define DEFAULT_GLOM_VALUE -1 ++#ifndef CUSTOM_GLOM_SETTING ++#define CUSTOM_GLOM_SETTING DEFAULT_GLOM_VALUE ++#endif ++#define WL_AUTO_ROAM_TRIGGER -75 ++/* hooks for custom Roaming Trigger setting via Makefile */ ++#define DEFAULT_ROAM_TRIGGER_VALUE -75 /* dBm default roam trigger all band */ ++#define DEFAULT_ROAM_TRIGGER_SETTING -1 ++#ifndef CUSTOM_ROAM_TRIGGER_SETTING ++#define CUSTOM_ROAM_TRIGGER_SETTING DEFAULT_ROAM_TRIGGER_VALUE ++#endif + -+/* #define CBUF_DEBUG */ -+#ifdef CBUF_DEBUG -+#define CBUF_DEBUG_CHECK(x) x -+#else -+#define CBUF_DEBUG_CHECK(x) -+#endif /* CBUF_DEBUG */ ++/* hooks for custom Roaming Romaing setting via Makefile */ ++#define DEFAULT_ROAM_DELTA_VALUE 10 /* dBm default roam delta all band */ ++#define DEFAULT_ROAM_DELTA_SETTING -1 ++#ifndef CUSTOM_ROAM_DELTA_SETTING ++#define CUSTOM_ROAM_DELTA_SETTING DEFAULT_ROAM_DELTA_VALUE ++#endif + -+/** -+ * ----------------------------------------------------------------------------- -+ * Function : circularbuf_init -+ * Description: -+ * -+ * -+ * Input Args : buf_base_addr: address of DMA'able host memory provided by caller -+ * -+ * -+ * Return Values : -+ * -+ * ----------------------------------------------------------------------------- -+ */ -+void -+circularbuf_init(circularbuf_t *handle, void *buf_base_addr, uint16 total_buf_len) -+{ -+ handle->buf_addr = buf_base_addr; ++/* hooks for custom PNO Event wake lock to guarantee enough time ++ for the Platform to detect Event before system suspended ++*/ ++#define DEFAULT_PNO_EVENT_LOCK_xTIME 2 /* multiplay of DHD_PACKET_TIMEOUT_MS */ ++#ifndef CUSTOM_PNO_EVENT_LOCK_xTIME ++#define CUSTOM_PNO_EVENT_LOCK_xTIME DEFAULT_PNO_EVENT_LOCK_xTIME ++#endif ++/* hooks for custom dhd_dpc_prio setting option via Makefile */ ++#define DEFAULT_DHP_DPC_PRIO 1 ++#ifndef CUSTOM_DPC_PRIO_SETTING ++#define CUSTOM_DPC_PRIO_SETTING DEFAULT_DHP_DPC_PRIO ++#endif + -+ handle->depth = handle->e_ptr = HTOL32(total_buf_len); ++#ifndef CUSTOM_LISTEN_INTERVAL ++#define CUSTOM_LISTEN_INTERVAL LISTEN_INTERVAL ++#endif /* CUSTOM_LISTEN_INTERVAL */ + -+ /* Initialize Read and Write pointers */ -+ handle->w_ptr = handle->r_ptr = handle->wp_ptr = handle->rp_ptr = HTOL32(0); -+ handle->mb_ring_bell = NULL; -+ handle->mb_ctx = NULL; ++#define DEFAULT_SUSPEND_BCN_LI_DTIM 3 ++#ifndef CUSTOM_SUSPEND_BCN_LI_DTIM ++#define CUSTOM_SUSPEND_BCN_LI_DTIM DEFAULT_SUSPEND_BCN_LI_DTIM ++#endif + -+ return; -+} ++#ifndef CUSTOM_RXF_PRIO_SETTING ++#define CUSTOM_RXF_PRIO_SETTING MAX((CUSTOM_DPC_PRIO_SETTING - 1), 1) ++#endif + -+/** -+ * When an item is added to the circular buffer by the producing party, the consuming party has to -+ * be notified by means of a 'door bell' or 'ring'. This function allows the caller to register a -+ * 'ring' function that will be called when a 'write complete' occurs. -+ */ -+void -+circularbuf_register_cb(circularbuf_t *handle, mb_ring_t mb_ring_func, void *ctx) -+{ -+ handle->mb_ring_bell = mb_ring_func; -+ handle->mb_ctx = ctx; -+} ++#define DEFAULT_WIFI_TURNOFF_DELAY 0 ++#ifndef WIFI_TURNOFF_DELAY ++#define WIFI_TURNOFF_DELAY DEFAULT_WIFI_TURNOFF_DELAY ++#endif /* WIFI_TURNOFF_DELAY */ + -+#ifdef CBUF_DEBUG -+static void -+circularbuf_check_sanity(circularbuf_t *handle) -+{ -+ if ((handle->e_ptr > handle->depth) || -+ (handle->r_ptr > handle->e_ptr) || -+ (handle->rp_ptr > handle->e_ptr) || -+ (handle->w_ptr > handle->e_ptr)) -+ { -+ printf("%s:%d: Pointers are corrupted.\n", __FUNCTION__, __LINE__); -+ circularbuf_debug_print(handle); -+ ASSERT(0); -+ } -+ return; -+} -+#endif /* CBUF_DEBUG */ ++#define DEFAULT_WIFI_TURNON_DELAY 200 ++#ifndef WIFI_TURNON_DELAY ++#define WIFI_TURNON_DELAY DEFAULT_WIFI_TURNON_DELAY ++#endif /* WIFI_TURNON_DELAY */ + -+/** -+ * ----------------------------------------------------------------------------- -+ * Function : circularbuf_reserve_for_write -+ * -+ * Description: -+ * This function reserves N bytes for write in the circular buffer. The circularbuf -+ * implementation will only reserve space in the circular buffer and return -+ * the pointer to the address where the new data can be written. -+ * The actual write implementation (bcopy/dma) is outside the scope of -+ * circularbuf implementation. -+ * -+ * Input Args : -+ * size - No. of bytes to reserve for write -+ * -+ * Return Values : -+ * void * : Pointer to the reserved location. This is the address -+ * that will be used for write (dma/bcopy) -+ * -+ * ----------------------------------------------------------------------------- -+ */ -+void * BCMFASTPATH -+circularbuf_reserve_for_write(circularbuf_t *handle, uint16 size) -+{ -+ int16 avail_space; -+ void *ret_ptr = NULL; ++#ifdef BCMSDIO ++#define DEFAULT_DHD_WATCHDOG_INTERVAL_MS 10 /* msec */ ++#else ++#define DEFAULT_DHD_WATCHDOG_INTERVAL_MS 0 /* msec */ ++#endif ++#ifndef CUSTOM_DHD_WATCHDOG_MS ++#define CUSTOM_DHD_WATCHDOG_MS DEFAULT_DHD_WATCHDOG_INTERVAL_MS ++#endif /* DEFAULT_DHD_WATCHDOG_INTERVAL_MS */ + -+ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle)); -+ ASSERT(size < handle->depth); ++#ifdef WLTDLS ++#ifndef CUSTOM_TDLS_IDLE_MODE_SETTING ++#define CUSTOM_TDLS_IDLE_MODE_SETTING 60000 /* 60sec to tear down TDLS of not active */ ++#endif ++#ifndef CUSTOM_TDLS_RSSI_THRESHOLD_HIGH ++#define CUSTOM_TDLS_RSSI_THRESHOLD_HIGH -70 /* rssi threshold for establishing TDLS link */ ++#endif ++#ifndef CUSTOM_TDLS_RSSI_THRESHOLD_LOW ++#define CUSTOM_TDLS_RSSI_THRESHOLD_LOW -80 /* rssi threshold for tearing down TDLS link */ ++#endif ++#endif /* WLTDLS */ + -+ if (handle->wp_ptr >= handle->r_ptr) -+ avail_space = handle->depth - handle->wp_ptr; -+ else -+ avail_space = handle->r_ptr - handle->wp_ptr; ++#define DEFAULT_BCN_TIMEOUT 8 ++#ifndef CUSTOM_BCN_TIMEOUT ++#define CUSTOM_BCN_TIMEOUT DEFAULT_BCN_TIMEOUT ++#endif + -+ ASSERT(avail_space <= handle->depth); -+ if (avail_space > size) -+ { -+ /* Great. We have enough space. */ -+ ret_ptr = CIRCULARBUF_START(handle) + handle->wp_ptr; ++#define MAX_DTIM_SKIP_BEACON_INTERVAL 100 /* max allowed associated AP beacon for DTIM skip */ ++#ifndef MAX_DTIM_ALLOWED_INTERVAL ++#define MAX_DTIM_ALLOWED_INTERVAL 600 /* max allowed total beacon interval for DTIM skip */ ++#endif ++#define NO_DTIM_SKIP 1 ++#ifdef SDTEST ++/* Echo packet generator (SDIO), pkts/s */ ++extern uint dhd_pktgen; + -+ /* -+ * We need to update the wp_ptr for the next guy to write. -+ * -+ * Please Note : We are not updating the write pointer here. This can be -+ * done only after write is complete (In case of DMA, we can only schedule -+ * the DMA. Actual completion will be known only on DMA complete interrupt). -+ */ -+ handle->wp_ptr += size; -+ return ret_ptr; -+ } ++/* Echo packet len (0 => sawtooth, max 1800) */ ++extern uint dhd_pktgen_len; ++#define MAX_PKTGEN_LEN 1800 ++#endif + -+ /* -+ * If there is no available space, we should check if there is some space left -+ * in the beginning of the circular buffer. Wrap-around case, where there is -+ * not enough space in the end of the circular buffer. But, there might be -+ * room in the beginning of the buffer. -+ */ -+ if (handle->wp_ptr >= handle->r_ptr) -+ { -+ avail_space = handle->r_ptr; -+ if (avail_space > size) -+ { -+ /* OK. There is room in the beginning. Let's go ahead and use that. -+ * But, before that, we have left a hole at the end of the circular -+ * buffer as that was not sufficient to accomodate the requested -+ * size. Let's make sure this is updated in the circularbuf structure -+ * so that consumer does not use the hole. -+ */ -+ handle->e_ptr = handle->wp_ptr; -+ handle->wp_ptr = size; + -+ return CIRCULARBUF_START(handle); -+ } -+ } ++/* optionally set by a module_param_string() */ ++#define MOD_PARAM_PATHLEN 2048 ++#define MOD_PARAM_INFOLEN 512 + -+ /* We have tried enough to accomodate the new packet. There is no room for now. */ -+ return NULL; -+} ++#ifdef SOFTAP ++extern char fw_path2[MOD_PARAM_PATHLEN]; ++#endif + -+/** -+ * ----------------------------------------------------------------------------- -+ * Function : circularbuf_write_complete -+ * -+ * Description: -+ * This function has to be called by the producer end of circularbuf to indicate to -+ * the circularbuf layer that data has been written and the write pointer can be -+ * updated. In the process, if there was a doorbell callback registered, that -+ * function would also be invoked as to notify the consuming party. -+ * -+ * Input Args : -+ * dest_addr : Address where the data was written. This would be the -+ * same address that was reserved earlier. -+ * bytes_written : Length of data written -+ * -+ * ----------------------------------------------------------------------------- -+ */ -+void BCMFASTPATH -+circularbuf_write_complete(circularbuf_t *handle, uint16 bytes_written) -+{ -+ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle)); ++/* Flag to indicate if we should download firmware on driver load */ ++extern uint dhd_download_fw_on_driverload; + -+ /* Update the write pointer */ -+ if ((handle->w_ptr + bytes_written) >= handle->depth) { -+ OSL_CACHE_FLUSH((void *) CIRCULARBUF_START(handle), bytes_written); -+ handle->w_ptr = bytes_written; -+ } else { -+ OSL_CACHE_FLUSH((void *) (CIRCULARBUF_START(handle) + handle->w_ptr), -+ bytes_written); -+ handle->w_ptr += bytes_written; -+ } + -+ /* And ring the door bell (mail box interrupt) to indicate to the peer that -+ * message is available for consumption. -+ */ -+ if (handle->mb_ring_bell) -+ handle->mb_ring_bell(handle->mb_ctx); -+} ++extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar); ++extern void dhd_wait_event_wakeup(dhd_pub_t*dhd); + -+/** -+ * ----------------------------------------------------------------------------- -+ * Function : circularbuf_get_read_ptr -+ * -+ * Description: -+ * This function will be called by the consumer of circularbuf for reading data from -+ * the circular buffer. This will typically be invoked when the consumer gets a -+ * doorbell interrupt. -+ * Please note that the function only returns the pointer (and length) from -+ * where the data can be read. Actual read implementation is up to the -+ * consumer. It could be a bcopy or dma. -+ * -+ * Input Args : -+ * void * : Address from where the data can be read. -+ * available_len : Length of data available for read. -+ * -+ * ----------------------------------------------------------------------------- -+ */ -+void * BCMFASTPATH -+circularbuf_get_read_ptr(circularbuf_t *handle, uint16 *available_len) -+{ -+ uint8 *ret_addr; ++#define IFLOCK_INIT(lock) *lock = 0 ++#define IFLOCK(lock) while (InterlockedCompareExchange((lock), 1, 0)) \ ++ NdisStallExecution(1); ++#define IFUNLOCK(lock) InterlockedExchange((lock), 0) ++#define IFLOCK_FREE(lock) ++#define FW_SUPPORTED(dhd, capa) ((strstr(dhd->fw_capabilities, #capa) != NULL)) ++#ifdef ARP_OFFLOAD_SUPPORT ++#define MAX_IPV4_ENTRIES 8 ++void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode); ++void dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable); + -+ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle)); ++/* dhd_commn arp offload wrapers */ ++void dhd_aoe_hostip_clr(dhd_pub_t *dhd, int idx); ++void dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx); ++int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx); ++void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx); ++#endif /* ARP_OFFLOAD_SUPPORT */ ++#ifdef WLTDLS ++int dhd_tdls_enable(struct net_device *dev, bool tdls_on, bool auto_on, struct ether_addr *mac); ++#ifdef PCIE_FULL_DONGLE ++void dhd_tdls_update_peer_info(struct net_device *dev, bool connect_disconnect, uint8 *addr); ++#endif /* PCIE_FULL_DONGLE */ ++#endif /* WLTDLS */ ++/* Neighbor Discovery Offload Support */ ++int dhd_ndo_enable(dhd_pub_t * dhd, int ndo_enable); ++int dhd_ndo_add_ip(dhd_pub_t *dhd, char* ipaddr, int idx); ++int dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx); ++/* ioctl processing for nl80211 */ ++int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, struct dhd_ioctl *ioc, void *data_buf); + -+ /* First check if there is any data available in the circular buffer */ -+ *available_len = CIRCULARBUF_READ_SPACE_AVAIL(handle); -+ if (*available_len == 0) -+ return NULL; ++void dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path, char *pconf_path); ++void dhd_set_bus_state(void *bus, uint32 state); + -+ /* -+ * Although there might be data in the circular buffer for read, in -+ * cases of write wrap-around and read still in the end of the circular -+ * buffer, we might have to wrap around the read pending pointer also. -+ */ -+ if (CIRCULARBUF_READ_SPACE_AT_END(handle) == 0) -+ handle->rp_ptr = 0; ++/* Remove proper pkts(either one no-frag pkt or whole fragmented pkts) */ ++typedef int (*f_droppkt_t)(dhd_pub_t *dhdp, int prec, void* p, bool bPktInQ); ++extern bool dhd_prec_drop_pkts(dhd_pub_t *dhdp, struct pktq *pq, int prec, f_droppkt_t fn); + -+ ret_addr = CIRCULARBUF_START(handle) + handle->rp_ptr; ++#ifdef PROP_TXSTATUS ++int dhd_os_wlfc_block(dhd_pub_t *pub); ++int dhd_os_wlfc_unblock(dhd_pub_t *pub); ++extern const uint8 prio2fifo[]; ++#endif /* PROP_TXSTATUS */ + -+ /* -+ * Please note that we do not update the read pointer here. Only -+ * read pending pointer is updated, so that next reader knows where -+ * to read data from. -+ * read pointer can only be updated when the read is complete. -+ */ -+ handle->rp_ptr = (uint16)(ret_addr - CIRCULARBUF_START(handle) + *available_len); ++uint8* dhd_os_prealloc(dhd_pub_t *dhdpub, int section, uint size, bool kmalloc_if_fail); ++void dhd_os_prefree(dhd_pub_t *dhdpub, void *addr, uint size); + -+ ASSERT(*available_len <= handle->depth); ++int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost); + -+ OSL_CACHE_INV((void *) ret_addr, *available_len); ++#if defined(CONFIG_DHD_USE_STATIC_BUF) ++#define DHD_OS_PREALLOC(dhdpub, section, size) dhd_os_prealloc(dhdpub, section, size, FALSE) ++#define DHD_OS_PREFREE(dhdpub, addr, size) dhd_os_prefree(dhdpub, addr, size) ++#else ++#define DHD_OS_PREALLOC(dhdpub, section, size) MALLOC(dhdpub->osh, size) ++#define DHD_OS_PREFREE(dhdpub, addr, size) MFREE(dhdpub->osh, addr, size) ++#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */ + -+ return ret_addr; -+} + -+/** -+ * ----------------------------------------------------------------------------- -+ * Function : circularbuf_read_complete -+ * Description: -+ * This function has to be called by the consumer end of circularbuf to indicate -+ * that data has been consumed and the read pointer can be updated, so the producing side -+ * can can use the freed space for new entries. -+ * -+ * -+ * Input Args : -+ * bytes_read : No. of bytes consumed by the consumer. This has to match -+ * the length returned by circularbuf_get_read_ptr -+ * -+ * Return Values : -+ * CIRCULARBUF_SUCCESS : Otherwise -+ * -+ * ----------------------------------------------------------------------------- -+ */ -+circularbuf_ret_t BCMFASTPATH -+circularbuf_read_complete(circularbuf_t *handle, uint16 bytes_read) -+{ -+ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle)); -+ ASSERT(bytes_read < handle->depth); ++#define dhd_add_flowid(pub, ifidx, ac_prio, ea, flowid) do {} while (0) ++#define dhd_del_flowid(pub, ifidx, flowid) do {} while (0) + -+ /* Update the read pointer */ -+ if ((handle->w_ptr < handle->e_ptr) && (handle->r_ptr + bytes_read) > handle->e_ptr) -+ handle->r_ptr = bytes_read; -+ else -+ handle->r_ptr += bytes_read; ++extern unsigned long dhd_os_general_spin_lock(dhd_pub_t *pub); ++extern void dhd_os_general_spin_unlock(dhd_pub_t *pub, unsigned long flags); + -+ return CIRCULARBUF_SUCCESS; -+} ++/** Miscellaenous DHD Spin Locks */ + -+/** -+ * ----------------------------------------------------------------------------- -+ * Function : circularbuf_revert_rp_ptr -+ * -+ * Description: -+ * The rp_ptr update during circularbuf_get_read_ptr() is done to reflect the amount of data -+ * that is sent out to be read by the consumer. But the consumer may not always read the -+ * entire data. In such a case, the rp_ptr needs to be reverted back by 'left' bytes, where -+ * 'left' is the no. of bytes left unread. -+ * -+ * Input args: -+ * bytes : The no. of bytes left unread by the consumer -+ * -+ * ----------------------------------------------------------------------------- -+ */ -+circularbuf_ret_t -+circularbuf_revert_rp_ptr(circularbuf_t *handle, uint16 bytes) -+{ -+ CBUF_DEBUG_CHECK(circularbuf_check_sanity(handle)); -+ ASSERT(bytes < handle->depth); ++/* Disable router 3GMAC bypass path perimeter lock */ ++#define DHD_PERIM_LOCK(dhdp) do {} while (0) ++#define DHD_PERIM_UNLOCK(dhdp) do {} while (0) + -+ handle->rp_ptr -= bytes; ++/* Enable DHD general spin lock/unlock */ ++#define DHD_GENERAL_LOCK(dhdp, flags) \ ++ (flags) = dhd_os_general_spin_lock(dhdp) ++#define DHD_GENERAL_UNLOCK(dhdp, flags) \ ++ dhd_os_general_spin_unlock((dhdp), (flags)) + -+ return CIRCULARBUF_SUCCESS; -+} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_bta.c b/drivers/net/wireless/bcm4336/dhd_bta.c ---- a/drivers/net/wireless/bcm4336/dhd_bta.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_bta.c 2018-05-06 08:49:50.618753851 +0200 ++/* Enable DHD flowring spin lock/unlock */ ++#define DHD_FLOWRING_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) ++#define DHD_FLOWRING_UNLOCK(lock, flags) dhd_os_spin_unlock((lock), (flags)) ++ ++/* Enable DHD common flowring info spin lock/unlock */ ++#define DHD_FLOWID_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) ++#define DHD_FLOWID_UNLOCK(lock, flags) dhd_os_spin_unlock((lock), (flags)) ++ ++ ++ ++typedef struct wl_io_pport { ++ dhd_pub_t *dhd_pub; ++ uint ifidx; ++} wl_io_pport_t; ++ ++extern void *dhd_pub_wlinfo(dhd_pub_t *dhd_pub); ++#ifdef CONFIG_MACH_UNIVERSAL5433 ++extern int check_rev(void); ++#endif ++#endif /* _dhd_h_ */ +diff --git a/drivers/net/wireless/bcm4336/dhd_bta.c b/drivers/net/wireless/bcm4336/dhd_bta.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_bta.c @@ -0,0 +1,321 @@ +/* + * BT-AMP support routines @@ -126054,9 +128595,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_bta.c b/drivers/net/wireless/bcm + break; + } +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_bta.h b/drivers/net/wireless/bcm4336/dhd_bta.h ---- a/drivers/net/wireless/bcm4336/dhd_bta.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_bta.h 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_bta.h b/drivers/net/wireless/bcm4336/dhd_bta.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_bta.h @@ -0,0 +1,21 @@ +/* + * BT-AMP support routines @@ -126079,9 +128622,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_bta.h b/drivers/net/wireless/bcm + + +#endif /* __dhd_bta_h__ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_bus.h b/drivers/net/wireless/bcm4336/dhd_bus.h ---- a/drivers/net/wireless/bcm4336/dhd_bus.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_bus.h 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_bus.h b/drivers/net/wireless/bcm4336/dhd_bus.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_bus.h @@ -0,0 +1,174 @@ +/* + * Header file describing the internal (inter-module) DHD interfaces. @@ -126257,9 +128802,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_bus.h b/drivers/net/wireless/bcm + +#endif /* BCMPCIE */ +#endif /* _dhd_bus_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_cdc.c b/drivers/net/wireless/bcm4336/dhd_cdc.c ---- a/drivers/net/wireless/bcm4336/dhd_cdc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_cdc.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_cdc.c b/drivers/net/wireless/bcm4336/dhd_cdc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_cdc.c @@ -0,0 +1,810 @@ +/* + * DHD Protocol Module for CDC and BDC. @@ -127071,9 +129618,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_cdc.c b/drivers/net/wireless/bcm + } + return 0; +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_cfg80211.c b/drivers/net/wireless/bcm4336/dhd_cfg80211.c ---- a/drivers/net/wireless/bcm4336/dhd_cfg80211.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_cfg80211.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_cfg80211.c b/drivers/net/wireless/bcm4336/dhd_cfg80211.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_cfg80211.c @@ -0,0 +1,201 @@ +/* + * Linux cfg80211 driver - Dongle Host Driver (DHD) related @@ -127276,9 +129825,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_cfg80211.c b/drivers/net/wireles + return err; + +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_cfg80211.h b/drivers/net/wireless/bcm4336/dhd_cfg80211.h ---- a/drivers/net/wireless/bcm4336/dhd_cfg80211.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_cfg80211.h 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_cfg80211.h b/drivers/net/wireless/bcm4336/dhd_cfg80211.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_cfg80211.h @@ -0,0 +1,30 @@ +/* + * Linux cfg80211 driver - Dongle Host Driver (DHD) related @@ -127310,9 +129861,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_cfg80211.h b/drivers/net/wireles +s32 dhd_config_dongle(struct bcm_cfg80211 *cfg); + +#endif /* __DHD_CFG80211__ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_cfg_vendor.c b/drivers/net/wireless/bcm4336/dhd_cfg_vendor.c ---- a/drivers/net/wireless/bcm4336/dhd_cfg_vendor.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_cfg_vendor.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_cfg_vendor.c b/drivers/net/wireless/bcm4336/dhd_cfg_vendor.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_cfg_vendor.c @@ -0,0 +1,153 @@ +/* + * Linux cfg80211 vendor command/event handlers of DHD @@ -127467,9 +130020,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_cfg_vendor.c b/drivers/net/wirel + return 0; +} +#endif /* VENDOR_EXT_SUPPORT */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_common.c b/drivers/net/wireless/bcm4336/dhd_common.c ---- a/drivers/net/wireless/bcm4336/dhd_common.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_common.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_common.c b/drivers/net/wireless/bcm4336/dhd_common.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_common.c @@ -0,0 +1,2881 @@ +/* + * Broadcom Dongle Host Driver (DHD), common DHD core. @@ -130352,9 +132907,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_common.c b/drivers/net/wireless/ + *list_str = str; + return num; +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_config.c b/drivers/net/wireless/bcm4336/dhd_config.c ---- a/drivers/net/wireless/bcm4336/dhd_config.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_config.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_config.c b/drivers/net/wireless/bcm4336/dhd_config.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_config.c @@ -0,0 +1,2154 @@ + +#include @@ -132510,9 +135067,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_config.c b/drivers/net/wireless/ + } + dhd->conf = NULL; +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_config.h b/drivers/net/wireless/bcm4336/dhd_config.h ---- a/drivers/net/wireless/bcm4336/dhd_config.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_config.h 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_config.h b/drivers/net/wireless/bcm4336/dhd_config.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_config.h @@ -0,0 +1,178 @@ + +#ifndef _dhd_config_ @@ -132692,9 +135251,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_config.h b/drivers/net/wireless/ +void *dhd_get_pub(struct net_device *dev); + +#endif /* _dhd_config_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_custom_gpio.c b/drivers/net/wireless/bcm4336/dhd_custom_gpio.c ---- a/drivers/net/wireless/bcm4336/dhd_custom_gpio.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_custom_gpio.c 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_custom_gpio.c b/drivers/net/wireless/bcm4336/dhd_custom_gpio.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_custom_gpio.c @@ -0,0 +1,422 @@ +/* +* Customer code to add GPIO control during WLAN start/stop @@ -133118,9 +135679,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_custom_gpio.c b/drivers/net/wire + return; +#endif /* defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) */ +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_dbg.h b/drivers/net/wireless/bcm4336/dhd_dbg.h ---- a/drivers/net/wireless/bcm4336/dhd_dbg.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_dbg.h 2018-05-06 08:49:50.618753851 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_dbg.h b/drivers/net/wireless/bcm4336/dhd_dbg.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_dbg.h @@ -0,0 +1,107 @@ +/* + * Debug/trace/assert driver definitions for Dongle Host Driver. @@ -133171,2306 +135734,1204 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_dbg.h b/drivers/net/wireless/bcm +#define DHD_EVENT_ON() (dhd_msg_level & DHD_EVENT_VAL) +#define DHD_BTA_ON() (dhd_msg_level & DHD_BTA_VAL) +#define DHD_ISCAN_ON() (dhd_msg_level & DHD_ISCAN_VAL) -+#define DHD_ARPOE_ON() (dhd_msg_level & DHD_ARPOE_VAL) -+#define DHD_REORDER_ON() (dhd_msg_level & DHD_REORDER_VAL) -+#define DHD_NOCHECKDIED_ON() (dhd_msg_level & DHD_NOCHECKDIED_VAL) -+#define DHD_PNO_ON() (dhd_msg_level & DHD_PNO_VAL) -+ -+#else /* defined(BCMDBG) || defined(DHD_DEBUG) */ -+ -+#define DHD_ERROR(args) do {if (USE_NET_RATELIMIT) printf args;} while (0) -+#define DHD_TRACE(args) -+#define DHD_INFO(args) -+#define DHD_DATA(args) -+#define DHD_CTL(args) -+#define DHD_TIMER(args) -+#define DHD_HDRS(args) -+#define DHD_BYTES(args) -+#define DHD_INTR(args) -+#define DHD_GLOM(args) -+#define DHD_EVENT(args) -+#define DHD_BTA(args) -+#define DHD_ISCAN(args) -+#define DHD_ARPOE(args) -+#define DHD_REORDER(args) -+#define DHD_PNO(args) -+ -+#define DHD_TRACE_HW4 DHD_TRACE -+#define DHD_INFO_HW4 DHD_INFO -+ -+#define DHD_ERROR_ON() 0 -+#define DHD_TRACE_ON() 0 -+#define DHD_INFO_ON() 0 -+#define DHD_DATA_ON() 0 -+#define DHD_CTL_ON() 0 -+#define DHD_TIMER_ON() 0 -+#define DHD_HDRS_ON() 0 -+#define DHD_BYTES_ON() 0 -+#define DHD_INTR_ON() 0 -+#define DHD_GLOM_ON() 0 -+#define DHD_EVENT_ON() 0 -+#define DHD_BTA_ON() 0 -+#define DHD_ISCAN_ON() 0 -+#define DHD_ARPOE_ON() 0 -+#define DHD_REORDER_ON() 0 -+#define DHD_NOCHECKDIED_ON() 0 -+#define DHD_PNO_ON() 0 -+ -+#endif -+ -+#define DHD_LOG(args) -+ -+#define DHD_BLOG(cp, size) -+ -+#define DHD_NONE(args) -+extern int dhd_msg_level; -+ -+/* Defines msg bits */ -+#include -+ -+#endif /* _dhd_dbg_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_flowring.c b/drivers/net/wireless/bcm4336/dhd_flowring.c ---- a/drivers/net/wireless/bcm4336/dhd_flowring.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_flowring.c 2018-05-06 08:49:50.618753851 +0200 -@@ -0,0 +1,810 @@ -+/* -+ * Broadcom Dongle Host Driver (DHD), Flow ring specific code at top level -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * $Id: dhd_flowrings.c jaganlv $ -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static INLINE uint16 dhd_flowid_alloc(dhd_pub_t *dhdp, uint8 ifindex, -+ uint8 prio, char *sa, char *da); -+ -+static INLINE int dhd_flowid_lookup(dhd_pub_t *dhdp, uint8 ifindex, -+ uint8 prio, char *sa, char *da, uint16 *flowid); -+int BCMFASTPATH dhd_flow_queue_overflow(flow_queue_t *queue, void *pkt); -+ -+#define FLOW_QUEUE_PKT_NEXT(p) PKTLINK(p) -+#define FLOW_QUEUE_PKT_SETNEXT(p, x) PKTSETLINK((p), (x)) -+ -+const uint8 prio2ac[8] = { 0, 1, 1, 0, 2, 2, 3, 3 }; -+const uint8 prio2tid[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; -+ -+int BCMFASTPATH -+dhd_flow_queue_overflow(flow_queue_t *queue, void *pkt) -+{ -+ return BCME_NORESOURCE; -+} -+ -+/* Flow ring's queue management functions */ -+ -+void /* Initialize a flow ring's queue */ -+dhd_flow_queue_init(dhd_pub_t *dhdp, flow_queue_t *queue, int max) -+{ -+ ASSERT((queue != NULL) && (max > 0)); -+ -+ dll_init(&queue->list); -+ queue->head = queue->tail = NULL; -+ queue->len = 0; -+ queue->max = max - 1; -+ queue->failures = 0U; -+ queue->cb = &dhd_flow_queue_overflow; -+} -+ -+void /* Register an enqueue overflow callback handler */ -+dhd_flow_queue_register(flow_queue_t *queue, flow_queue_cb_t cb) -+{ -+ ASSERT(queue != NULL); -+ queue->cb = cb; -+} -+ -+ -+int BCMFASTPATH /* Enqueue a packet in a flow ring's queue */ -+dhd_flow_queue_enqueue(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt) -+{ -+ int ret = BCME_OK; -+ -+ ASSERT(queue != NULL); -+ -+ if (queue->len >= queue->max) { -+ queue->failures++; -+ ret = (*queue->cb)(queue, pkt); -+ goto done; -+ } -+ -+ if (queue->head) { -+ FLOW_QUEUE_PKT_SETNEXT(queue->tail, pkt); -+ } else { -+ queue->head = pkt; -+ } -+ -+ FLOW_QUEUE_PKT_SETNEXT(pkt, NULL); -+ -+ queue->tail = pkt; /* at tail */ -+ -+ queue->len++; -+ -+done: -+ return ret; -+} -+ -+void * BCMFASTPATH /* Dequeue a packet from a flow ring's queue, from head */ -+dhd_flow_queue_dequeue(dhd_pub_t *dhdp, flow_queue_t *queue) -+{ -+ void * pkt; -+ -+ ASSERT(queue != NULL); -+ -+ pkt = queue->head; /* from head */ -+ -+ if (pkt == NULL) { -+ ASSERT((queue->len == 0) && (queue->tail == NULL)); -+ goto done; -+ } -+ -+ queue->head = FLOW_QUEUE_PKT_NEXT(pkt); -+ if (queue->head == NULL) -+ queue->tail = NULL; -+ -+ queue->len--; -+ -+ FLOW_QUEUE_PKT_SETNEXT(pkt, NULL); /* dettach packet from queue */ -+ -+done: -+ return pkt; -+} -+ -+void BCMFASTPATH /* Reinsert a dequeued packet back at the head */ -+dhd_flow_queue_reinsert(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt) -+{ -+ if (queue->head == NULL) { -+ queue->tail = pkt; -+ } -+ -+ FLOW_QUEUE_PKT_SETNEXT(pkt, queue->head); -+ queue->head = pkt; -+ queue->len++; -+} -+ -+ -+/* Init Flow Ring specific data structures */ -+int -+dhd_flow_rings_init(dhd_pub_t *dhdp, uint32 num_flow_rings) -+{ -+ uint32 idx; -+ uint32 flow_ring_table_sz; -+ uint32 if_flow_lkup_sz; -+ void * flowid_allocator; -+ flow_ring_table_t *flow_ring_table; -+ if_flow_lkup_t *if_flow_lkup = NULL; -+#ifdef PCIE_TX_DEFERRAL -+ uint32 count; -+#endif -+ void *lock = NULL; -+ unsigned long flags; -+ -+ DHD_INFO(("%s\n", __FUNCTION__)); -+ -+ /* Construct a 16bit flow1d allocator */ -+ flowid_allocator = id16_map_init(dhdp->osh, -+ num_flow_rings - FLOW_RING_COMMON, FLOWID_RESERVED); -+ if (flowid_allocator == NULL) { -+ DHD_ERROR(("%s: flowid allocator init failure\n", __FUNCTION__)); -+ return BCME_NOMEM; -+ } -+ -+ /* Allocate a flow ring table, comprising of requested number of rings */ -+ flow_ring_table_sz = (num_flow_rings * sizeof(flow_ring_node_t)); -+ flow_ring_table = (flow_ring_table_t *)MALLOC(dhdp->osh, flow_ring_table_sz); -+ if (flow_ring_table == NULL) { -+ DHD_ERROR(("%s: flow ring table alloc failure\n", __FUNCTION__)); -+ goto fail; -+ } -+ -+ /* Initialize flow ring table state */ -+ bzero((uchar *)flow_ring_table, flow_ring_table_sz); -+ for (idx = 0; idx < num_flow_rings; idx++) { -+ flow_ring_table[idx].status = FLOW_RING_STATUS_CLOSED; -+ flow_ring_table[idx].flowid = (uint16)idx; -+ flow_ring_table[idx].lock = dhd_os_spin_lock_init(dhdp->osh); -+ if (flow_ring_table[idx].lock == NULL) { -+ DHD_ERROR(("%s: Failed to init spinlock for queue!\n", __FUNCTION__)); -+ goto fail; -+ } -+ -+ dll_init(&flow_ring_table[idx].list); -+ -+ /* Initialize the per flow ring backup queue */ -+ dhd_flow_queue_init(dhdp, &flow_ring_table[idx].queue, -+ FLOW_RING_QUEUE_THRESHOLD); -+ } -+ -+ /* Allocate per interface hash table */ -+ if_flow_lkup_sz = sizeof(if_flow_lkup_t) * DHD_MAX_IFS; -+ if_flow_lkup = (if_flow_lkup_t *)DHD_OS_PREALLOC(dhdp, -+ DHD_PREALLOC_IF_FLOW_LKUP, if_flow_lkup_sz); -+ if (if_flow_lkup == NULL) { -+ DHD_ERROR(("%s: if flow lkup alloc failure\n", __FUNCTION__)); -+ goto fail; -+ } -+ -+ /* Initialize per interface hash table */ -+ bzero((uchar *)if_flow_lkup, if_flow_lkup_sz); -+ for (idx = 0; idx < DHD_MAX_IFS; idx++) { -+ int hash_ix; -+ if_flow_lkup[idx].status = 0; -+ if_flow_lkup[idx].role = 0; -+ for (hash_ix = 0; hash_ix < DHD_FLOWRING_HASH_SIZE; hash_ix++) -+ if_flow_lkup[idx].fl_hash[hash_ix] = NULL; -+ } -+ -+#ifdef PCIE_TX_DEFERRAL -+ count = BITS_TO_LONGS(num_flow_rings); -+ dhdp->bus->delete_flow_map = kzalloc(count, GFP_ATOMIC); -+ if (!dhdp->bus->delete_flow_map) { -+ DHD_ERROR(("%s: delete_flow_map alloc failure\n", __FUNCTION__)); -+ goto fail; -+ } -+#endif -+ -+ lock = dhd_os_spin_lock_init(dhdp->osh); -+ if (lock == NULL) -+ goto fail; -+ -+ dhdp->flow_prio_map_type = DHD_FLOW_PRIO_AC_MAP; -+ bcopy(prio2ac, dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO); -+ -+ /* Now populate into dhd pub */ -+ DHD_FLOWID_LOCK(lock, flags); -+ dhdp->num_flow_rings = num_flow_rings; -+ dhdp->flowid_allocator = (void *)flowid_allocator; -+ dhdp->flow_ring_table = (void *)flow_ring_table; -+ dhdp->if_flow_lkup = (void *)if_flow_lkup; -+ dhdp->flowid_lock = lock; -+ DHD_FLOWID_UNLOCK(lock, flags); -+ -+ DHD_INFO(("%s done\n", __FUNCTION__)); -+ return BCME_OK; -+ -+fail: -+ -+#ifdef PCIE_TX_DEFERRAL -+ if (dhdp->bus->delete_flow_map) -+ kfree(dhdp->bus->delete_flow_map); -+#endif -+ /* Destruct the per interface flow lkup table */ -+ if (dhdp->if_flow_lkup != NULL) { -+ DHD_OS_PREFREE(dhdp, if_flow_lkup, if_flow_lkup_sz); -+ } -+ if (flow_ring_table != NULL) { -+ for (idx = 0; idx < num_flow_rings; idx++) { -+ if (flow_ring_table[idx].lock != NULL) -+ dhd_os_spin_lock_deinit(dhdp->osh, flow_ring_table[idx].lock); -+ } -+ MFREE(dhdp->osh, flow_ring_table, flow_ring_table_sz); -+ } -+ id16_map_fini(dhdp->osh, flowid_allocator); -+ -+ return BCME_NOMEM; -+} -+ -+/* Deinit Flow Ring specific data structures */ -+void dhd_flow_rings_deinit(dhd_pub_t *dhdp) -+{ -+ uint16 idx; -+ uint32 flow_ring_table_sz; -+ uint32 if_flow_lkup_sz; -+ flow_ring_table_t *flow_ring_table; -+ unsigned long flags; -+ void *lock; -+ -+ DHD_INFO(("dhd_flow_rings_deinit\n")); -+ -+ if (dhdp->flow_ring_table != NULL) { -+ -+ ASSERT(dhdp->num_flow_rings > 0); -+ -+ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); -+ flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table; -+ dhdp->flow_ring_table = NULL; -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ for (idx = 0; idx < dhdp->num_flow_rings; idx++) { -+ if (flow_ring_table[idx].active) { -+ dhd_bus_clean_flow_ring(dhdp->bus, &flow_ring_table[idx]); -+ } -+ ASSERT(flow_queue_empty(&flow_ring_table[idx].queue)); -+ -+ /* Deinit flow ring queue locks before destroying flow ring table */ -+ dhd_os_spin_lock_deinit(dhdp->osh, flow_ring_table[idx].lock); -+ flow_ring_table[idx].lock = NULL; -+ } -+ -+ /* Destruct the flow ring table */ -+ flow_ring_table_sz = dhdp->num_flow_rings * sizeof(flow_ring_table_t); -+ MFREE(dhdp->osh, flow_ring_table, flow_ring_table_sz); -+ } -+ -+ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); -+ -+ /* Destruct the per interface flow lkup table */ -+ if (dhdp->if_flow_lkup != NULL) { -+ if_flow_lkup_sz = sizeof(if_flow_lkup_t) * DHD_MAX_IFS; -+ bzero(dhdp->if_flow_lkup, sizeof(if_flow_lkup_sz)); -+ DHD_OS_PREFREE(dhdp, dhdp->if_flow_lkup, if_flow_lkup_sz); -+ dhdp->if_flow_lkup = NULL; -+ } -+ -+#ifdef PCIE_TX_DEFERRAL -+ if (dhdp->bus->delete_flow_map) -+ kfree(dhdp->bus->delete_flow_map); -+#endif -+ -+ /* Destruct the flowid allocator */ -+ if (dhdp->flowid_allocator != NULL) -+ dhdp->flowid_allocator = id16_map_fini(dhdp->osh, dhdp->flowid_allocator); -+ -+ dhdp->num_flow_rings = 0U; -+ lock = dhdp->flowid_lock; -+ dhdp->flowid_lock = NULL; -+ -+ DHD_FLOWID_UNLOCK(lock, flags); -+ dhd_os_spin_lock_deinit(dhdp->osh, lock); -+} -+ -+uint8 -+dhd_flow_rings_ifindex2role(dhd_pub_t *dhdp, uint8 ifindex) -+{ -+ if_flow_lkup_t *if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; -+ ASSERT(if_flow_lkup); -+ return if_flow_lkup[ifindex].role; -+} -+ -+#ifdef WLTDLS -+bool is_tdls_destination(dhd_pub_t *dhdp, uint8 *da) -+{ -+ tdls_peer_node_t *cur = dhdp->peer_tbl.node; -+ while (cur != NULL) { -+ if (!memcmp(da, cur->addr, ETHER_ADDR_LEN)) { -+ return TRUE; -+ } -+ cur = cur->next; -+ } -+ return FALSE; -+} -+#endif /* WLTDLS */ -+ -+/* For a given interface, search the hash table for a matching flow */ -+uint16 -+dhd_flowid_find(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, char *sa, char *da) -+{ -+ int hash; -+ bool ismcast = FALSE; -+ flow_hash_info_t *cur; -+ if_flow_lkup_t *if_flow_lkup; -+ unsigned long flags; -+ -+ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); -+ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; -+ -+ if (DHD_IF_ROLE_STA(if_flow_lkup[ifindex].role)) { -+#ifdef WLTDLS -+ if (dhdp->peer_tbl.tdls_peer_count && !(ETHER_ISMULTI(da)) && -+ is_tdls_destination(dhdp, da)) { -+ hash = DHD_FLOWRING_HASHINDEX(da, prio); -+ cur = if_flow_lkup[ifindex].fl_hash[hash]; -+ while (cur != NULL) { -+ if (!memcmp(cur->flow_info.da, da, ETHER_ADDR_LEN)) { -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ return cur->flowid; -+ } -+ cur = cur->next; -+ } -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ return FLOWID_INVALID; -+ } -+#endif /* WLTDLS */ -+ cur = if_flow_lkup[ifindex].fl_hash[prio]; -+ if (cur) { -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ return cur->flowid; -+ } -+ -+ } else { -+ -+ if (ETHER_ISMULTI(da)) { -+ ismcast = TRUE; -+ hash = 0; -+ } else { -+ hash = DHD_FLOWRING_HASHINDEX(da, prio); -+ } -+ -+ cur = if_flow_lkup[ifindex].fl_hash[hash]; -+ -+ while (cur) { -+ if ((ismcast && ETHER_ISMULTI(cur->flow_info.da)) || -+ (!memcmp(cur->flow_info.da, da, ETHER_ADDR_LEN) && -+ (cur->flow_info.tid == prio))) { -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ return cur->flowid; -+ } -+ cur = cur->next; -+ } -+ } -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ -+ return FLOWID_INVALID; -+} -+ -+/* Allocate Flow ID */ -+static INLINE uint16 -+dhd_flowid_alloc(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, char *sa, char *da) -+{ -+ flow_hash_info_t *fl_hash_node, *cur; -+ if_flow_lkup_t *if_flow_lkup; -+ int hash; -+ uint16 flowid; -+ unsigned long flags; -+ -+ fl_hash_node = (flow_hash_info_t *) MALLOC(dhdp->osh, sizeof(flow_hash_info_t)); -+ memcpy(fl_hash_node->flow_info.da, da, sizeof(fl_hash_node->flow_info.da)); -+ -+ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); -+ ASSERT(dhdp->flowid_allocator != NULL); -+ flowid = id16_map_alloc(dhdp->flowid_allocator); -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ -+ if (flowid == FLOWID_INVALID) { -+ MFREE(dhdp->osh, fl_hash_node, sizeof(flow_hash_info_t)); -+ DHD_ERROR(("%s: cannot get free flowid \n", __FUNCTION__)); -+ return FLOWID_INVALID; -+ } -+ -+ fl_hash_node->flowid = flowid; -+ fl_hash_node->flow_info.tid = prio; -+ fl_hash_node->flow_info.ifindex = ifindex; -+ fl_hash_node->next = NULL; -+ -+ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); -+ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; -+ if (DHD_IF_ROLE_STA(if_flow_lkup[ifindex].role)) { -+ /* For STA non TDLS dest we allocate entry based on prio only */ -+#ifdef WLTDLS -+ if (dhdp->peer_tbl.tdls_peer_count && -+ (is_tdls_destination(dhdp, da))) { -+ hash = DHD_FLOWRING_HASHINDEX(da, prio); -+ cur = if_flow_lkup[ifindex].fl_hash[hash]; -+ if (cur) { -+ while (cur->next) { -+ cur = cur->next; -+ } -+ cur->next = fl_hash_node; -+ } else { -+ if_flow_lkup[ifindex].fl_hash[hash] = fl_hash_node; -+ } -+ } else -+#endif /* WLTDLS */ -+ if_flow_lkup[ifindex].fl_hash[prio] = fl_hash_node; -+ } else { -+ -+ /* For bcast/mcast assign first slot in in interface */ -+ hash = ETHER_ISMULTI(da) ? 0 : DHD_FLOWRING_HASHINDEX(da, prio); -+ cur = if_flow_lkup[ifindex].fl_hash[hash]; -+ if (cur) { -+ while (cur->next) { -+ cur = cur->next; -+ } -+ cur->next = fl_hash_node; -+ } else -+ if_flow_lkup[ifindex].fl_hash[hash] = fl_hash_node; -+ } -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ -+ DHD_INFO(("%s: allocated flowid %d\n", __FUNCTION__, fl_hash_node->flowid)); -+ -+ return fl_hash_node->flowid; -+} -+ -+/* Get flow ring ID, if not present try to create one */ -+static INLINE int -+dhd_flowid_lookup(dhd_pub_t *dhdp, uint8 ifindex, -+ uint8 prio, char *sa, char *da, uint16 *flowid) -+{ -+ uint16 id; -+ flow_ring_node_t *flow_ring_node; -+ flow_ring_table_t *flow_ring_table; -+ unsigned long flags; -+ -+ DHD_INFO(("%s\n", __FUNCTION__)); -+ -+ if (!dhdp->flow_ring_table) -+ return BCME_ERROR; -+ -+ flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table; -+ -+ id = dhd_flowid_find(dhdp, ifindex, prio, sa, da); -+ -+ if (id == FLOWID_INVALID) { -+ -+ if_flow_lkup_t *if_flow_lkup; -+ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; -+ -+ if (!if_flow_lkup[ifindex].status) -+ return BCME_ERROR; -+ -+ id = dhd_flowid_alloc(dhdp, ifindex, prio, sa, da); -+ if (id == FLOWID_INVALID) { -+ DHD_ERROR(("%s: alloc flowid ifindex %u status %u\n", -+ __FUNCTION__, ifindex, if_flow_lkup[ifindex].status)); -+ return BCME_ERROR; -+ } -+ -+ /* register this flowid in dhd_pub */ -+ dhd_add_flowid(dhdp, ifindex, prio, da, id); -+ } -+ -+ ASSERT(id < dhdp->num_flow_rings); -+ -+ flow_ring_node = (flow_ring_node_t *) &flow_ring_table[id]; -+ DHD_FLOWRING_LOCK(flow_ring_node->lock, flags); -+ if (flow_ring_node->active) { -+ DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags); -+ *flowid = id; -+ return BCME_OK; -+ } -+ /* Init Flow info */ -+ memcpy(flow_ring_node->flow_info.sa, sa, sizeof(flow_ring_node->flow_info.sa)); -+ memcpy(flow_ring_node->flow_info.da, da, sizeof(flow_ring_node->flow_info.da)); -+ flow_ring_node->flow_info.tid = prio; -+ flow_ring_node->flow_info.ifindex = ifindex; -+ flow_ring_node->active = TRUE; -+ flow_ring_node->status = FLOW_RING_STATUS_PENDING; -+ DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags); -+ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); -+ dll_prepend(&dhdp->bus->const_flowring, &flow_ring_node->list); -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ -+ /* Create and inform device about the new flow */ -+ if (dhd_bus_flow_ring_create_request(dhdp->bus, (void *)flow_ring_node) -+ != BCME_OK) { -+ DHD_ERROR(("%s: create error %d\n", __FUNCTION__, id)); -+ return BCME_ERROR; -+ } -+ -+ *flowid = id; -+ return BCME_OK; -+} -+ -+/* Update flowid information on the packet */ -+int BCMFASTPATH -+dhd_flowid_update(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, void *pktbuf) -+{ -+ uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, pktbuf); -+ struct ether_header *eh = (struct ether_header *)pktdata; -+ uint16 flowid; -+ -+ if (dhd_bus_is_txmode_push(dhdp->bus)) -+ return BCME_OK; -+ -+ ASSERT(ifindex < DHD_MAX_IFS); -+ if (ifindex >= DHD_MAX_IFS) { -+ return BCME_BADARG; -+ } -+ -+ if (!dhdp->flowid_allocator) { -+ DHD_ERROR(("%s: Flow ring not intited yet \n", __FUNCTION__)); -+ return BCME_ERROR; -+ } -+ if (dhd_flowid_lookup(dhdp, ifindex, prio, eh->ether_shost, eh->ether_dhost, -+ &flowid) != BCME_OK) { -+ return BCME_ERROR; -+ } -+ -+ DHD_INFO(("%s: prio %d flowid %d\n", __FUNCTION__, prio, flowid)); -+ -+ /* Tag the packet with flowid */ -+ DHD_PKTTAG_SET_FLOWID((dhd_pkttag_fr_t *)PKTTAG(pktbuf), flowid); -+ return BCME_OK; -+} -+ -+void -+dhd_flowid_free(dhd_pub_t *dhdp, uint8 ifindex, uint16 flowid) -+{ -+ int hashix; -+ bool found = FALSE; -+ flow_hash_info_t *cur, *prev; -+ if_flow_lkup_t *if_flow_lkup; -+ unsigned long flags; -+ -+ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); -+ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; -+ -+ for (hashix = 0; hashix < DHD_FLOWRING_HASH_SIZE; hashix++) { -+ -+ cur = if_flow_lkup[ifindex].fl_hash[hashix]; -+ -+ if (cur) { -+ if (cur->flowid == flowid) { -+ found = TRUE; -+ } -+ -+ prev = NULL; -+ while (!found && cur) { -+ if (cur->flowid == flowid) { -+ found = TRUE; -+ break; -+ } -+ prev = cur; -+ cur = cur->next; -+ } -+ if (found) { -+ if (!prev) { -+ if_flow_lkup[ifindex].fl_hash[hashix] = cur->next; -+ } else { -+ prev->next = cur->next; -+ } -+ -+ /* deregister flowid from dhd_pub. */ -+ dhd_del_flowid(dhdp, ifindex, flowid); -+ -+ id16_map_free(dhdp->flowid_allocator, flowid); -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ MFREE(dhdp->osh, cur, sizeof(flow_hash_info_t)); -+ -+ return; -+ } -+ } -+ } -+ -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ DHD_ERROR(("%s: could not free flow ring hash entry flowid %d\n", -+ __FUNCTION__, flowid)); -+} -+ -+ -+/* Delete all Flow rings assocaited with the given Interface */ -+void -+dhd_flow_rings_delete(dhd_pub_t *dhdp, uint8 ifindex) -+{ -+ uint32 id; -+ flow_ring_table_t *flow_ring_table; -+ -+ DHD_INFO(("%s: ifindex %u\n", __FUNCTION__, ifindex)); -+ -+ ASSERT(ifindex < DHD_MAX_IFS); -+ if (ifindex >= DHD_MAX_IFS) -+ return; -+ -+ if (!dhdp->flow_ring_table) -+ return; -+ -+ flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table; -+ for (id = 0; id < dhdp->num_flow_rings; id++) { -+ if (flow_ring_table[id].active && -+ (flow_ring_table[id].flow_info.ifindex == ifindex) && -+ (flow_ring_table[id].status != FLOW_RING_STATUS_DELETE_PENDING)) { -+ DHD_INFO(("%s: deleting flowid %d\n", -+ __FUNCTION__, flow_ring_table[id].flowid)); -+ dhd_bus_flow_ring_delete_request(dhdp->bus, -+ (void *) &flow_ring_table[id]); -+ } -+ } -+} -+ -+/* Delete flow/s for given peer address */ -+void -+dhd_flow_rings_delete_for_peer(dhd_pub_t *dhdp, uint8 ifindex, char *addr) -+{ -+ uint32 id; -+ flow_ring_table_t *flow_ring_table; -+ -+ DHD_ERROR(("%s: ifindex %u\n", __FUNCTION__, ifindex)); -+ -+ ASSERT(ifindex < DHD_MAX_IFS); -+ if (ifindex >= DHD_MAX_IFS) -+ return; -+ -+ if (!dhdp->flow_ring_table) -+ return; -+ -+ flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table; -+ for (id = 0; id < dhdp->num_flow_rings; id++) { -+ if (flow_ring_table[id].active && -+ (flow_ring_table[id].flow_info.ifindex == ifindex) && -+ (!memcmp(flow_ring_table[id].flow_info.da, addr, ETHER_ADDR_LEN)) && -+ (flow_ring_table[id].status != FLOW_RING_STATUS_DELETE_PENDING)) { -+ DHD_INFO(("%s: deleting flowid %d\n", -+ __FUNCTION__, flow_ring_table[id].flowid)); -+ dhd_bus_flow_ring_delete_request(dhdp->bus, -+ (void *) &flow_ring_table[id]); -+ } -+ } -+} -+ -+/* Handle Interface ADD, DEL operations */ -+void -+dhd_update_interface_flow_info(dhd_pub_t *dhdp, uint8 ifindex, -+ uint8 op, uint8 role) -+{ -+ if_flow_lkup_t *if_flow_lkup; -+ unsigned long flags; -+ -+ ASSERT(ifindex < DHD_MAX_IFS); -+ if (ifindex >= DHD_MAX_IFS) -+ return; -+ -+ DHD_INFO(("%s: ifindex %u op %u role is %u \n", -+ __FUNCTION__, ifindex, op, role)); -+ if (!dhdp->flowid_allocator) { -+ DHD_ERROR(("%s: Flow ring not intited yet \n", __FUNCTION__)); -+ return; -+ } -+ -+ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); -+ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; -+ -+ if (op == WLC_E_IF_ADD || op == WLC_E_IF_CHANGE) { -+ -+ if_flow_lkup[ifindex].role = role; -+ -+ if (!(DHD_IF_ROLE_STA(role))) { -+ if_flow_lkup[ifindex].status = TRUE; -+ DHD_INFO(("%s: Mcast Flow ring for ifindex %d role is %d \n", -+ __FUNCTION__, ifindex, role)); -+ /* Create Mcast Flow */ -+ } -+ } else if (op == WLC_E_IF_DEL) { -+ if_flow_lkup[ifindex].status = FALSE; -+ DHD_INFO(("%s: cleanup all Flow rings for ifindex %d role is %d \n", -+ __FUNCTION__, ifindex, role)); -+ } -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+} -+ -+/* Handle a STA interface link status update */ -+int -+dhd_update_interface_link_status(dhd_pub_t *dhdp, uint8 ifindex, uint8 status) -+{ -+ if_flow_lkup_t *if_flow_lkup; -+ unsigned long flags; -+ -+ ASSERT(ifindex < DHD_MAX_IFS); -+ if (ifindex >= DHD_MAX_IFS) -+ return BCME_BADARG; -+ -+ DHD_INFO(("%s: ifindex %d status %d\n", __FUNCTION__, ifindex, status)); -+ -+ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); -+ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; -+ -+ if (DHD_IF_ROLE_STA(if_flow_lkup[ifindex].role)) { -+ if (status) -+ if_flow_lkup[ifindex].status = TRUE; -+ else -+ if_flow_lkup[ifindex].status = FALSE; -+ } -+ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); -+ -+ return BCME_OK; -+} -+/* Update flow priority mapping */ -+int dhd_update_flow_prio_map(dhd_pub_t *dhdp, uint8 map) -+{ -+ uint16 flowid; -+ flow_ring_node_t *flow_ring_node; -+ -+ if (map > DHD_FLOW_PRIO_TID_MAP) -+ return BCME_BADOPTION; -+ -+ /* Check if we need to change prio map */ -+ if (map == dhdp->flow_prio_map_type) -+ return BCME_OK; -+ -+ /* If any ring is active we cannot change priority mapping for flow rings */ -+ for (flowid = 0; flowid < dhdp->num_flow_rings; flowid++) { -+ flow_ring_node = DHD_FLOW_RING(dhdp, flowid); -+ if (flow_ring_node->active) -+ return BCME_EPERM; -+ } -+ /* Infor firmware about new mapping type */ -+ if (BCME_OK != dhd_flow_prio_map(dhdp, &map, TRUE)) -+ return BCME_ERROR; -+ -+ /* update internal structures */ -+ dhdp->flow_prio_map_type = map; -+ if (dhdp->flow_prio_map_type == DHD_FLOW_PRIO_TID_MAP) -+ bcopy(prio2tid, dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO); -+ else -+ bcopy(prio2ac, dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO); -+ -+ return BCME_OK; -+} -+ -+/* Set/Get flwo ring priority map */ -+int dhd_flow_prio_map(dhd_pub_t *dhd, uint8 *map, bool set) -+{ -+ uint8 iovbuf[24]; -+ if (!set) { -+ bcm_mkiovar("bus:fl_prio_map", NULL, 0, (char*)iovbuf, sizeof(iovbuf)); -+ if (dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0) < 0) { -+ DHD_ERROR(("%s: failed to get fl_prio_map\n", __FUNCTION__)); -+ return BCME_ERROR; -+ } -+ *map = iovbuf[0]; -+ return BCME_OK; -+ } -+ bcm_mkiovar("bus:fl_prio_map", (char *)map, 4, (char*)iovbuf, sizeof(iovbuf)); -+ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) { -+ DHD_ERROR(("%s: failed to set fl_prio_map \n", -+ __FUNCTION__)); -+ return BCME_ERROR; -+ } -+ return BCME_OK; -+} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_flowring.h b/drivers/net/wireless/bcm4336/dhd_flowring.h ---- a/drivers/net/wireless/bcm4336/dhd_flowring.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_flowring.h 2018-05-06 08:49:50.618753851 +0200 -@@ -0,0 +1,159 @@ -+/* -+ * Header file describing the flow rings DHD interfaces. -+ * -+ * Provides type definitions and function prototypes used to create, delete and manage -+ * -+ * flow rings at high level -+ * -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * $Id: dhd_flowrings.h jaganlv $ -+ */ -+ -+/**************** -+ * Common types * -+ */ -+ -+#ifndef _dhd_flowrings_h_ -+#define _dhd_flowrings_h_ -+ -+/* Max pkts held in a flow ring's backup queue */ -+#define FLOW_RING_QUEUE_THRESHOLD (2048) -+ -+/* Number of H2D common rings : PCIE Spec Rev? */ -+#define FLOW_RING_COMMON 2 -+ -+#define FLOWID_INVALID (ID16_INVALID) -+#define FLOWID_RESERVED (FLOW_RING_COMMON) -+ -+#define FLOW_RING_STATUS_OPEN 0 -+#define FLOW_RING_STATUS_PENDING 1 -+#define FLOW_RING_STATUS_CLOSED 2 -+#define FLOW_RING_STATUS_DELETE_PENDING 3 -+#define FLOW_RING_STATUS_FLUSH_PENDING 4 -+ -+#define DHD_FLOWRING_RX_BUFPOST_PKTSZ 2048 -+ -+#define DHD_FLOW_PRIO_AC_MAP 0 -+#define DHD_FLOW_PRIO_TID_MAP 1 -+ -+ -+/* Pkttag not compatible with PROP_TXSTATUS or WLFC */ -+typedef struct dhd_pkttag_fr { -+ uint16 flowid; -+ int dataoff; -+} dhd_pkttag_fr_t; -+ -+#define DHD_PKTTAG_SET_FLOWID(tag, flow) ((tag)->flowid = (uint16)(flow)) -+#define DHD_PKTTAG_SET_DATAOFF(tag, offset) ((tag)->dataoff = (int)(offset)) -+ -+#define DHD_PKTTAG_FLOWID(tag) ((tag)->flowid) -+#define DHD_PKTTAG_DATAOFF(tag) ((tag)->dataoff) -+ -+/* Hashing a MacAddress for lkup into a per interface flow hash table */ -+#define DHD_FLOWRING_HASH_SIZE 256 -+#define DHD_FLOWRING_HASHINDEX(ea, prio) \ -+ ((((uint8 *)(ea))[3] ^ ((uint8 *)(ea))[4] ^ ((uint8 *)(ea))[5] ^ ((uint8)(prio))) \ -+ % DHD_FLOWRING_HASH_SIZE) -+ -+#define DHD_IF_ROLE(pub, idx) (((if_flow_lkup_t *)(pub)->if_flow_lkup)[idx].role) -+#define DHD_IF_ROLE_AP(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_AP) -+#define DHD_IF_ROLE_P2PGO(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_P2P_GO) -+#define DHD_FLOW_RING(dhdp, flowid) \ -+ (flow_ring_node_t *)&(((flow_ring_node_t *)((dhdp)->flow_ring_table))[flowid]) -+ -+struct flow_queue; -+ -+/* Flow Ring Queue Enqueue overflow callback */ -+typedef int (*flow_queue_cb_t)(struct flow_queue * queue, void * pkt); -+ -+typedef struct flow_queue { -+ dll_t list; /* manage a flowring queue in a dll */ -+ void * head; /* first packet in the queue */ -+ void * tail; /* last packet in the queue */ -+ uint16 len; /* number of packets in the queue */ -+ uint16 max; /* maximum number of packets, queue may hold */ -+ uint32 failures; /* enqueue failures due to queue overflow */ -+ flow_queue_cb_t cb; /* callback invoked on threshold crossing */ -+} flow_queue_t; -+ -+#define flow_queue_len(queue) ((int)(queue)->len) -+#define flow_queue_max(queue) ((int)(queue)->max) -+#define flow_queue_avail(queue) ((int)((queue)->max - (queue)->len)) -+#define flow_queue_full(queue) ((queue)->len >= (queue)->max) -+#define flow_queue_empty(queue) ((queue)->len == 0) -+ -+typedef struct flow_info { -+ uint8 tid; -+ uint8 ifindex; -+ char sa[ETHER_ADDR_LEN]; -+ char da[ETHER_ADDR_LEN]; -+} flow_info_t; -+ -+typedef struct flow_ring_node { -+ dll_t list; /* manage a constructed flowring in a dll, must be at first place */ -+ flow_queue_t queue; -+ bool active; -+ uint8 status; -+ uint16 flowid; -+ flow_info_t flow_info; -+ void *prot_info; -+ void *lock; /* lock for flowring access protection */ -+} flow_ring_node_t; -+typedef flow_ring_node_t flow_ring_table_t; -+ -+typedef struct flow_hash_info { -+ uint16 flowid; -+ flow_info_t flow_info; -+ struct flow_hash_info *next; -+} flow_hash_info_t; -+ -+typedef struct if_flow_lkup { -+ bool status; -+ uint8 role; /* Interface role: STA/AP */ -+ flow_hash_info_t *fl_hash[DHD_FLOWRING_HASH_SIZE]; /* Lkup Hash table */ -+} if_flow_lkup_t; -+ -+static INLINE flow_ring_node_t * -+dhd_constlist_to_flowring(dll_t *item) -+{ -+ return ((flow_ring_node_t *)item); -+} ++#define DHD_ARPOE_ON() (dhd_msg_level & DHD_ARPOE_VAL) ++#define DHD_REORDER_ON() (dhd_msg_level & DHD_REORDER_VAL) ++#define DHD_NOCHECKDIED_ON() (dhd_msg_level & DHD_NOCHECKDIED_VAL) ++#define DHD_PNO_ON() (dhd_msg_level & DHD_PNO_VAL) + -+/* Exported API */ ++#else /* defined(BCMDBG) || defined(DHD_DEBUG) */ + -+/* Flow ring's queue management functions */ -+extern void dhd_flow_queue_init(dhd_pub_t *dhdp, flow_queue_t *queue, int max); -+extern void dhd_flow_queue_register(flow_queue_t *queue, flow_queue_cb_t cb); -+extern int dhd_flow_queue_enqueue(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt); -+extern void * dhd_flow_queue_dequeue(dhd_pub_t *dhdp, flow_queue_t *queue); -+extern void dhd_flow_queue_reinsert(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt); ++#define DHD_ERROR(args) do {if (USE_NET_RATELIMIT) printf args;} while (0) ++#define DHD_TRACE(args) ++#define DHD_INFO(args) ++#define DHD_DATA(args) ++#define DHD_CTL(args) ++#define DHD_TIMER(args) ++#define DHD_HDRS(args) ++#define DHD_BYTES(args) ++#define DHD_INTR(args) ++#define DHD_GLOM(args) ++#define DHD_EVENT(args) ++#define DHD_BTA(args) ++#define DHD_ISCAN(args) ++#define DHD_ARPOE(args) ++#define DHD_REORDER(args) ++#define DHD_PNO(args) + -+extern int dhd_flow_rings_init(dhd_pub_t *dhdp, uint32 num_flow_rings); ++#define DHD_TRACE_HW4 DHD_TRACE ++#define DHD_INFO_HW4 DHD_INFO + -+extern void dhd_flow_rings_deinit(dhd_pub_t *dhdp); ++#define DHD_ERROR_ON() 0 ++#define DHD_TRACE_ON() 0 ++#define DHD_INFO_ON() 0 ++#define DHD_DATA_ON() 0 ++#define DHD_CTL_ON() 0 ++#define DHD_TIMER_ON() 0 ++#define DHD_HDRS_ON() 0 ++#define DHD_BYTES_ON() 0 ++#define DHD_INTR_ON() 0 ++#define DHD_GLOM_ON() 0 ++#define DHD_EVENT_ON() 0 ++#define DHD_BTA_ON() 0 ++#define DHD_ISCAN_ON() 0 ++#define DHD_ARPOE_ON() 0 ++#define DHD_REORDER_ON() 0 ++#define DHD_NOCHECKDIED_ON() 0 ++#define DHD_PNO_ON() 0 + -+extern uint16 dhd_flowid_find(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, char *sa, char *da); ++#endif + -+extern int dhd_flowid_update(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, -+ void *pktbuf); ++#define DHD_LOG(args) + -+extern void dhd_flowid_free(dhd_pub_t *dhdp, uint8 ifindex, uint16 flowid); ++#define DHD_BLOG(cp, size) + -+extern void dhd_flow_rings_delete(dhd_pub_t *dhdp, uint8 ifindex); ++#define DHD_NONE(args) ++extern int dhd_msg_level; + -+extern void dhd_flow_rings_delete_for_peer(dhd_pub_t *dhdp, uint8 ifindex, -+ char *addr); ++/* Defines msg bits */ ++#include + -+/* Handle Interface ADD, DEL operations */ -+extern void dhd_update_interface_flow_info(dhd_pub_t *dhdp, uint8 ifindex, -+ uint8 op, uint8 role); ++#endif /* _dhd_dbg_ */ +diff --git a/drivers/net/wireless/bcm4336/dhd_flowring.c b/drivers/net/wireless/bcm4336/dhd_flowring.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_flowring.c +@@ -0,0 +1,810 @@ ++/* ++ * Broadcom Dongle Host Driver (DHD), Flow ring specific code at top level ++ * $Copyright Open Broadcom Corporation$ ++ * ++ * $Id: dhd_flowrings.c jaganlv $ ++ */ + -+/* Handle a STA interface link status update */ -+extern int dhd_update_interface_link_status(dhd_pub_t *dhdp, uint8 ifindex, -+ uint8 status); -+extern int dhd_flow_prio_map(dhd_pub_t *dhd, uint8 *map, bool set); -+extern int dhd_update_flow_prio_map(dhd_pub_t *dhdp, uint8 map); ++#include ++#include ++#include ++#include + -+extern uint8 dhd_flow_rings_ifindex2role(dhd_pub_t *dhdp, uint8 ifindex); -+#endif /* _dhd_flowrings_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_gpio.c b/drivers/net/wireless/bcm4336/dhd_gpio.c ---- a/drivers/net/wireless/bcm4336/dhd_gpio.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_gpio.c 2018-05-06 08:49:50.622754012 +0200 -@@ -0,0 +1,148 @@ -+#ifdef CUSTOMER_HW -+#include ++#include ++#include +#include ++ +#include + -+#include "ap621x.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+struct wifi_platform_data dhd_wlan_control = {0}; ++static INLINE uint16 dhd_flowid_alloc(dhd_pub_t *dhdp, uint8 ifindex, ++ uint8 prio, char *sa, char *da); + -+/* nanopi: irq and flags are read from OF dtb, see read_brcm_nanopi_irq() */ -+#if defined(CUSTOMER_OOB) && !defined(CONFIG_ARCH_S5P6818) -+uint bcm_wlan_get_oob_irq(void) -+{ -+ uint host_oob_irq = 0; ++static INLINE int dhd_flowid_lookup(dhd_pub_t *dhdp, uint8 ifindex, ++ uint8 prio, char *sa, char *da, uint16 *flowid); ++int BCMFASTPATH dhd_flow_queue_overflow(flow_queue_t *queue, void *pkt); + -+#ifdef GPIO_WLAN_HOST_WAKE -+ printf("GPIO(GPIO_WLAN_HOST_WAKE) = %d\n", brcm_gpio_host_wake()); -+ host_oob_irq = gpio_to_irq(brcm_gpio_host_wake()); -+ gpio_direction_input(brcm_gpio_host_wake()); -+#elif defined(CONFIG_ARCH_CPU_SLSI) -+ host_oob_irq = get_host_wake_irq(); -+#endif ++#define FLOW_QUEUE_PKT_NEXT(p) PKTLINK(p) ++#define FLOW_QUEUE_PKT_SETNEXT(p, x) PKTSETLINK((p), (x)) + -+ printf("host_oob_irq: %d\n", host_oob_irq); -+ return host_oob_irq; ++const uint8 prio2ac[8] = { 0, 1, 1, 0, 2, 2, 3, 3 }; ++const uint8 prio2tid[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ++ ++int BCMFASTPATH ++dhd_flow_queue_overflow(flow_queue_t *queue, void *pkt) ++{ ++ return BCME_NORESOURCE; +} + -+uint bcm_wlan_get_oob_irq_flags(void) ++/* Flow ring's queue management functions */ ++ ++void /* Initialize a flow ring's queue */ ++dhd_flow_queue_init(dhd_pub_t *dhdp, flow_queue_t *queue, int max) +{ -+ uint host_oob_irq_flags = 0; ++ ASSERT((queue != NULL) && (max > 0)); + -+#if defined(GPIO_WLAN_HOST_WAKE) || defined(CONFIG_ARCH_S5P6818) -+#ifdef HW_OOB -+ host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE; -+#else -+ host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_SHAREABLE; -+#endif -+#endif -+ printf("host_oob_irq_flags = %x\n", host_oob_irq_flags); ++ dll_init(&queue->list); ++ queue->head = queue->tail = NULL; ++ queue->len = 0; ++ queue->max = max - 1; ++ queue->failures = 0U; ++ queue->cb = &dhd_flow_queue_overflow; ++} + -+ return host_oob_irq_flags; ++void /* Register an enqueue overflow callback handler */ ++dhd_flow_queue_register(flow_queue_t *queue, flow_queue_cb_t cb) ++{ ++ ASSERT(queue != NULL); ++ queue->cb = cb; +} -+#endif + -+int bcm_wlan_set_power(bool on) ++ ++int BCMFASTPATH /* Enqueue a packet in a flow ring's queue */ ++dhd_flow_queue_enqueue(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt) +{ -+ int err = 0; ++ int ret = BCME_OK; + -+ if (on) { -+ printf("======== PULL WL_REG_ON HIGH! ========\n"); -+#ifdef GPIO_WLAN_EN -+ gpio_set_value(GPIO_WLAN_EN, 1); -+#elif defined(CONFIG_ARCH_S5P6818) -+ /* nanopi: the function sets high/low value on gpiob-24 pin, which is -+ * connected with WL_REG_ON pin on ap6212. -+ * When set to low, WLAN section of the chip is powered off and -+ * set in reset state. In this case the chip becomes also unresponsive -+ * on SDIO interface. But we don't want to interfere with mmc driver... -+ */ -+ //wifi_pm_gpio_ctrl("bcmdhd", 1); -+#endif -+ /* Lets customer power to get stable */ -+ msleep(50); ++ ASSERT(queue != NULL); ++ ++ if (queue->len >= queue->max) { ++ queue->failures++; ++ ret = (*queue->cb)(queue, pkt); ++ goto done; ++ } ++ ++ if (queue->head) { ++ FLOW_QUEUE_PKT_SETNEXT(queue->tail, pkt); + } else { -+ printf("======== PULL WL_REG_ON LOW! ========\n"); -+#ifdef GPIO_WLAN_EN -+ gpio_set_value(GPIO_WLAN_EN, 0); -+#elif defined(CONFIG_ARCH_S5P6818) -+ // wifi_pm_gpio_ctrl("bcmdhd", 0); -+#endif -+ msleep(50); ++ queue->head = pkt; + } + -+ return err; ++ FLOW_QUEUE_PKT_SETNEXT(pkt, NULL); ++ ++ queue->tail = pkt; /* at tail */ ++ ++ queue->len++; ++ ++done: ++ return ret; +} + -+int bcm_wlan_set_carddetect(bool present) ++void * BCMFASTPATH /* Dequeue a packet from a flow ring's queue, from head */ ++dhd_flow_queue_dequeue(dhd_pub_t *dhdp, flow_queue_t *queue) +{ -+ int err = 0; ++ void * pkt; + -+#if 0 -+ if (present) { -+ printf("======== Card detection to detect SDIO card! ========\n"); -+ err = sdhci_s3c_force_presence_change(&sdmmc_channel, 1); -+ } else { -+ printf("======== Card detection to remove SDIO card! ========\n"); -+ err = sdhci_s3c_force_presence_change(&sdmmc_channel, 0); ++ ASSERT(queue != NULL); ++ ++ pkt = queue->head; /* from head */ ++ ++ if (pkt == NULL) { ++ ASSERT((queue->len == 0) && (queue->tail == NULL)); ++ goto done; + } -+#endif + -+#if defined(CONFIG_ARCH_S5P6818) -+ /* nanopi: kernel 3.x has added method in MMC driver -+ * which mimics insertion/removal of SD card. -+ * The function is used after pull WL_REG_ON pin low/high. -+ */ -+ //force_presence_change(NULL, present); -+#else -+ mmc_force_presence_change_onoff(&sdmmc_channel, present); -+#endif ++ queue->head = FLOW_QUEUE_PKT_NEXT(pkt); ++ if (queue->head == NULL) ++ queue->tail = NULL; + -+ return err; ++ queue->len--; ++ ++ FLOW_QUEUE_PKT_SETNEXT(pkt, NULL); /* dettach packet from queue */ ++ ++done: ++ return pkt; +} + -+int bcm_wlan_get_mac_address(unsigned char *buf) ++void BCMFASTPATH /* Reinsert a dequeued packet back at the head */ ++dhd_flow_queue_reinsert(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt) +{ -+ int err = 0; -+ -+ printf("======== %s ========\n", __FUNCTION__); -+#ifdef EXAMPLE_GET_MAC -+ /* EXAMPLE code */ -+ { -+ struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}}; -+ bcopy((char *)&ea_example, buf, sizeof(struct ether_addr)); ++ if (queue->head == NULL) { ++ queue->tail = pkt; + } -+#endif /* EXAMPLE_GET_MAC */ + -+ return err; ++ FLOW_QUEUE_PKT_SETNEXT(pkt, queue->head); ++ queue->head = pkt; ++ queue->len++; +} + -+#ifdef CONFIG_DHD_USE_STATIC_BUF -+extern void *bcmdhd_mem_prealloc(int section, unsigned long size); -+void* bcm_wlan_prealloc(int section, unsigned long size) ++ ++/* Init Flow Ring specific data structures */ ++int ++dhd_flow_rings_init(dhd_pub_t *dhdp, uint32 num_flow_rings) +{ -+ void *alloc_ptr = NULL; -+ alloc_ptr = bcmdhd_mem_prealloc(section, size); -+ if (alloc_ptr) { -+ printf("success alloc section %d, size %ld\n", section, size); -+ if (size != 0L) -+ bzero(alloc_ptr, size); -+ return alloc_ptr; -+ } -+ printf("can't alloc section %d\n", section); -+ return NULL; -+} ++ uint32 idx; ++ uint32 flow_ring_table_sz; ++ uint32 if_flow_lkup_sz; ++ void * flowid_allocator; ++ flow_ring_table_t *flow_ring_table; ++ if_flow_lkup_t *if_flow_lkup = NULL; ++#ifdef PCIE_TX_DEFERRAL ++ uint32 count; +#endif ++ void *lock = NULL; ++ unsigned long flags; + -+int bcm_wlan_set_plat_data(void) { -+ printf("======== %s ========\n", __FUNCTION__); -+ dhd_wlan_control.set_power = bcm_wlan_set_power; -+ dhd_wlan_control.set_carddetect = bcm_wlan_set_carddetect; -+ dhd_wlan_control.get_mac_addr = bcm_wlan_get_mac_address; -+#ifdef CONFIG_DHD_USE_STATIC_BUF -+ dhd_wlan_control.mem_prealloc = bcm_wlan_prealloc; -+#endif -+ return 0; -+} ++ DHD_INFO(("%s\n", __FUNCTION__)); + -+#endif /* CUSTOMER_HW */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd.h b/drivers/net/wireless/bcm4336/dhd.h ---- a/drivers/net/wireless/bcm4336/dhd.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd.h 2018-05-06 08:49:50.618753851 +0200 -@@ -0,0 +1,1106 @@ -+/* -+ * Header file describing the internal (inter-module) DHD interfaces. -+ * -+ * Provides type definitions and function prototypes used to link the -+ * DHD OS, bus, and protocol modules. -+ * -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * $Id: dhd.h 504503 2014-09-24 11:28:56Z $ -+ */ ++ /* Construct a 16bit flow1d allocator */ ++ flowid_allocator = id16_map_init(dhdp->osh, ++ num_flow_rings - FLOW_RING_COMMON, FLOWID_RESERVED); ++ if (flowid_allocator == NULL) { ++ DHD_ERROR(("%s: flowid allocator init failure\n", __FUNCTION__)); ++ return BCME_NOMEM; ++ } + -+/**************** -+ * Common types * -+ */ ++ /* Allocate a flow ring table, comprising of requested number of rings */ ++ flow_ring_table_sz = (num_flow_rings * sizeof(flow_ring_node_t)); ++ flow_ring_table = (flow_ring_table_t *)MALLOC(dhdp->osh, flow_ring_table_sz); ++ if (flow_ring_table == NULL) { ++ DHD_ERROR(("%s: flow ring table alloc failure\n", __FUNCTION__)); ++ goto fail; ++ } + -+#ifndef _dhd_h_ -+#define _dhd_h_ ++ /* Initialize flow ring table state */ ++ bzero((uchar *)flow_ring_table, flow_ring_table_sz); ++ for (idx = 0; idx < num_flow_rings; idx++) { ++ flow_ring_table[idx].status = FLOW_RING_STATUS_CLOSED; ++ flow_ring_table[idx].flowid = (uint16)idx; ++ flow_ring_table[idx].lock = dhd_os_spin_lock_init(dhdp->osh); ++ if (flow_ring_table[idx].lock == NULL) { ++ DHD_ERROR(("%s: Failed to init spinlock for queue!\n", __FUNCTION__)); ++ goto fail; ++ } + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) -+#include -+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ -+/* The kernel threading is sdio-specific */ -+struct task_struct; -+struct sched_param; -+int setScheduler(struct task_struct *p, int policy, struct sched_param *param); -+int get_scheduler_policy(struct task_struct *p); -+#define MAX_EVENT 16 ++ dll_init(&flow_ring_table[idx].list); + -+#define ALL_INTERFACES 0xff ++ /* Initialize the per flow ring backup queue */ ++ dhd_flow_queue_init(dhdp, &flow_ring_table[idx].queue, ++ FLOW_RING_QUEUE_THRESHOLD); ++ } + -+#include -+#include -+#include ++ /* Allocate per interface hash table */ ++ if_flow_lkup_sz = sizeof(if_flow_lkup_t) * DHD_MAX_IFS; ++ if_flow_lkup = (if_flow_lkup_t *)DHD_OS_PREALLOC(dhdp, ++ DHD_PREALLOC_IF_FLOW_LKUP, if_flow_lkup_sz); ++ if (if_flow_lkup == NULL) { ++ DHD_ERROR(("%s: if flow lkup alloc failure\n", __FUNCTION__)); ++ goto fail; ++ } + -+#if defined(BCMWDF) -+#include -+#include -+#endif /* (BCMWDF) */ ++ /* Initialize per interface hash table */ ++ bzero((uchar *)if_flow_lkup, if_flow_lkup_sz); ++ for (idx = 0; idx < DHD_MAX_IFS; idx++) { ++ int hash_ix; ++ if_flow_lkup[idx].status = 0; ++ if_flow_lkup[idx].role = 0; ++ for (hash_ix = 0; hash_ix < DHD_FLOWRING_HASH_SIZE; hash_ix++) ++ if_flow_lkup[idx].fl_hash[hash_ix] = NULL; ++ } + -+#if defined(WL11U) && !defined(MFP) -+#define MFP /* Applying interaction with MFP by spec HS2.0 REL2 */ -+#endif /* WL11U */ ++#ifdef PCIE_TX_DEFERRAL ++ count = BITS_TO_LONGS(num_flow_rings); ++ dhdp->bus->delete_flow_map = kzalloc(count, GFP_ATOMIC); ++ if (!dhdp->bus->delete_flow_map) { ++ DHD_ERROR(("%s: delete_flow_map alloc failure\n", __FUNCTION__)); ++ goto fail; ++ } ++#endif + -+#if defined(KEEP_ALIVE) -+/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ -+#define KEEP_ALIVE_PERIOD 55000 -+#define NULL_PKT_STR "null_pkt" -+#endif /* KEEP_ALIVE */ -+/* Forward decls */ -+struct dhd_bus; -+struct dhd_prot; -+struct dhd_info; -+struct dhd_ioctl; ++ lock = dhd_os_spin_lock_init(dhdp->osh); ++ if (lock == NULL) ++ goto fail; + -+/* The level of bus communication with the dongle */ -+enum dhd_bus_state { -+ DHD_BUS_DOWN, /* Not ready for frame transfers */ -+ DHD_BUS_LOAD, /* Download access only (CPU reset) */ -+ DHD_BUS_DATA, /* Ready for frame transfers */ -+ DHD_BUS_SUSPEND, /* Bus has been suspended */ -+}; ++ dhdp->flow_prio_map_type = DHD_FLOW_PRIO_AC_MAP; ++ bcopy(prio2ac, dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO); + -+#if defined(NDISVER) -+#if (NDISVER >= 0x0600) -+/* Firmware requested operation mode */ -+#define STA_MASK 0x0001 -+#define HOSTAPD_MASK 0x0002 -+#define WFD_MASK 0x0004 -+#define SOFTAP_FW_MASK 0x0008 -+#define P2P_GO_ENABLED 0x0010 -+#define P2P_GC_ENABLED 0x0020 -+#define CONCURENT_MASK 0x00F0 -+#endif /* (NDISVER >= 0x0600) */ -+#endif /* #if defined(NDISVER) */ ++ /* Now populate into dhd pub */ ++ DHD_FLOWID_LOCK(lock, flags); ++ dhdp->num_flow_rings = num_flow_rings; ++ dhdp->flowid_allocator = (void *)flowid_allocator; ++ dhdp->flow_ring_table = (void *)flow_ring_table; ++ dhdp->if_flow_lkup = (void *)if_flow_lkup; ++ dhdp->flowid_lock = lock; ++ DHD_FLOWID_UNLOCK(lock, flags); + -+#define DHD_IF_ROLE_STA(role) (role == WLC_E_IF_ROLE_STA ||\ -+ role == WLC_E_IF_ROLE_P2P_CLIENT) ++ DHD_INFO(("%s done\n", __FUNCTION__)); ++ return BCME_OK; + -+/* For supporting multiple interfaces */ -+#define DHD_MAX_IFS 16 -+#define DHD_DEL_IF -0xE -+#define DHD_BAD_IF -0xF ++fail: + -+enum dhd_op_flags { -+/* Firmware requested operation mode */ -+ DHD_FLAG_STA_MODE = (1 << (0)), /* STA only */ -+ DHD_FLAG_HOSTAP_MODE = (1 << (1)), /* SOFTAP only */ -+ DHD_FLAG_P2P_MODE = (1 << (2)), /* P2P Only */ -+ /* STA + P2P */ -+ DHD_FLAG_CONCURR_SINGLE_CHAN_MODE = (DHD_FLAG_STA_MODE | DHD_FLAG_P2P_MODE), -+ DHD_FLAG_CONCURR_MULTI_CHAN_MODE = (1 << (4)), /* STA + P2P */ -+ /* Current P2P mode for P2P connection */ -+ DHD_FLAG_P2P_GC_MODE = (1 << (5)), -+ DHD_FLAG_P2P_GO_MODE = (1 << (6)), -+ DHD_FLAG_MBSS_MODE = (1 << (7)), /* MBSS in future */ -+ DHD_FLAG_IBSS_MODE = (1 << (8)), -+ DHD_FLAG_MFG_MODE = (1 << (9)) -+}; ++#ifdef PCIE_TX_DEFERRAL ++ if (dhdp->bus->delete_flow_map) ++ kfree(dhdp->bus->delete_flow_map); ++#endif ++ /* Destruct the per interface flow lkup table */ ++ if (dhdp->if_flow_lkup != NULL) { ++ DHD_OS_PREFREE(dhdp, if_flow_lkup, if_flow_lkup_sz); ++ } ++ if (flow_ring_table != NULL) { ++ for (idx = 0; idx < num_flow_rings; idx++) { ++ if (flow_ring_table[idx].lock != NULL) ++ dhd_os_spin_lock_deinit(dhdp->osh, flow_ring_table[idx].lock); ++ } ++ MFREE(dhdp->osh, flow_ring_table, flow_ring_table_sz); ++ } ++ id16_map_fini(dhdp->osh, flowid_allocator); + -+/* Max sequential TX/RX Control timeouts to set HANG event */ -+#ifndef MAX_CNTL_TX_TIMEOUT -+#define MAX_CNTL_TX_TIMEOUT 2 -+#endif /* MAX_CNTL_TX_TIMEOUT */ -+#ifndef MAX_CNTL_RX_TIMEOUT -+#define MAX_CNTL_RX_TIMEOUT 1 -+#endif /* MAX_CNTL_RX_TIMEOUT */ ++ return BCME_NOMEM; ++} + -+#define DHD_SCAN_ASSOC_ACTIVE_TIME 40 /* ms: Embedded default Active setting from DHD */ -+#define DHD_SCAN_UNASSOC_ACTIVE_TIME 80 /* ms: Embedded def. Unassoc Active setting from DHD */ -+#define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD */ ++/* Deinit Flow Ring specific data structures */ ++void dhd_flow_rings_deinit(dhd_pub_t *dhdp) ++{ ++ uint16 idx; ++ uint32 flow_ring_table_sz; ++ uint32 if_flow_lkup_sz; ++ flow_ring_table_t *flow_ring_table; ++ unsigned long flags; ++ void *lock; + -+#ifndef POWERUP_MAX_RETRY -+#define POWERUP_MAX_RETRY 3 /* how many times we retry to power up the chip */ -+#endif -+#ifndef POWERUP_WAIT_MS -+#define POWERUP_WAIT_MS 2000 /* ms: time out in waiting wifi to come up */ -+#endif ++ DHD_INFO(("dhd_flow_rings_deinit\n")); + -+enum dhd_bus_wake_state { -+ WAKE_LOCK_OFF, -+ WAKE_LOCK_PRIV, -+ WAKE_LOCK_DPC, -+ WAKE_LOCK_IOCTL, -+ WAKE_LOCK_DOWNLOAD, -+ WAKE_LOCK_TMOUT, -+ WAKE_LOCK_WATCHDOG, -+ WAKE_LOCK_LINK_DOWN_TMOUT, -+ WAKE_LOCK_PNO_FIND_TMOUT, -+ WAKE_LOCK_SOFTAP_SET, -+ WAKE_LOCK_SOFTAP_STOP, -+ WAKE_LOCK_SOFTAP_START, -+ WAKE_LOCK_SOFTAP_THREAD -+}; ++ if (dhdp->flow_ring_table != NULL) { + -+enum dhd_prealloc_index { -+ DHD_PREALLOC_PROT = 0, -+ DHD_PREALLOC_RXBUF, -+ DHD_PREALLOC_DATABUF, -+ DHD_PREALLOC_OSL_BUF, -+#if defined(STATIC_WL_PRIV_STRUCT) -+ DHD_PREALLOC_WIPHY_ESCAN0 = 5, -+#endif /* STATIC_WL_PRIV_STRUCT */ -+ DHD_PREALLOC_DHD_INFO = 7, -+ DHD_PREALLOC_DHD_WLFC_INFO = 8, -+ DHD_PREALLOC_IF_FLOW_LKUP = 9, -+ DHD_PREALLOC_FLOWRING = 10 -+}; ++ ASSERT(dhdp->num_flow_rings > 0); + -+/* Packet alignment for most efficient SDIO (can change based on platform) */ -+#ifndef DHD_SDALIGN -+#define DHD_SDALIGN 32 -+#endif ++ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); ++ flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table; ++ dhdp->flow_ring_table = NULL; ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); ++ for (idx = 0; idx < dhdp->num_flow_rings; idx++) { ++ if (flow_ring_table[idx].active) { ++ dhd_bus_clean_flow_ring(dhdp->bus, &flow_ring_table[idx]); ++ } ++ ASSERT(flow_queue_empty(&flow_ring_table[idx].queue)); + -+/* host reordering packts logic */ -+/* followed the structure to hold the reorder buffers (void **p) */ -+typedef struct reorder_info { -+ void **p; -+ uint8 flow_id; -+ uint8 cur_idx; -+ uint8 exp_idx; -+ uint8 max_idx; -+ uint8 pend_pkts; -+} reorder_info_t; ++ /* Deinit flow ring queue locks before destroying flow ring table */ ++ dhd_os_spin_lock_deinit(dhdp->osh, flow_ring_table[idx].lock); ++ flow_ring_table[idx].lock = NULL; ++ } + -+#ifdef DHDTCPACK_SUPPRESS ++ /* Destruct the flow ring table */ ++ flow_ring_table_sz = dhdp->num_flow_rings * sizeof(flow_ring_table_t); ++ MFREE(dhdp->osh, flow_ring_table, flow_ring_table_sz); ++ } + -+enum { -+ /* TCPACK suppress off */ -+ TCPACK_SUP_OFF, -+ /* Replace TCPACK in txq when new coming one has higher ACK number. */ -+ TCPACK_SUP_REPLACE, -+ /* TCPACK_SUP_REPLACE + delayed TCPACK TX unless ACK to PSH DATA. -+ * This will give benefits to Half-Duplex bus interface(e.g. SDIO) that -+ * 1. we are able to read TCP DATA packets first from the bus -+ * 2. TCPACKs that don't need to hurry delivered remains longer in TXQ so can be suppressed. -+ */ -+ TCPACK_SUP_DELAYTX, -+ TCPACK_SUP_HOLD, -+ TCPACK_SUP_LAST_MODE -+}; -+#endif /* DHDTCPACK_SUPPRESS */ ++ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); + ++ /* Destruct the per interface flow lkup table */ ++ if (dhdp->if_flow_lkup != NULL) { ++ if_flow_lkup_sz = sizeof(if_flow_lkup_t) * DHD_MAX_IFS; ++ bzero(dhdp->if_flow_lkup, sizeof(if_flow_lkup_sz)); ++ DHD_OS_PREFREE(dhdp, dhdp->if_flow_lkup, if_flow_lkup_sz); ++ dhdp->if_flow_lkup = NULL; ++ } + -+/* DMA'ing r/w indices for rings supported */ -+#ifdef BCM_INDX_TCM /* FW gets r/w indices in TCM */ -+#define DMA_INDX_ENAB(dma_indxsup) 0 -+#elif defined BCM_INDX_DMA /* FW gets r/w indices from Host memory */ -+#define DMA_INDX_ENAB(dma_indxsup) 1 -+#else /* r/w indices in TCM or host memory based on FW/Host agreement */ -+#define DMA_INDX_ENAB(dma_indxsup) dma_indxsup -+#endif /* BCM_INDX_TCM */ ++#ifdef PCIE_TX_DEFERRAL ++ if (dhdp->bus->delete_flow_map) ++ kfree(dhdp->bus->delete_flow_map); ++#endif + -+#if defined(WLTDLS) && defined(PCIE_FULL_DONGLE) -+struct tdls_peer_node { -+ uint8 addr[ETHER_ADDR_LEN]; -+ struct tdls_peer_node *next; -+}; -+typedef struct tdls_peer_node tdls_peer_node_t; -+typedef struct { -+ tdls_peer_node_t *node; -+ uint8 tdls_peer_count; -+} tdls_peer_tbl_t; -+#endif /* defined(WLTDLS) && defined(PCIE_FULL_DONGLE) */ ++ /* Destruct the flowid allocator */ ++ if (dhdp->flowid_allocator != NULL) ++ dhdp->flowid_allocator = id16_map_fini(dhdp->osh, dhdp->flowid_allocator); + -+/* Common structure for module and instance linkage */ -+typedef struct dhd_pub { -+ /* Linkage ponters */ -+ osl_t *osh; /* OSL handle */ -+ struct dhd_bus *bus; /* Bus module handle */ -+ struct dhd_prot *prot; /* Protocol module handle */ -+ struct dhd_info *info; /* Info module handle */ ++ dhdp->num_flow_rings = 0U; ++ lock = dhdp->flowid_lock; ++ dhdp->flowid_lock = NULL; + -+ /* to NDIS developer, the structure dhd_common is redundant, -+ * please do NOT merge it back from other branches !!! -+ */ ++ DHD_FLOWID_UNLOCK(lock, flags); ++ dhd_os_spin_lock_deinit(dhdp->osh, lock); ++} + ++uint8 ++dhd_flow_rings_ifindex2role(dhd_pub_t *dhdp, uint8 ifindex) ++{ ++ if_flow_lkup_t *if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; ++ ASSERT(if_flow_lkup); ++ return if_flow_lkup[ifindex].role; ++} + -+ /* Internal dhd items */ -+ bool up; /* Driver up/down (to OS) */ -+ bool txoff; /* Transmit flow-controlled */ -+ bool dongle_reset; /* TRUE = DEVRESET put dongle into reset */ -+ enum dhd_bus_state busstate; -+ uint hdrlen; /* Total DHD header length (proto + bus) */ -+ uint maxctl; /* Max size rxctl request from proto to bus */ -+ uint rxsz; /* Rx buffer size bus module should use */ -+ uint8 wme_dp; /* wme discard priority */ ++#ifdef WLTDLS ++bool is_tdls_destination(dhd_pub_t *dhdp, uint8 *da) ++{ ++ tdls_peer_node_t *cur = dhdp->peer_tbl.node; ++ while (cur != NULL) { ++ if (!memcmp(da, cur->addr, ETHER_ADDR_LEN)) { ++ return TRUE; ++ } ++ cur = cur->next; ++ } ++ return FALSE; ++} ++#endif /* WLTDLS */ + -+ /* Dongle media info */ -+ bool iswl; /* Dongle-resident driver is wl */ -+ ulong drv_version; /* Version of dongle-resident driver */ -+ struct ether_addr mac; /* MAC address obtained from dongle */ -+ dngl_stats_t dstats; /* Stats for dongle-based data */ ++/* For a given interface, search the hash table for a matching flow */ ++uint16 ++dhd_flowid_find(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, char *sa, char *da) ++{ ++ int hash; ++ bool ismcast = FALSE; ++ flow_hash_info_t *cur; ++ if_flow_lkup_t *if_flow_lkup; ++ unsigned long flags; + -+ /* Additional stats for the bus level */ -+ ulong tx_packets; /* Data packets sent to dongle */ -+ ulong tx_dropped; /* Data packets dropped in dhd */ -+ ulong tx_multicast; /* Multicast data packets sent to dongle */ -+ ulong tx_errors; /* Errors in sending data to dongle */ -+ ulong tx_ctlpkts; /* Control packets sent to dongle */ -+ ulong tx_ctlerrs; /* Errors sending control frames to dongle */ -+ ulong rx_packets; /* Packets sent up the network interface */ -+ ulong rx_multicast; /* Multicast packets sent up the network interface */ -+ ulong rx_errors; /* Errors processing rx data packets */ -+ ulong rx_ctlpkts; /* Control frames processed from dongle */ -+ ulong rx_ctlerrs; /* Errors in processing rx control frames */ -+ ulong rx_dropped; /* Packets dropped locally (no memory) */ -+ ulong rx_flushed; /* Packets flushed due to unscheduled sendup thread */ -+ ulong wd_dpc_sched; /* Number of times dhd dpc scheduled by watchdog timer */ ++ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); ++ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; + -+ ulong rx_readahead_cnt; /* Number of packets where header read-ahead was used. */ -+ ulong tx_realloc; /* Number of tx packets we had to realloc for headroom */ -+ ulong fc_packets; /* Number of flow control pkts recvd */ ++ if (DHD_IF_ROLE_STA(if_flow_lkup[ifindex].role)) { ++#ifdef WLTDLS ++ if (dhdp->peer_tbl.tdls_peer_count && !(ETHER_ISMULTI(da)) && ++ is_tdls_destination(dhdp, da)) { ++ hash = DHD_FLOWRING_HASHINDEX(da, prio); ++ cur = if_flow_lkup[ifindex].fl_hash[hash]; ++ while (cur != NULL) { ++ if (!memcmp(cur->flow_info.da, da, ETHER_ADDR_LEN)) { ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); ++ return cur->flowid; ++ } ++ cur = cur->next; ++ } ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); ++ return FLOWID_INVALID; ++ } ++#endif /* WLTDLS */ ++ cur = if_flow_lkup[ifindex].fl_hash[prio]; ++ if (cur) { ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); ++ return cur->flowid; ++ } + -+ /* Last error return */ -+ int bcmerror; -+ uint tickcnt; ++ } else { + -+ /* Last error from dongle */ -+ int dongle_error; ++ if (ETHER_ISMULTI(da)) { ++ ismcast = TRUE; ++ hash = 0; ++ } else { ++ hash = DHD_FLOWRING_HASHINDEX(da, prio); ++ } + -+ uint8 country_code[WLC_CNTRY_BUF_SZ]; ++ cur = if_flow_lkup[ifindex].fl_hash[hash]; + -+ /* Suspend disable flag and "in suspend" flag */ -+ int suspend_disable_flag; /* "1" to disable all extra powersaving during suspend */ -+ int in_suspend; /* flag set to 1 when early suspend called */ -+#ifdef PNO_SUPPORT -+ int pno_enable; /* pno status : "1" is pno enable */ -+ int pno_suspend; /* pno suspend status : "1" is pno suspended */ -+#endif /* PNO_SUPPORT */ -+ /* DTIM skip value, default 0(or 1) means wake each DTIM -+ * 3 means skip 2 DTIMs and wake up 3rd DTIM(9th beacon when AP DTIM is 3) -+ */ -+ int suspend_bcn_li_dtim; /* bcn_li_dtim value in suspend mode */ -+#ifdef PKT_FILTER_SUPPORT -+ int early_suspended; /* Early suspend status */ -+ int dhcp_in_progress; /* DHCP period */ -+#endif ++ while (cur) { ++ if ((ismcast && ETHER_ISMULTI(cur->flow_info.da)) || ++ (!memcmp(cur->flow_info.da, da, ETHER_ADDR_LEN) && ++ (cur->flow_info.tid == prio))) { ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); ++ return cur->flowid; ++ } ++ cur = cur->next; ++ } ++ } ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); + -+ /* Pkt filter defination */ -+ char * pktfilter[100]; -+ int pktfilter_count; ++ return FLOWID_INVALID; ++} + -+ wl_country_t dhd_cspec; /* Current Locale info */ -+ char eventmask[WL_EVENTING_MASK_LEN]; -+ int op_mode; /* STA, HostAPD, WFD, SoftAP */ ++/* Allocate Flow ID */ ++static INLINE uint16 ++dhd_flowid_alloc(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, char *sa, char *da) ++{ ++ flow_hash_info_t *fl_hash_node, *cur; ++ if_flow_lkup_t *if_flow_lkup; ++ int hash; ++ uint16 flowid; ++ unsigned long flags; + -+/* Set this to 1 to use a seperate interface (p2p0) for p2p operations. -+ * For ICS MR1 releases it should be disable to be compatable with ICS MR1 Framework -+ * see target dhd-cdc-sdmmc-panda-cfg80211-icsmr1-gpl-debug in Makefile -+ */ -+/* #define WL_ENABLE_P2P_IF 1 */ ++ fl_hash_node = (flow_hash_info_t *) MALLOC(dhdp->osh, sizeof(flow_hash_info_t)); ++ memcpy(fl_hash_node->flow_info.da, da, sizeof(fl_hash_node->flow_info.da)); + -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 -+ struct mutex wl_start_stop_lock; /* lock/unlock for Android start/stop */ -+ struct mutex wl_softap_lock; /* lock/unlock for any SoftAP/STA settings */ -+#endif ++ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); ++ ASSERT(dhdp->flowid_allocator != NULL); ++ flowid = id16_map_alloc(dhdp->flowid_allocator); ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); + -+#ifdef WLBTAMP -+ uint16 maxdatablks; -+#endif /* WLBTAMP */ -+#ifdef PROP_TXSTATUS -+ bool wlfc_enabled; -+ int wlfc_mode; -+ void* wlfc_state; -+ /* -+ Mode in which the dhd flow control shall operate. Must be set before -+ traffic starts to the device. -+ 0 - Do not do any proptxtstatus flow control -+ 1 - Use implied credit from a packet status -+ 2 - Use explicit credit -+ 3 - Only AMPDU hostreorder used. no wlfc. -+ */ -+ uint8 proptxstatus_mode; -+ bool proptxstatus_txoff; -+ bool proptxstatus_module_ignore; -+ bool proptxstatus_credit_ignore; -+ bool proptxstatus_txstatus_ignore; ++ if (flowid == FLOWID_INVALID) { ++ MFREE(dhdp->osh, fl_hash_node, sizeof(flow_hash_info_t)); ++ DHD_ERROR(("%s: cannot get free flowid \n", __FUNCTION__)); ++ return FLOWID_INVALID; ++ } + -+ bool wlfc_rxpkt_chk; -+ /* -+ * implement below functions in each platform if needed. -+ */ -+ /* platform specific function whether to skip flow control */ -+ bool (*skip_fc)(void); -+ /* platform specific function for wlfc_enable and wlfc_deinit */ -+ void (*plat_init)(void *dhd); -+ void (*plat_deinit)(void *dhd); -+#endif /* PROP_TXSTATUS */ -+#ifdef PNO_SUPPORT -+ void *pno_state; -+#endif -+ bool dongle_isolation; -+ bool dongle_trap_occured; /* flag for sending HANG event to upper layer */ -+ int hang_was_sent; -+ int rxcnt_timeout; /* counter rxcnt timeout to send HANG */ -+ int txcnt_timeout; /* counter txcnt timeout to send HANG */ -+ bool hang_report; /* enable hang report by default */ -+#ifdef WLMEDIA_HTSF -+ uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */ -+#endif -+#ifdef WLTDLS -+ bool tdls_enable; -+#endif -+ struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS]; -+ char fw_capabilities[WLC_IOCTL_SMLEN]; -+ #define MAXSKBPEND 1024 -+ void *skbbuf[MAXSKBPEND]; -+ uint32 store_idx; -+ uint32 sent_idx; -+#ifdef DHDTCPACK_SUPPRESS -+ uint8 tcpack_sup_mode; /* TCPACK suppress mode */ -+ void *tcpack_sup_module; /* TCPACK suppress module */ -+ uint32 tcpack_sup_ratio; -+ uint32 tcpack_sup_delay; -+#endif /* DHDTCPACK_SUPPRESS */ -+#if defined(ARP_OFFLOAD_SUPPORT) -+ uint32 arp_version; -+#endif -+#if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X) -+ bool fw_4way_handshake; /* Whether firmware will to do the 4way handshake. */ -+#endif -+#if defined(CUSTOM_PLATFORM_NV_TEGRA) -+#ifdef PKT_FILTER_SUPPORT -+ uint pkt_filter_mode; -+ uint pkt_filter_ports_count; -+ uint16 pkt_filter_ports[WL_PKT_FILTER_PORTS_MAX]; -+#endif /* PKT_FILTER_SUPPORT */ -+#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */ -+#ifdef CUSTOM_SET_CPUCORE -+ struct task_struct * current_dpc; -+ struct task_struct * current_rxf; -+ int chan_isvht80; -+#endif /* CUSTOM_SET_CPUCORE */ ++ fl_hash_node->flowid = flowid; ++ fl_hash_node->flow_info.tid = prio; ++ fl_hash_node->flow_info.ifindex = ifindex; ++ fl_hash_node->next = NULL; + -+ void *sta_pool; /* pre-allocated pool of sta objects */ -+ void *staid_allocator; /* allocator of sta indexes */ ++ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); ++ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; ++ if (DHD_IF_ROLE_STA(if_flow_lkup[ifindex].role)) { ++ /* For STA non TDLS dest we allocate entry based on prio only */ ++#ifdef WLTDLS ++ if (dhdp->peer_tbl.tdls_peer_count && ++ (is_tdls_destination(dhdp, da))) { ++ hash = DHD_FLOWRING_HASHINDEX(da, prio); ++ cur = if_flow_lkup[ifindex].fl_hash[hash]; ++ if (cur) { ++ while (cur->next) { ++ cur = cur->next; ++ } ++ cur->next = fl_hash_node; ++ } else { ++ if_flow_lkup[ifindex].fl_hash[hash] = fl_hash_node; ++ } ++ } else ++#endif /* WLTDLS */ ++ if_flow_lkup[ifindex].fl_hash[prio] = fl_hash_node; ++ } else { + -+ void *flowid_allocator; /* unique flowid allocator */ -+ void *flow_ring_table; /* flow ring table, include prot and bus info */ -+ void *if_flow_lkup; /* per interface flowid lkup hash table */ -+ void *flowid_lock; /* per os lock for flowid info protection */ -+ uint32 num_flow_rings; ++ /* For bcast/mcast assign first slot in in interface */ ++ hash = ETHER_ISMULTI(da) ? 0 : DHD_FLOWRING_HASHINDEX(da, prio); ++ cur = if_flow_lkup[ifindex].fl_hash[hash]; ++ if (cur) { ++ while (cur->next) { ++ cur = cur->next; ++ } ++ cur->next = fl_hash_node; ++ } else ++ if_flow_lkup[ifindex].fl_hash[hash] = fl_hash_node; ++ } ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); + -+ uint32 d2h_sync_mode; /* D2H DMA completion sync mode */ ++ DHD_INFO(("%s: allocated flowid %d\n", __FUNCTION__, fl_hash_node->flowid)); + -+ uint8 flow_prio_map[NUMPRIO]; -+ uint8 flow_prio_map_type; -+ char enable_log[MAX_EVENT]; -+ bool dma_d2h_ring_upd_support; -+ bool dma_h2d_ring_upd_support; -+#ifdef DHD_WMF -+ bool wmf_ucast_igmp; -+#ifdef DHD_IGMP_UCQUERY -+ bool wmf_ucast_igmp_query; -+#endif -+#ifdef DHD_UCAST_UPNP -+ bool wmf_ucast_upnp; -+#endif -+#endif /* DHD_WMF */ -+#ifdef DHD_UNICAST_DHCP -+ bool dhcp_unicast; -+#endif /* DHD_UNICAST_DHCP */ -+#ifdef DHD_L2_FILTER -+ bool block_ping; -+#endif -+#if defined(WLTDLS) && defined(PCIE_FULL_DONGLE) -+ tdls_peer_tbl_t peer_tbl; -+#endif /* defined(WLTDLS) && defined(PCIE_FULL_DONGLE) */ -+ char *conf_path; /* module_param: path to config vars file */ -+ struct dhd_conf *conf; /* Bus module handle */ -+} dhd_pub_t; ++ return fl_hash_node->flowid; ++} + -+#if defined(BCMWDF) -+typedef struct { -+ dhd_pub_t *dhd_pub; -+} dhd_workitem_context_t; ++/* Get flow ring ID, if not present try to create one */ ++static INLINE int ++dhd_flowid_lookup(dhd_pub_t *dhdp, uint8 ifindex, ++ uint8 prio, char *sa, char *da, uint16 *flowid) ++{ ++ uint16 id; ++ flow_ring_node_t *flow_ring_node; ++ flow_ring_table_t *flow_ring_table; ++ unsigned long flags; + -+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(dhd_workitem_context_t, dhd_get_dhd_workitem_context) -+#endif /* (BCMWDF) */ ++ DHD_INFO(("%s\n", __FUNCTION__)); + -+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) ++ if (!dhdp->flow_ring_table) ++ return BCME_ERROR; + -+ #define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); -+ #define _DHD_PM_RESUME_WAIT(a, b) do {\ -+ int retry = 0; \ -+ SMP_RD_BARRIER_DEPENDS(); \ -+ while (dhd_mmc_suspend && retry++ != b) { \ -+ SMP_RD_BARRIER_DEPENDS(); \ -+ wait_event_interruptible_timeout(a, !dhd_mmc_suspend, 1); \ -+ } \ -+ } while (0) -+ #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 200) -+ #define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0) -+ #ifdef CUSTOMER_HW4 -+ #define DHD_PM_RESUME_RETURN_ERROR(a) do { \ -+ if (dhd_mmc_suspend) { \ -+ printf("%s[%d]: mmc is still in suspend state!!!\n", \ -+ __FUNCTION__, __LINE__); \ -+ return a; \ -+ } \ -+ } while (0) -+ #else -+ #define DHD_PM_RESUME_RETURN_ERROR(a) do { \ -+ if (dhd_mmc_suspend) return a; } while (0) -+ #endif -+ #define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0) ++ flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table; + -+ #define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); -+ #define SPINWAIT_SLEEP(a, exp, us) do { \ -+ uint countdown = (us) + 9999; \ -+ while ((exp) && (countdown >= 10000)) { \ -+ wait_event_interruptible_timeout(a, FALSE, 1); \ -+ countdown -= 10000; \ -+ } \ -+ } while (0) ++ id = dhd_flowid_find(dhdp, ifindex, prio, sa, da); + -+ #else ++ if (id == FLOWID_INVALID) { + -+ #define DHD_PM_RESUME_WAIT_INIT(a) -+ #define DHD_PM_RESUME_WAIT(a) -+ #define DHD_PM_RESUME_WAIT_FOREVER(a) -+ #define DHD_PM_RESUME_RETURN_ERROR(a) -+ #define DHD_PM_RESUME_RETURN ++ if_flow_lkup_t *if_flow_lkup; ++ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; + -+ #define DHD_SPINWAIT_SLEEP_INIT(a) -+ #define SPINWAIT_SLEEP(a, exp, us) do { \ -+ uint countdown = (us) + 9; \ -+ while ((exp) && (countdown >= 10)) { \ -+ OSL_DELAY(10); \ -+ countdown -= 10; \ -+ } \ -+ } while (0) ++ if (!if_flow_lkup[ifindex].status) ++ return BCME_ERROR; + -+ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ ++ id = dhd_flowid_alloc(dhdp, ifindex, prio, sa, da); ++ if (id == FLOWID_INVALID) { ++ DHD_ERROR(("%s: alloc flowid ifindex %u status %u\n", ++ __FUNCTION__, ifindex, if_flow_lkup[ifindex].status)); ++ return BCME_ERROR; ++ } + -+#ifndef OSL_SLEEP -+#define OSL_SLEEP(ms) OSL_DELAY(ms*1000) -+#endif /* OSL_SLEEP */ ++ /* register this flowid in dhd_pub */ ++ dhd_add_flowid(dhdp, ifindex, prio, da, id); ++ } + -+#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */ ++ ASSERT(id < dhdp->num_flow_rings); + -+#ifdef PNO_SUPPORT -+int dhd_pno_clean(dhd_pub_t *dhd); -+#endif /* PNO_SUPPORT */ -+/* -+ * Wake locks are an Android power management concept. They are used by applications and services -+ * to request CPU resources. -+ */ -+extern int dhd_os_wake_lock(dhd_pub_t *pub); -+extern int dhd_os_wake_unlock(dhd_pub_t *pub); -+extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub); -+extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val); -+extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val); -+extern int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub); -+extern int dhd_os_wd_wake_lock(dhd_pub_t *pub); -+extern int dhd_os_wd_wake_unlock(dhd_pub_t *pub); -+#ifdef BCMPCIE_OOB_HOST_WAKE -+extern int dhd_os_oob_irq_wake_lock_timeout(dhd_pub_t *pub, int val); -+extern int dhd_os_oob_irq_wake_unlock(dhd_pub_t *pub); -+#endif /* BCMPCIE_OOB_HOST_WAKE */ -+extern int dhd_os_wake_lock_waive(dhd_pub_t *pub); -+extern int dhd_os_wake_lock_restore(dhd_pub_t *pub); ++ flow_ring_node = (flow_ring_node_t *) &flow_ring_table[id]; ++ DHD_FLOWRING_LOCK(flow_ring_node->lock, flags); ++ if (flow_ring_node->active) { ++ DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags); ++ *flowid = id; ++ return BCME_OK; ++ } ++ /* Init Flow info */ ++ memcpy(flow_ring_node->flow_info.sa, sa, sizeof(flow_ring_node->flow_info.sa)); ++ memcpy(flow_ring_node->flow_info.da, da, sizeof(flow_ring_node->flow_info.da)); ++ flow_ring_node->flow_info.tid = prio; ++ flow_ring_node->flow_info.ifindex = ifindex; ++ flow_ring_node->active = TRUE; ++ flow_ring_node->status = FLOW_RING_STATUS_PENDING; ++ DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags); ++ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); ++ dll_prepend(&dhdp->bus->const_flowring, &flow_ring_node->list); ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); + -+inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp) -+{ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 -+ mutex_init(&dhdp->wl_softap_lock); -+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -+} ++ /* Create and inform device about the new flow */ ++ if (dhd_bus_flow_ring_create_request(dhdp->bus, (void *)flow_ring_node) ++ != BCME_OK) { ++ DHD_ERROR(("%s: create error %d\n", __FUNCTION__, id)); ++ return BCME_ERROR; ++ } + -+inline static void MUTEX_LOCK_SOFTAP_SET(dhd_pub_t * dhdp) -+{ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 -+ mutex_lock(&dhdp->wl_softap_lock); -+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ ++ *flowid = id; ++ return BCME_OK; +} + -+inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) ++/* Update flowid information on the packet */ ++int BCMFASTPATH ++dhd_flowid_update(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, void *pktbuf) +{ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 -+ mutex_unlock(&dhdp->wl_softap_lock); -+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -+} ++ uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, pktbuf); ++ struct ether_header *eh = (struct ether_header *)pktdata; ++ uint16 flowid; + -+#define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub) -+#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub) -+#define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub) -+#define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) \ -+ dhd_os_wake_lock_rx_timeout_enable(pub, val) -+#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) \ -+ dhd_os_wake_lock_ctrl_timeout_enable(pub, val) -+#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL(pub) \ -+ dhd_os_wake_lock_ctrl_timeout_cancel(pub) -+#define DHD_OS_WAKE_LOCK_WAIVE(pub) dhd_os_wake_lock_waive(pub) -+#define DHD_OS_WAKE_LOCK_RESTORE(pub) dhd_os_wake_lock_restore(pub) ++ if (dhd_bus_is_txmode_push(dhdp->bus)) ++ return BCME_OK; + -+#define DHD_OS_WD_WAKE_LOCK(pub) dhd_os_wd_wake_lock(pub) -+#define DHD_OS_WD_WAKE_UNLOCK(pub) dhd_os_wd_wake_unlock(pub) -+#ifdef BCMPCIE_OOB_HOST_WAKE -+#define OOB_WAKE_LOCK_TIMEOUT 500 -+#define DHD_OS_OOB_IRQ_WAKE_LOCK_TIMEOUT(pub, val) dhd_os_oob_irq_wake_lock_timeout(pub, val) -+#define DHD_OS_OOB_IRQ_WAKE_UNLOCK(pub) dhd_os_oob_irq_wake_unlock(pub) -+#endif /* BCMPCIE_OOB_HOST_WAKE */ -+#define DHD_PACKET_TIMEOUT_MS 500 -+#define DHD_EVENT_TIMEOUT_MS 1500 ++ ASSERT(ifindex < DHD_MAX_IFS); ++ if (ifindex >= DHD_MAX_IFS) { ++ return BCME_BADARG; ++ } + ++ if (!dhdp->flowid_allocator) { ++ DHD_ERROR(("%s: Flow ring not intited yet \n", __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ if (dhd_flowid_lookup(dhdp, ifindex, prio, eh->ether_shost, eh->ether_dhost, ++ &flowid) != BCME_OK) { ++ return BCME_ERROR; ++ } + -+/* interface operations (register, remove) should be atomic, use this lock to prevent race -+ * condition among wifi on/off and interface operation functions -+ */ -+void dhd_net_if_lock(struct net_device *dev); -+void dhd_net_if_unlock(struct net_device *dev); ++ DHD_INFO(("%s: prio %d flowid %d\n", __FUNCTION__, prio, flowid)); + -+#if defined(MULTIPLE_SUPPLICANT) -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 -+extern struct mutex _dhd_sdio_mutex_lock_; -+#endif -+#endif /* MULTIPLE_SUPPLICANT */ ++ /* Tag the packet with flowid */ ++ DHD_PKTTAG_SET_FLOWID((dhd_pkttag_fr_t *)PKTTAG(pktbuf), flowid); ++ return BCME_OK; ++} + -+typedef enum dhd_attach_states ++void ++dhd_flowid_free(dhd_pub_t *dhdp, uint8 ifindex, uint16 flowid) +{ -+ DHD_ATTACH_STATE_INIT = 0x0, -+ DHD_ATTACH_STATE_NET_ALLOC = 0x1, -+ DHD_ATTACH_STATE_DHD_ALLOC = 0x2, -+ DHD_ATTACH_STATE_ADD_IF = 0x4, -+ DHD_ATTACH_STATE_PROT_ATTACH = 0x8, -+ DHD_ATTACH_STATE_WL_ATTACH = 0x10, -+ DHD_ATTACH_STATE_THREADS_CREATED = 0x20, -+ DHD_ATTACH_STATE_WAKELOCKS_INIT = 0x40, -+ DHD_ATTACH_STATE_CFG80211 = 0x80, -+ DHD_ATTACH_STATE_EARLYSUSPEND_DONE = 0x100, -+ DHD_ATTACH_STATE_DONE = 0x200 -+} dhd_attach_states_t; ++ int hashix; ++ bool found = FALSE; ++ flow_hash_info_t *cur, *prev; ++ if_flow_lkup_t *if_flow_lkup; ++ unsigned long flags; + -+/* Value -1 means we are unsuccessful in creating the kthread. */ -+#define DHD_PID_KT_INVALID -1 -+/* Value -2 means we are unsuccessful in both creating the kthread and tasklet */ -+#define DHD_PID_KT_TL_INVALID -2 ++ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); ++ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; + -+/* -+ * Exported from dhd OS modules (dhd_linux/dhd_ndis) -+ */ ++ for (hashix = 0; hashix < DHD_FLOWRING_HASH_SIZE; hashix++) { + -+/* Indication from bus module regarding presence/insertion of dongle. -+ * Return dhd_pub_t pointer, used as handle to OS module in later calls. -+ * Returned structure should have bus and prot pointers filled in. -+ * bus_hdrlen specifies required headroom for bus module header. -+ */ -+extern dhd_pub_t *dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen); -+#if defined(WLP2P) && defined(WL_CFG80211) -+/* To allow attach/detach calls corresponding to p2p0 interface */ -+extern int dhd_attach_p2p(dhd_pub_t *); -+extern int dhd_detach_p2p(dhd_pub_t *); -+#endif /* WLP2P && WL_CFG80211 */ -+extern int dhd_register_if(dhd_pub_t *dhdp, int idx, bool need_rtnl_lock); ++ cur = if_flow_lkup[ifindex].fl_hash[hashix]; + -+/* Indication from bus module regarding removal/absence of dongle */ -+extern void dhd_detach(dhd_pub_t *dhdp); -+extern void dhd_free(dhd_pub_t *dhdp); -+extern void dhd_clear(dhd_pub_t *dhdp); ++ if (cur) { ++ if (cur->flowid == flowid) { ++ found = TRUE; ++ } + -+/* Indication from bus module to change flow-control state */ -+extern void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool on); ++ prev = NULL; ++ while (!found && cur) { ++ if (cur->flowid == flowid) { ++ found = TRUE; ++ break; ++ } ++ prev = cur; ++ cur = cur->next; ++ } ++ if (found) { ++ if (!prev) { ++ if_flow_lkup[ifindex].fl_hash[hashix] = cur->next; ++ } else { ++ prev->next = cur->next; ++ } + -+/* Store the status of a connection attempt for later retrieval by an iovar */ -+extern void dhd_store_conn_status(uint32 event, uint32 status, uint32 reason); ++ /* deregister flowid from dhd_pub. */ ++ dhd_del_flowid(dhdp, ifindex, flowid); + -+extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec); ++ id16_map_free(dhdp->flowid_allocator, flowid); ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); ++ MFREE(dhdp->osh, cur, sizeof(flow_hash_info_t)); + -+/* Receive frame for delivery to OS. Callee disposes of rxp. */ -+extern void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *rxp, int numpkt, uint8 chan); ++ return; ++ } ++ } ++ } + -+/* Return pointer to interface name */ -+extern char *dhd_ifname(dhd_pub_t *dhdp, int idx); ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); ++ DHD_ERROR(("%s: could not free flow ring hash entry flowid %d\n", ++ __FUNCTION__, flowid)); ++} + -+/* Request scheduling of the bus dpc */ -+extern void dhd_sched_dpc(dhd_pub_t *dhdp); + -+/* Notify tx completion */ -+extern void dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success); ++/* Delete all Flow rings assocaited with the given Interface */ ++void ++dhd_flow_rings_delete(dhd_pub_t *dhdp, uint8 ifindex) ++{ ++ uint32 id; ++ flow_ring_table_t *flow_ring_table; + -+/* OS independent layer functions */ -+extern int dhd_os_proto_block(dhd_pub_t * pub); -+extern int dhd_os_proto_unblock(dhd_pub_t * pub); -+extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition, bool * pending); -+extern int dhd_os_ioctl_resp_wake(dhd_pub_t * pub); -+extern unsigned int dhd_os_get_ioctl_resp_timeout(void); -+extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec); ++ DHD_INFO(("%s: ifindex %u\n", __FUNCTION__, ifindex)); + -+extern int dhd_os_get_image_block(char * buf, int len, void * image); -+extern void * dhd_os_open_image(char * filename); -+extern void dhd_os_close_image(void * image); -+extern void dhd_os_wd_timer(void *bus, uint wdtick); -+extern void dhd_os_sdlock(dhd_pub_t * pub); -+extern void dhd_os_sdunlock(dhd_pub_t * pub); -+extern void dhd_os_sdlock_txq(dhd_pub_t * pub); -+extern void dhd_os_sdunlock_txq(dhd_pub_t * pub); -+extern void dhd_os_sdlock_rxq(dhd_pub_t * pub); -+extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub); -+extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub); -+#ifdef DHDTCPACK_SUPPRESS -+extern void dhd_os_tcpacklock(dhd_pub_t *pub); -+extern void dhd_os_tcpackunlock(dhd_pub_t *pub); -+#endif /* DHDTCPACK_SUPPRESS */ ++ ASSERT(ifindex < DHD_MAX_IFS); ++ if (ifindex >= DHD_MAX_IFS) ++ return; + -+extern int dhd_customer_oob_irq_map(void *adapter, unsigned long *irq_flags_ptr); -+extern int dhd_customer_gpio_wlan_ctrl(void *adapter, int onoff); -+extern int dhd_custom_get_mac_address(void *adapter, unsigned char *buf); -+extern void get_customized_country_code(void *adapter, char *country_iso_code, wl_country_t *cspec); -+extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub); -+extern void dhd_os_sdlock_eventq(dhd_pub_t * pub); -+extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub); -+extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret); -+extern int dhd_os_send_hang_message(dhd_pub_t *dhdp); -+extern void dhd_set_version_info(dhd_pub_t *pub, char *fw); -+extern bool dhd_os_check_if_up(dhd_pub_t *pub); -+extern int dhd_os_check_wakelock(dhd_pub_t *pub); -+extern int dhd_os_check_wakelock_all(dhd_pub_t *pub); -+extern int dhd_get_instance(dhd_pub_t *pub); -+#ifdef CUSTOM_SET_CPUCORE -+extern void dhd_set_cpucore(dhd_pub_t *dhd, int set); -+#endif /* CUSTOM_SET_CPUCORE */ ++ if (!dhdp->flow_ring_table) ++ return; + -+#if defined(KEEP_ALIVE) -+extern int dhd_keep_alive_onoff(dhd_pub_t *dhd); -+#endif /* KEEP_ALIVE */ ++ flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table; ++ for (id = 0; id < dhdp->num_flow_rings; id++) { ++ if (flow_ring_table[id].active && ++ (flow_ring_table[id].flow_info.ifindex == ifindex) && ++ (flow_ring_table[id].status != FLOW_RING_STATUS_DELETE_PENDING)) { ++ DHD_INFO(("%s: deleting flowid %d\n", ++ __FUNCTION__, flow_ring_table[id].flowid)); ++ dhd_bus_flow_ring_delete_request(dhdp->bus, ++ (void *) &flow_ring_table[id]); ++ } ++ } ++} + -+#ifdef SUPPORT_AP_POWERSAVE -+extern int dhd_set_ap_powersave(dhd_pub_t *dhdp, int ifidx, int enable); -+#endif ++/* Delete flow/s for given peer address */ ++void ++dhd_flow_rings_delete_for_peer(dhd_pub_t *dhdp, uint8 ifindex, char *addr) ++{ ++ uint32 id; ++ flow_ring_table_t *flow_ring_table; + ++ DHD_ERROR(("%s: ifindex %u\n", __FUNCTION__, ifindex)); + -+#ifdef PKT_FILTER_SUPPORT -+#define DHD_UNICAST_FILTER_NUM 0 -+#define DHD_BROADCAST_FILTER_NUM 1 -+#define DHD_MULTICAST4_FILTER_NUM 2 -+#define DHD_MULTICAST6_FILTER_NUM 3 -+#define DHD_MDNS_FILTER_NUM 4 -+#define DHD_ARP_FILTER_NUM 5 ++ ASSERT(ifindex < DHD_MAX_IFS); ++ if (ifindex >= DHD_MAX_IFS) ++ return; + -+#if defined(CUSTOM_PLATFORM_NV_TEGRA) -+/* Port based packet filtering command actions */ -+#define PKT_FILTER_PORTS_CLEAR 0 -+#define PKT_FILTER_PORTS_ADD 1 -+#define PKT_FILTER_PORTS_DEL 2 -+#define PKT_FILTER_PORTS_LOOPBACK 3 -+#define PKT_FILTER_PORTS_MAX PKT_FILTER_PORTS_LOOPBACK -+#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */ ++ if (!dhdp->flow_ring_table) ++ return; + -+extern int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val); -+extern void dhd_enable_packet_filter(int value, dhd_pub_t *dhd); -+extern int net_os_enable_packet_filter(struct net_device *dev, int val); -+extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); -+#if defined(CUSTOM_PLATFORM_NV_TEGRA) -+extern void dhd_set_packet_filter_mode(struct net_device *dev, char *command); -+extern int dhd_set_packet_filter_ports(struct net_device *dev, char *command); -+#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */ -+#endif /* PKT_FILTER_SUPPORT */ ++ flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table; ++ for (id = 0; id < dhdp->num_flow_rings; id++) { ++ if (flow_ring_table[id].active && ++ (flow_ring_table[id].flow_info.ifindex == ifindex) && ++ (!memcmp(flow_ring_table[id].flow_info.da, addr, ETHER_ADDR_LEN)) && ++ (flow_ring_table[id].status != FLOW_RING_STATUS_DELETE_PENDING)) { ++ DHD_INFO(("%s: deleting flowid %d\n", ++ __FUNCTION__, flow_ring_table[id].flowid)); ++ dhd_bus_flow_ring_delete_request(dhdp->bus, ++ (void *) &flow_ring_table[id]); ++ } ++ } ++} + -+extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd); -+extern bool dhd_support_sta_mode(dhd_pub_t *dhd); ++/* Handle Interface ADD, DEL operations */ ++void ++dhd_update_interface_flow_info(dhd_pub_t *dhdp, uint8 ifindex, ++ uint8 op, uint8 role) ++{ ++ if_flow_lkup_t *if_flow_lkup; ++ unsigned long flags; + -+#ifdef DHD_DEBUG -+extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size); -+#endif /* DHD_DEBUG */ ++ ASSERT(ifindex < DHD_MAX_IFS); ++ if (ifindex >= DHD_MAX_IFS) ++ return; + -+typedef struct { -+ uint32 limit; /* Expiration time (usec) */ -+ uint32 increment; /* Current expiration increment (usec) */ -+ uint32 elapsed; /* Current elapsed time (usec) */ -+ uint32 tick; /* O/S tick time (usec) */ -+} dhd_timeout_t; ++ DHD_INFO(("%s: ifindex %u op %u role is %u \n", ++ __FUNCTION__, ifindex, op, role)); ++ if (!dhdp->flowid_allocator) { ++ DHD_ERROR(("%s: Flow ring not intited yet \n", __FUNCTION__)); ++ return; ++ } + -+#ifdef SHOW_LOGTRACE -+typedef struct { -+ int num_fmts; -+ char **fmts; -+ char *raw_fmts; -+} dhd_event_log_t; -+#endif /* SHOW_LOGTRACE */ ++ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); ++ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; + -+extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec); -+extern int dhd_timeout_expired(dhd_timeout_t *tmo); ++ if (op == WLC_E_IF_ADD || op == WLC_E_IF_CHANGE) { + -+extern int dhd_ifname2idx(struct dhd_info *dhd, char *name); -+extern int dhd_ifidx2hostidx(struct dhd_info *dhd, int ifidx); -+extern int dhd_net2idx(struct dhd_info *dhd, struct net_device *net); -+extern struct net_device * dhd_idx2net(void *pub, int ifidx); -+extern int net_os_send_hang_message(struct net_device *dev); -+extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata, -+ wl_event_msg_t *, void **data_ptr, void *); -+extern void wl_event_to_host_order(wl_event_msg_t * evt); ++ if_flow_lkup[ifindex].role = role; + -+extern int dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len); -+extern int dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, -+ int ifindex); -+extern void dhd_common_init(osl_t *osh); ++ if (!(DHD_IF_ROLE_STA(role))) { ++ if_flow_lkup[ifindex].status = TRUE; ++ DHD_INFO(("%s: Mcast Flow ring for ifindex %d role is %d \n", ++ __FUNCTION__, ifindex, role)); ++ /* Create Mcast Flow */ ++ } ++ } else if (op == WLC_E_IF_DEL) { ++ if_flow_lkup[ifindex].status = FALSE; ++ DHD_INFO(("%s: cleanup all Flow rings for ifindex %d role is %d \n", ++ __FUNCTION__, ifindex, role)); ++ } ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); ++} + -+extern int dhd_do_driver_init(struct net_device *net); -+extern int dhd_event_ifadd(struct dhd_info *dhd, struct wl_event_data_if *ifevent, -+ char *name, uint8 *mac); -+extern int dhd_event_ifdel(struct dhd_info *dhd, struct wl_event_data_if *ifevent, -+ char *name, uint8 *mac); -+extern struct net_device* dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, char *name, -+ uint8 *mac, uint8 bssidx, bool need_rtnl_lock); -+extern int dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock); -+extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char * name); -+extern void dhd_vif_del(struct dhd_info *dhd, int ifidx); -+extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx); -+extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, uchar *cp, int len); ++/* Handle a STA interface link status update */ ++int ++dhd_update_interface_link_status(dhd_pub_t *dhdp, uint8 ifindex, uint8 status) ++{ ++ if_flow_lkup_t *if_flow_lkup; ++ unsigned long flags; + -+/* Send packet to dongle via data channel */ -+extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pkt); ++ ASSERT(ifindex < DHD_MAX_IFS); ++ if (ifindex >= DHD_MAX_IFS) ++ return BCME_BADARG; + -+/* send up locally generated event */ -+extern void dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data); -+/* Send event to host */ -+extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data); -+#ifdef LOG_INTO_TCPDUMP -+extern void dhd_sendup_log(dhd_pub_t *dhdp, void *data, int len); -+#endif /* LOG_INTO_TCPDUMP */ -+extern int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag); -+extern uint dhd_bus_status(dhd_pub_t *dhdp); -+extern int dhd_bus_start(dhd_pub_t *dhdp); -+extern int dhd_bus_suspend(dhd_pub_t *dhdpub); -+extern int dhd_bus_resume(dhd_pub_t *dhdpub, int stage); -+extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size); -+extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line); -+extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval); -+#if defined(BCMSDIO) || defined(BCMPCIE) -+extern uint dhd_bus_chip_id(dhd_pub_t *dhdp); -+extern uint dhd_bus_chiprev_id(dhd_pub_t *dhdp); -+extern uint dhd_bus_chippkg_id(dhd_pub_t *dhdp); -+#endif /* defined(BCMSDIO) || defined(BCMPCIE) */ ++ DHD_INFO(("%s: ifindex %d status %d\n", __FUNCTION__, ifindex, status)); + -+#if defined(KEEP_ALIVE) -+extern int dhd_keep_alive_onoff(dhd_pub_t *dhd); -+#endif /* KEEP_ALIVE */ ++ DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); ++ if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; + -+/* OS spin lock API */ -+extern void *dhd_os_spin_lock_init(osl_t *osh); -+extern void dhd_os_spin_lock_deinit(osl_t *osh, void *lock); -+extern unsigned long dhd_os_spin_lock(void *lock); -+void dhd_os_spin_unlock(void *lock, unsigned long flags); ++ if (DHD_IF_ROLE_STA(if_flow_lkup[ifindex].role)) { ++ if (status) ++ if_flow_lkup[ifindex].status = TRUE; ++ else ++ if_flow_lkup[ifindex].status = FALSE; ++ } ++ DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); + -+/* -+ * Manage sta objects in an interface. Interface is identified by an ifindex and -+ * sta(s) within an interfaces are managed using a MacAddress of the sta. -+ */ -+struct dhd_sta; -+extern struct dhd_sta *dhd_findadd_sta(void *pub, int ifidx, void *ea); -+extern void dhd_del_sta(void *pub, int ifidx, void *ea); -+extern int dhd_get_ap_isolate(dhd_pub_t *dhdp, uint32 idx); -+extern int dhd_set_ap_isolate(dhd_pub_t *dhdp, uint32 idx, int val); -+extern int dhd_bssidx2idx(dhd_pub_t *dhdp, uint32 bssidx); ++ return BCME_OK; ++} ++/* Update flow priority mapping */ ++int dhd_update_flow_prio_map(dhd_pub_t *dhdp, uint8 map) ++{ ++ uint16 flowid; ++ flow_ring_node_t *flow_ring_node; + -+extern bool dhd_is_concurrent_mode(dhd_pub_t *dhd); -+extern int dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set); -+typedef enum cust_gpio_modes { -+ WLAN_RESET_ON, -+ WLAN_RESET_OFF, -+ WLAN_POWER_ON, -+ WLAN_POWER_OFF -+} cust_gpio_modes_t; ++ if (map > DHD_FLOW_PRIO_TID_MAP) ++ return BCME_BADOPTION; + -+extern int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag); -+extern int wl_iw_send_priv_event(struct net_device *dev, char *flag); -+/* -+ * Insmod parameters for debug/test -+ */ ++ /* Check if we need to change prio map */ ++ if (map == dhdp->flow_prio_map_type) ++ return BCME_OK; + -+/* Watchdog timer interval */ -+extern uint dhd_watchdog_ms; ++ /* If any ring is active we cannot change priority mapping for flow rings */ ++ for (flowid = 0; flowid < dhdp->num_flow_rings; flowid++) { ++ flow_ring_node = DHD_FLOW_RING(dhdp, flowid); ++ if (flow_ring_node->active) ++ return BCME_EPERM; ++ } ++ /* Infor firmware about new mapping type */ ++ if (BCME_OK != dhd_flow_prio_map(dhdp, &map, TRUE)) ++ return BCME_ERROR; + -+#if defined(DHD_DEBUG) -+/* Console output poll interval */ -+extern uint dhd_console_ms; -+#endif /* defined(DHD_DEBUG) */ -+extern uint android_msg_level; -+extern uint config_msg_level; -+extern uint sd_msglevel; -+#ifdef WL_WIRELESS_EXT -+extern uint iw_msg_level; -+#endif -+#ifdef WL_CFG80211 -+extern uint wl_dbg_level; -+#endif ++ /* update internal structures */ ++ dhdp->flow_prio_map_type = map; ++ if (dhdp->flow_prio_map_type == DHD_FLOW_PRIO_TID_MAP) ++ bcopy(prio2tid, dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO); ++ else ++ bcopy(prio2ac, dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO); + -+#ifdef CUSTOMER_HW -+struct wifi_platform_data { -+ int (*set_power)(bool val); -+ int (*set_carddetect)(bool val); -+ void *(*mem_prealloc)(int section, unsigned long size); -+ int (*get_mac_addr)(unsigned char *buf); -+ void *(*get_country_code)(char *ccode); -+}; -+#endif ++ return BCME_OK; ++} + -+extern uint dhd_slpauto; ++/* Set/Get flwo ring priority map */ ++int dhd_flow_prio_map(dhd_pub_t *dhd, uint8 *map, bool set) ++{ ++ uint8 iovbuf[24]; ++ if (!set) { ++ bcm_mkiovar("bus:fl_prio_map", NULL, 0, (char*)iovbuf, sizeof(iovbuf)); ++ if (dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0) < 0) { ++ DHD_ERROR(("%s: failed to get fl_prio_map\n", __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ *map = iovbuf[0]; ++ return BCME_OK; ++ } ++ bcm_mkiovar("bus:fl_prio_map", (char *)map, 4, (char*)iovbuf, sizeof(iovbuf)); ++ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) { ++ DHD_ERROR(("%s: failed to set fl_prio_map \n", ++ __FUNCTION__)); ++ return BCME_ERROR; ++ } ++ return BCME_OK; ++} +diff --git a/drivers/net/wireless/bcm4336/dhd_flowring.h b/drivers/net/wireless/bcm4336/dhd_flowring.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_flowring.h +@@ -0,0 +1,159 @@ ++/* ++ * Header file describing the flow rings DHD interfaces. ++ * ++ * Provides type definitions and function prototypes used to create, delete and manage ++ * ++ * flow rings at high level ++ * ++ * $Copyright Open Broadcom Corporation$ ++ * ++ * $Id: dhd_flowrings.h jaganlv $ ++ */ + -+/* Use interrupts */ -+extern uint dhd_intr; ++/**************** ++ * Common types * ++ */ + -+/* Use polling */ -+extern uint dhd_poll; ++#ifndef _dhd_flowrings_h_ ++#define _dhd_flowrings_h_ + -+/* ARP offload agent mode */ -+extern uint dhd_arp_mode; ++/* Max pkts held in a flow ring's backup queue */ ++#define FLOW_RING_QUEUE_THRESHOLD (2048) + -+/* ARP offload enable */ -+extern uint dhd_arp_enable; ++/* Number of H2D common rings : PCIE Spec Rev? */ ++#define FLOW_RING_COMMON 2 + -+/* Pkt filte enable control */ -+extern uint dhd_pkt_filter_enable; ++#define FLOWID_INVALID (ID16_INVALID) ++#define FLOWID_RESERVED (FLOW_RING_COMMON) + -+/* Pkt filter init setup */ -+extern uint dhd_pkt_filter_init; ++#define FLOW_RING_STATUS_OPEN 0 ++#define FLOW_RING_STATUS_PENDING 1 ++#define FLOW_RING_STATUS_CLOSED 2 ++#define FLOW_RING_STATUS_DELETE_PENDING 3 ++#define FLOW_RING_STATUS_FLUSH_PENDING 4 + -+/* Pkt filter mode control */ -+extern uint dhd_master_mode; ++#define DHD_FLOWRING_RX_BUFPOST_PKTSZ 2048 + -+/* Roaming mode control */ -+extern uint dhd_roam_disable; ++#define DHD_FLOW_PRIO_AC_MAP 0 ++#define DHD_FLOW_PRIO_TID_MAP 1 + -+/* Roaming mode control */ -+extern uint dhd_radio_up; + -+/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */ -+extern int dhd_idletime; -+#ifdef DHD_USE_IDLECOUNT -+#define DHD_IDLETIME_TICKS 5 -+#else -+#define DHD_IDLETIME_TICKS 1 -+#endif /* DHD_USE_IDLECOUNT */ ++/* Pkttag not compatible with PROP_TXSTATUS or WLFC */ ++typedef struct dhd_pkttag_fr { ++ uint16 flowid; ++ int dataoff; ++} dhd_pkttag_fr_t; + -+/* SDIO Drive Strength */ -+extern uint dhd_sdiod_drive_strength; ++#define DHD_PKTTAG_SET_FLOWID(tag, flow) ((tag)->flowid = (uint16)(flow)) ++#define DHD_PKTTAG_SET_DATAOFF(tag, offset) ((tag)->dataoff = (int)(offset)) + -+/* Override to force tx queueing all the time */ -+extern uint dhd_force_tx_queueing; -+/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ -+#define DEFAULT_KEEP_ALIVE_VALUE 55000 /* msec */ -+#ifndef CUSTOM_KEEP_ALIVE_SETTING -+#define CUSTOM_KEEP_ALIVE_SETTING DEFAULT_KEEP_ALIVE_VALUE -+#endif /* DEFAULT_KEEP_ALIVE_VALUE */ ++#define DHD_PKTTAG_FLOWID(tag) ((tag)->flowid) ++#define DHD_PKTTAG_DATAOFF(tag) ((tag)->dataoff) + -+#define NULL_PKT_STR "null_pkt" ++/* Hashing a MacAddress for lkup into a per interface flow hash table */ ++#define DHD_FLOWRING_HASH_SIZE 256 ++#define DHD_FLOWRING_HASHINDEX(ea, prio) \ ++ ((((uint8 *)(ea))[3] ^ ((uint8 *)(ea))[4] ^ ((uint8 *)(ea))[5] ^ ((uint8)(prio))) \ ++ % DHD_FLOWRING_HASH_SIZE) + -+/* hooks for custom glom setting option via Makefile */ -+#define DEFAULT_GLOM_VALUE -1 -+#ifndef CUSTOM_GLOM_SETTING -+#define CUSTOM_GLOM_SETTING DEFAULT_GLOM_VALUE -+#endif -+#define WL_AUTO_ROAM_TRIGGER -75 -+/* hooks for custom Roaming Trigger setting via Makefile */ -+#define DEFAULT_ROAM_TRIGGER_VALUE -75 /* dBm default roam trigger all band */ -+#define DEFAULT_ROAM_TRIGGER_SETTING -1 -+#ifndef CUSTOM_ROAM_TRIGGER_SETTING -+#define CUSTOM_ROAM_TRIGGER_SETTING DEFAULT_ROAM_TRIGGER_VALUE -+#endif ++#define DHD_IF_ROLE(pub, idx) (((if_flow_lkup_t *)(pub)->if_flow_lkup)[idx].role) ++#define DHD_IF_ROLE_AP(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_AP) ++#define DHD_IF_ROLE_P2PGO(pub, idx) (DHD_IF_ROLE(pub, idx) == WLC_E_IF_ROLE_P2P_GO) ++#define DHD_FLOW_RING(dhdp, flowid) \ ++ (flow_ring_node_t *)&(((flow_ring_node_t *)((dhdp)->flow_ring_table))[flowid]) + -+/* hooks for custom Roaming Romaing setting via Makefile */ -+#define DEFAULT_ROAM_DELTA_VALUE 10 /* dBm default roam delta all band */ -+#define DEFAULT_ROAM_DELTA_SETTING -1 -+#ifndef CUSTOM_ROAM_DELTA_SETTING -+#define CUSTOM_ROAM_DELTA_SETTING DEFAULT_ROAM_DELTA_VALUE -+#endif ++struct flow_queue; + -+/* hooks for custom PNO Event wake lock to guarantee enough time -+ for the Platform to detect Event before system suspended -+*/ -+#define DEFAULT_PNO_EVENT_LOCK_xTIME 2 /* multiplay of DHD_PACKET_TIMEOUT_MS */ -+#ifndef CUSTOM_PNO_EVENT_LOCK_xTIME -+#define CUSTOM_PNO_EVENT_LOCK_xTIME DEFAULT_PNO_EVENT_LOCK_xTIME -+#endif -+/* hooks for custom dhd_dpc_prio setting option via Makefile */ -+#define DEFAULT_DHP_DPC_PRIO 1 -+#ifndef CUSTOM_DPC_PRIO_SETTING -+#define CUSTOM_DPC_PRIO_SETTING DEFAULT_DHP_DPC_PRIO -+#endif ++/* Flow Ring Queue Enqueue overflow callback */ ++typedef int (*flow_queue_cb_t)(struct flow_queue * queue, void * pkt); + -+#ifndef CUSTOM_LISTEN_INTERVAL -+#define CUSTOM_LISTEN_INTERVAL LISTEN_INTERVAL -+#endif /* CUSTOM_LISTEN_INTERVAL */ ++typedef struct flow_queue { ++ dll_t list; /* manage a flowring queue in a dll */ ++ void * head; /* first packet in the queue */ ++ void * tail; /* last packet in the queue */ ++ uint16 len; /* number of packets in the queue */ ++ uint16 max; /* maximum number of packets, queue may hold */ ++ uint32 failures; /* enqueue failures due to queue overflow */ ++ flow_queue_cb_t cb; /* callback invoked on threshold crossing */ ++} flow_queue_t; + -+#define DEFAULT_SUSPEND_BCN_LI_DTIM 3 -+#ifndef CUSTOM_SUSPEND_BCN_LI_DTIM -+#define CUSTOM_SUSPEND_BCN_LI_DTIM DEFAULT_SUSPEND_BCN_LI_DTIM -+#endif ++#define flow_queue_len(queue) ((int)(queue)->len) ++#define flow_queue_max(queue) ((int)(queue)->max) ++#define flow_queue_avail(queue) ((int)((queue)->max - (queue)->len)) ++#define flow_queue_full(queue) ((queue)->len >= (queue)->max) ++#define flow_queue_empty(queue) ((queue)->len == 0) + -+#ifndef CUSTOM_RXF_PRIO_SETTING -+#define CUSTOM_RXF_PRIO_SETTING MAX((CUSTOM_DPC_PRIO_SETTING - 1), 1) -+#endif ++typedef struct flow_info { ++ uint8 tid; ++ uint8 ifindex; ++ char sa[ETHER_ADDR_LEN]; ++ char da[ETHER_ADDR_LEN]; ++} flow_info_t; + -+#define DEFAULT_WIFI_TURNOFF_DELAY 0 -+#ifndef WIFI_TURNOFF_DELAY -+#define WIFI_TURNOFF_DELAY DEFAULT_WIFI_TURNOFF_DELAY -+#endif /* WIFI_TURNOFF_DELAY */ ++typedef struct flow_ring_node { ++ dll_t list; /* manage a constructed flowring in a dll, must be at first place */ ++ flow_queue_t queue; ++ bool active; ++ uint8 status; ++ uint16 flowid; ++ flow_info_t flow_info; ++ void *prot_info; ++ void *lock; /* lock for flowring access protection */ ++} flow_ring_node_t; ++typedef flow_ring_node_t flow_ring_table_t; + -+#define DEFAULT_WIFI_TURNON_DELAY 200 -+#ifndef WIFI_TURNON_DELAY -+#define WIFI_TURNON_DELAY DEFAULT_WIFI_TURNON_DELAY -+#endif /* WIFI_TURNON_DELAY */ ++typedef struct flow_hash_info { ++ uint16 flowid; ++ flow_info_t flow_info; ++ struct flow_hash_info *next; ++} flow_hash_info_t; + -+#ifdef BCMSDIO -+#define DEFAULT_DHD_WATCHDOG_INTERVAL_MS 10 /* msec */ -+#else -+#define DEFAULT_DHD_WATCHDOG_INTERVAL_MS 0 /* msec */ -+#endif -+#ifndef CUSTOM_DHD_WATCHDOG_MS -+#define CUSTOM_DHD_WATCHDOG_MS DEFAULT_DHD_WATCHDOG_INTERVAL_MS -+#endif /* DEFAULT_DHD_WATCHDOG_INTERVAL_MS */ ++typedef struct if_flow_lkup { ++ bool status; ++ uint8 role; /* Interface role: STA/AP */ ++ flow_hash_info_t *fl_hash[DHD_FLOWRING_HASH_SIZE]; /* Lkup Hash table */ ++} if_flow_lkup_t; + -+#ifdef WLTDLS -+#ifndef CUSTOM_TDLS_IDLE_MODE_SETTING -+#define CUSTOM_TDLS_IDLE_MODE_SETTING 60000 /* 60sec to tear down TDLS of not active */ -+#endif -+#ifndef CUSTOM_TDLS_RSSI_THRESHOLD_HIGH -+#define CUSTOM_TDLS_RSSI_THRESHOLD_HIGH -70 /* rssi threshold for establishing TDLS link */ -+#endif -+#ifndef CUSTOM_TDLS_RSSI_THRESHOLD_LOW -+#define CUSTOM_TDLS_RSSI_THRESHOLD_LOW -80 /* rssi threshold for tearing down TDLS link */ -+#endif -+#endif /* WLTDLS */ ++static INLINE flow_ring_node_t * ++dhd_constlist_to_flowring(dll_t *item) ++{ ++ return ((flow_ring_node_t *)item); ++} + -+#define DEFAULT_BCN_TIMEOUT 8 -+#ifndef CUSTOM_BCN_TIMEOUT -+#define CUSTOM_BCN_TIMEOUT DEFAULT_BCN_TIMEOUT -+#endif ++/* Exported API */ + -+#define MAX_DTIM_SKIP_BEACON_INTERVAL 100 /* max allowed associated AP beacon for DTIM skip */ -+#ifndef MAX_DTIM_ALLOWED_INTERVAL -+#define MAX_DTIM_ALLOWED_INTERVAL 600 /* max allowed total beacon interval for DTIM skip */ -+#endif -+#define NO_DTIM_SKIP 1 -+#ifdef SDTEST -+/* Echo packet generator (SDIO), pkts/s */ -+extern uint dhd_pktgen; ++/* Flow ring's queue management functions */ ++extern void dhd_flow_queue_init(dhd_pub_t *dhdp, flow_queue_t *queue, int max); ++extern void dhd_flow_queue_register(flow_queue_t *queue, flow_queue_cb_t cb); ++extern int dhd_flow_queue_enqueue(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt); ++extern void * dhd_flow_queue_dequeue(dhd_pub_t *dhdp, flow_queue_t *queue); ++extern void dhd_flow_queue_reinsert(dhd_pub_t *dhdp, flow_queue_t *queue, void *pkt); + -+/* Echo packet len (0 => sawtooth, max 1800) */ -+extern uint dhd_pktgen_len; -+#define MAX_PKTGEN_LEN 1800 -+#endif ++extern int dhd_flow_rings_init(dhd_pub_t *dhdp, uint32 num_flow_rings); + ++extern void dhd_flow_rings_deinit(dhd_pub_t *dhdp); + -+/* optionally set by a module_param_string() */ -+#define MOD_PARAM_PATHLEN 2048 -+#define MOD_PARAM_INFOLEN 512 ++extern uint16 dhd_flowid_find(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, char *sa, char *da); + -+#ifdef SOFTAP -+extern char fw_path2[MOD_PARAM_PATHLEN]; -+#endif ++extern int dhd_flowid_update(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, ++ void *pktbuf); + -+/* Flag to indicate if we should download firmware on driver load */ -+extern uint dhd_download_fw_on_driverload; ++extern void dhd_flowid_free(dhd_pub_t *dhdp, uint8 ifindex, uint16 flowid); + ++extern void dhd_flow_rings_delete(dhd_pub_t *dhdp, uint8 ifindex); + -+extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar); -+extern void dhd_wait_event_wakeup(dhd_pub_t*dhd); ++extern void dhd_flow_rings_delete_for_peer(dhd_pub_t *dhdp, uint8 ifindex, ++ char *addr); + -+#define IFLOCK_INIT(lock) *lock = 0 -+#define IFLOCK(lock) while (InterlockedCompareExchange((lock), 1, 0)) \ -+ NdisStallExecution(1); -+#define IFUNLOCK(lock) InterlockedExchange((lock), 0) -+#define IFLOCK_FREE(lock) -+#define FW_SUPPORTED(dhd, capa) ((strstr(dhd->fw_capabilities, #capa) != NULL)) -+#ifdef ARP_OFFLOAD_SUPPORT -+#define MAX_IPV4_ENTRIES 8 -+void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode); -+void dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable); ++/* Handle Interface ADD, DEL operations */ ++extern void dhd_update_interface_flow_info(dhd_pub_t *dhdp, uint8 ifindex, ++ uint8 op, uint8 role); + -+/* dhd_commn arp offload wrapers */ -+void dhd_aoe_hostip_clr(dhd_pub_t *dhd, int idx); -+void dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx); -+int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx); -+void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx); -+#endif /* ARP_OFFLOAD_SUPPORT */ -+#ifdef WLTDLS -+int dhd_tdls_enable(struct net_device *dev, bool tdls_on, bool auto_on, struct ether_addr *mac); -+#ifdef PCIE_FULL_DONGLE -+void dhd_tdls_update_peer_info(struct net_device *dev, bool connect_disconnect, uint8 *addr); -+#endif /* PCIE_FULL_DONGLE */ -+#endif /* WLTDLS */ -+/* Neighbor Discovery Offload Support */ -+int dhd_ndo_enable(dhd_pub_t * dhd, int ndo_enable); -+int dhd_ndo_add_ip(dhd_pub_t *dhd, char* ipaddr, int idx); -+int dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx); -+/* ioctl processing for nl80211 */ -+int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, struct dhd_ioctl *ioc, void *data_buf); ++/* Handle a STA interface link status update */ ++extern int dhd_update_interface_link_status(dhd_pub_t *dhdp, uint8 ifindex, ++ uint8 status); ++extern int dhd_flow_prio_map(dhd_pub_t *dhd, uint8 *map, bool set); ++extern int dhd_update_flow_prio_map(dhd_pub_t *dhdp, uint8 map); + -+void dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path, char *pconf_path); -+void dhd_set_bus_state(void *bus, uint32 state); ++extern uint8 dhd_flow_rings_ifindex2role(dhd_pub_t *dhdp, uint8 ifindex); ++#endif /* _dhd_flowrings_h_ */ +diff --git a/drivers/net/wireless/bcm4336/dhd_gpio.c b/drivers/net/wireless/bcm4336/dhd_gpio.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_gpio.c +@@ -0,0 +1,148 @@ ++#ifdef CUSTOMER_HW ++#include ++#include ++#include + -+/* Remove proper pkts(either one no-frag pkt or whole fragmented pkts) */ -+typedef int (*f_droppkt_t)(dhd_pub_t *dhdp, int prec, void* p, bool bPktInQ); -+extern bool dhd_prec_drop_pkts(dhd_pub_t *dhdp, struct pktq *pq, int prec, f_droppkt_t fn); ++#include "ap621x.h" + -+#ifdef PROP_TXSTATUS -+int dhd_os_wlfc_block(dhd_pub_t *pub); -+int dhd_os_wlfc_unblock(dhd_pub_t *pub); -+extern const uint8 prio2fifo[]; -+#endif /* PROP_TXSTATUS */ ++struct wifi_platform_data dhd_wlan_control = {0}; + -+uint8* dhd_os_prealloc(dhd_pub_t *dhdpub, int section, uint size, bool kmalloc_if_fail); -+void dhd_os_prefree(dhd_pub_t *dhdpub, void *addr, uint size); ++/* nanopi: irq and flags are read from OF dtb, see read_brcm_nanopi_irq() */ ++#if defined(CUSTOMER_OOB) && !defined(CONFIG_ARCH_S5P6818) ++uint bcm_wlan_get_oob_irq(void) ++{ ++ uint host_oob_irq = 0; + -+int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost); ++#ifdef GPIO_WLAN_HOST_WAKE ++ printf("GPIO(GPIO_WLAN_HOST_WAKE) = %d\n", brcm_gpio_host_wake()); ++ host_oob_irq = gpio_to_irq(brcm_gpio_host_wake()); ++ gpio_direction_input(brcm_gpio_host_wake()); ++#elif defined(CONFIG_ARCH_CPU_SLSI) ++ host_oob_irq = get_host_wake_irq(); ++#endif + -+#if defined(CONFIG_DHD_USE_STATIC_BUF) -+#define DHD_OS_PREALLOC(dhdpub, section, size) dhd_os_prealloc(dhdpub, section, size, FALSE) -+#define DHD_OS_PREFREE(dhdpub, addr, size) dhd_os_prefree(dhdpub, addr, size) ++ printf("host_oob_irq: %d\n", host_oob_irq); ++ return host_oob_irq; ++} ++ ++uint bcm_wlan_get_oob_irq_flags(void) ++{ ++ uint host_oob_irq_flags = 0; ++ ++#if defined(GPIO_WLAN_HOST_WAKE) || defined(CONFIG_ARCH_S5P6818) ++#ifdef HW_OOB ++ host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE; +#else -+#define DHD_OS_PREALLOC(dhdpub, section, size) MALLOC(dhdpub->osh, size) -+#define DHD_OS_PREFREE(dhdpub, addr, size) MFREE(dhdpub->osh, addr, size) -+#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */ ++ host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_SHAREABLE; ++#endif ++#endif ++ printf("host_oob_irq_flags = %x\n", host_oob_irq_flags); + ++ return host_oob_irq_flags; ++} ++#endif + -+#define dhd_add_flowid(pub, ifidx, ac_prio, ea, flowid) do {} while (0) -+#define dhd_del_flowid(pub, ifidx, flowid) do {} while (0) ++int bcm_wlan_set_power(bool on) ++{ ++ int err = 0; + -+extern unsigned long dhd_os_general_spin_lock(dhd_pub_t *pub); -+extern void dhd_os_general_spin_unlock(dhd_pub_t *pub, unsigned long flags); ++ if (on) { ++ printf("======== PULL WL_REG_ON HIGH! ========\n"); ++#ifdef GPIO_WLAN_EN ++ gpio_set_value(GPIO_WLAN_EN, 1); ++#elif defined(CONFIG_ARCH_S5P6818) ++ /* nanopi: the function sets high/low value on gpiob-24 pin, which is ++ * connected with WL_REG_ON pin on ap6212. ++ * When set to low, WLAN section of the chip is powered off and ++ * set in reset state. In this case the chip becomes also unresponsive ++ * on SDIO interface. But we don't want to interfere with mmc driver... ++ */ ++ //wifi_pm_gpio_ctrl("bcmdhd", 1); ++#endif ++ /* Lets customer power to get stable */ ++ msleep(50); ++ } else { ++ printf("======== PULL WL_REG_ON LOW! ========\n"); ++#ifdef GPIO_WLAN_EN ++ gpio_set_value(GPIO_WLAN_EN, 0); ++#elif defined(CONFIG_ARCH_S5P6818) ++ // wifi_pm_gpio_ctrl("bcmdhd", 0); ++#endif ++ msleep(50); ++ } + -+/** Miscellaenous DHD Spin Locks */ ++ return err; ++} + -+/* Disable router 3GMAC bypass path perimeter lock */ -+#define DHD_PERIM_LOCK(dhdp) do {} while (0) -+#define DHD_PERIM_UNLOCK(dhdp) do {} while (0) ++int bcm_wlan_set_carddetect(bool present) ++{ ++ int err = 0; + -+/* Enable DHD general spin lock/unlock */ -+#define DHD_GENERAL_LOCK(dhdp, flags) \ -+ (flags) = dhd_os_general_spin_lock(dhdp) -+#define DHD_GENERAL_UNLOCK(dhdp, flags) \ -+ dhd_os_general_spin_unlock((dhdp), (flags)) ++#if 0 ++ if (present) { ++ printf("======== Card detection to detect SDIO card! ========\n"); ++ err = sdhci_s3c_force_presence_change(&sdmmc_channel, 1); ++ } else { ++ printf("======== Card detection to remove SDIO card! ========\n"); ++ err = sdhci_s3c_force_presence_change(&sdmmc_channel, 0); ++ } ++#endif + -+/* Enable DHD flowring spin lock/unlock */ -+#define DHD_FLOWRING_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) -+#define DHD_FLOWRING_UNLOCK(lock, flags) dhd_os_spin_unlock((lock), (flags)) ++#if defined(CONFIG_ARCH_S5P6818) ++ /* nanopi: kernel 3.x has added method in MMC driver ++ * which mimics insertion/removal of SD card. ++ * The function is used after pull WL_REG_ON pin low/high. ++ */ ++ //force_presence_change(NULL, present); ++#else ++ mmc_force_presence_change_onoff(&sdmmc_channel, present); ++#endif + -+/* Enable DHD common flowring info spin lock/unlock */ -+#define DHD_FLOWID_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) -+#define DHD_FLOWID_UNLOCK(lock, flags) dhd_os_spin_unlock((lock), (flags)) ++ return err; ++} + ++int bcm_wlan_get_mac_address(unsigned char *buf) ++{ ++ int err = 0; + ++ printf("======== %s ========\n", __FUNCTION__); ++#ifdef EXAMPLE_GET_MAC ++ /* EXAMPLE code */ ++ { ++ struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}}; ++ bcopy((char *)&ea_example, buf, sizeof(struct ether_addr)); ++ } ++#endif /* EXAMPLE_GET_MAC */ + -+typedef struct wl_io_pport { -+ dhd_pub_t *dhd_pub; -+ uint ifidx; -+} wl_io_pport_t; ++ return err; ++} + -+extern void *dhd_pub_wlinfo(dhd_pub_t *dhd_pub); -+#ifdef CONFIG_MACH_UNIVERSAL5433 -+extern int check_rev(void); ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++extern void *bcmdhd_mem_prealloc(int section, unsigned long size); ++void* bcm_wlan_prealloc(int section, unsigned long size) ++{ ++ void *alloc_ptr = NULL; ++ alloc_ptr = bcmdhd_mem_prealloc(section, size); ++ if (alloc_ptr) { ++ printf("success alloc section %d, size %ld\n", section, size); ++ if (size != 0L) ++ bzero(alloc_ptr, size); ++ return alloc_ptr; ++ } ++ printf("can't alloc section %d\n", section); ++ return NULL; ++} +#endif -+#endif /* _dhd_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_ip.c b/drivers/net/wireless/bcm4336/dhd_ip.c ---- a/drivers/net/wireless/bcm4336/dhd_ip.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_ip.c 2018-05-06 08:49:50.622754012 +0200 ++ ++int bcm_wlan_set_plat_data(void) { ++ printf("======== %s ========\n", __FUNCTION__); ++ dhd_wlan_control.set_power = bcm_wlan_set_power; ++ dhd_wlan_control.set_carddetect = bcm_wlan_set_carddetect; ++ dhd_wlan_control.get_mac_addr = bcm_wlan_get_mac_address; ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ dhd_wlan_control.mem_prealloc = bcm_wlan_prealloc; ++#endif ++ return 0; ++} ++ ++#endif /* CUSTOMER_HW */ +diff --git a/drivers/net/wireless/bcm4336/dhd_ip.c b/drivers/net/wireless/bcm4336/dhd_ip.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_ip.c @@ -0,0 +1,1285 @@ +/* + * IP Packet Parser Module. @@ -136757,9 +138218,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_ip.c b/drivers/net/wireless/bcm4 + return hold; +} +#endif /* DHDTCPACK_SUPPRESS */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_ip.h b/drivers/net/wireless/bcm4336/dhd_ip.h ---- a/drivers/net/wireless/bcm4336/dhd_ip.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_ip.h 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_ip.h b/drivers/net/wireless/bcm4336/dhd_ip.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_ip.h @@ -0,0 +1,58 @@ +/* + * Header file describing the common ip parser function. @@ -136819,9 +138282,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_ip.h b/drivers/net/wireless/bcm4 +#endif /* DHDTCPACK_SUPPRESS */ + +#endif /* _dhd_ip_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux.c b/drivers/net/wireless/bcm4336/dhd_linux.c ---- a/drivers/net/wireless/bcm4336/dhd_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_linux.c 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_linux.c b/drivers/net/wireless/bcm4336/dhd_linux.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_linux.c @@ -0,0 +1,10363 @@ +/* + * Broadcom Dongle Host Driver (DHD), Linux-specific network interface @@ -147186,9 +148651,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux.c b/drivers/net/wireless/b + else + return NULL; +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux.h b/drivers/net/wireless/bcm4336/dhd_linux.h ---- a/drivers/net/wireless/bcm4336/dhd_linux.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_linux.h 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_linux.h b/drivers/net/wireless/bcm4336/dhd_linux.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_linux.h @@ -0,0 +1,82 @@ +/* + * DHD Linux header file (dhd_linux exports for cfg80211 and other components) @@ -147272,9 +148739,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux.h b/drivers/net/wireless/b +dhd_wmf_t* dhd_wmf_conf(dhd_pub_t *dhdp, uint32 idx); +#endif /* DHD_WMF */ +#endif /* __DHD_LINUX_H__ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux_platdev.c b/drivers/net/wireless/bcm4336/dhd_linux_platdev.c ---- a/drivers/net/wireless/bcm4336/dhd_linux_platdev.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_linux_platdev.c 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_linux_platdev.c b/drivers/net/wireless/bcm4336/dhd_linux_platdev.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_linux_platdev.c @@ -0,0 +1,864 @@ +/* + * Linux platform device for DHD WLAN adapter @@ -148140,9 +149609,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux_platdev.c b/drivers/net/wi + + return err; +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux_sched.c b/drivers/net/wireless/bcm4336/dhd_linux_sched.c ---- a/drivers/net/wireless/bcm4336/dhd_linux_sched.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_linux_sched.c 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_linux_sched.c b/drivers/net/wireless/bcm4336/dhd_linux_sched.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_linux_sched.c @@ -0,0 +1,30 @@ +/* + * Expose some of the kernel scheduler routines @@ -148174,9 +149645,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux_sched.c b/drivers/net/wire +#endif /* LinuxVer */ + return rc; +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux_wq.c b/drivers/net/wireless/bcm4336/dhd_linux_wq.c ---- a/drivers/net/wireless/bcm4336/dhd_linux_wq.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_linux_wq.c 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_linux_wq.c b/drivers/net/wireless/bcm4336/dhd_linux_wq.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_linux_wq.c @@ -0,0 +1,299 @@ +/* + * Broadcom Dongle Host Driver (DHD), Generic work queue framework @@ -148477,9 +149950,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux_wq.c b/drivers/net/wireles + } while (1); + return; +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux_wq.h b/drivers/net/wireless/bcm4336/dhd_linux_wq.h ---- a/drivers/net/wireless/bcm4336/dhd_linux_wq.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_linux_wq.h 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_linux_wq.h b/drivers/net/wireless/bcm4336/dhd_linux_wq.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_linux_wq.h @@ -0,0 +1,46 @@ +/* + * Broadcom Dongle Host Driver (DHD), Generic work queue framework @@ -148527,9 +150002,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_linux_wq.h b/drivers/net/wireles +int dhd_deferred_schedule_work(void *workq, void *event_data, u8 event, + event_handler_t evt_handler, u8 priority); +#endif /* _dhd_linux_wq_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_log.c b/drivers/net/wireless/bcm4336/dhd_log.c ---- a/drivers/net/wireless/bcm4336/dhd_log.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_log.c 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_log.c b/drivers/net/wireless/bcm4336/dhd_log.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_log.c @@ -0,0 +1,58 @@ +/* + * DHD logging module for internal debug @@ -148589,9 +150066,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_log.c b/drivers/net/wireless/bcm + } +#endif /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_msgbuf.c b/drivers/net/wireless/bcm4336/dhd_msgbuf.c ---- a/drivers/net/wireless/bcm4336/dhd_msgbuf.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_msgbuf.c 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_msgbuf.c b/drivers/net/wireless/bcm4336/dhd_msgbuf.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_msgbuf.c @@ -0,0 +1,4189 @@ +/* + * Header file describing the internal (inter-module) DHD interfaces. @@ -152782,9 +154261,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_msgbuf.c b/drivers/net/wireless/ + dhd_flow_rings_deinit(dhd); + NATIVE_TO_PKTID_CLEAR(prot->pktid_map_handle); +} -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_pcie.c b/drivers/net/wireless/bcm4336/dhd_pcie.c ---- a/drivers/net/wireless/bcm4336/dhd_pcie.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_pcie.c 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_pcie.c b/drivers/net/wireless/bcm4336/dhd_pcie.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_pcie.c @@ -0,0 +1,4733 @@ +/* + * DHD Bus Module for PCIE @@ -157519,9 +159000,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_pcie.c b/drivers/net/wireless/bc + dhdpcie_oob_intr_set(dhdp->bus, enable); +} +#endif /* BCMPCIE_OOB_HOST_WAKE */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_pcie.h b/drivers/net/wireless/bcm4336/dhd_pcie.h ---- a/drivers/net/wireless/bcm4336/dhd_pcie.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_pcie.h 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_pcie.h b/drivers/net/wireless/bcm4336/dhd_pcie.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_pcie.h @@ -0,0 +1,207 @@ +/* + * Linux DHD Bus Module for PCIE @@ -157730,9 +159213,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_pcie.h b/drivers/net/wireless/bc + +extern int dhd_buzzz_dump_dngl(dhd_bus_t *bus); +#endif /* dhd_pcie_h */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_pcie_linux.c b/drivers/net/wireless/bcm4336/dhd_pcie_linux.c ---- a/drivers/net/wireless/bcm4336/dhd_pcie_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_pcie_linux.c 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_pcie_linux.c b/drivers/net/wireless/bcm4336/dhd_pcie_linux.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_pcie_linux.c @@ -0,0 +1,1315 @@ +/* + * Linux DHD Bus Module for PCIE @@ -159049,9 +160534,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_pcie_linux.c b/drivers/net/wirel + dhdpcie_osinfo->oob_irq_registered = FALSE; +} +#endif /* BCMPCIE_OOB_HOST_WAKE */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_pno.c b/drivers/net/wireless/bcm4336/dhd_pno.c ---- a/drivers/net/wireless/bcm4336/dhd_pno.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_pno.c 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_pno.c b/drivers/net/wireless/bcm4336/dhd_pno.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_pno.c @@ -0,0 +1,1874 @@ +/* + * Broadcom Dongle Host Driver (DHD) @@ -160927,9 +162414,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_pno.c b/drivers/net/wireless/bcm + return err; +} +#endif /* PNO_SUPPORT */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_pno.h b/drivers/net/wireless/bcm4336/dhd_pno.h ---- a/drivers/net/wireless/bcm4336/dhd_pno.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_pno.h 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_pno.h b/drivers/net/wireless/bcm4336/dhd_pno.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_pno.h @@ -0,0 +1,247 @@ +/* + * Header file of Broadcom Dongle Host Driver (DHD) @@ -161178,9 +162667,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_pno.h b/drivers/net/wireless/bcm +#endif /* #if defined(PNO_SUPPORT) */ +#endif /* #if defined(NDISVER) */ +#endif /* __DHD_PNO_H__ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_proto.h b/drivers/net/wireless/bcm4336/dhd_proto.h ---- a/drivers/net/wireless/bcm4336/dhd_proto.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_proto.h 2018-05-06 08:49:50.622754012 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_proto.h b/drivers/net/wireless/bcm4336/dhd_proto.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_proto.h @@ -0,0 +1,127 @@ +/* + * Header file describing the internal (inter-module) DHD interfaces. @@ -161309,9 +162800,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_proto.h b/drivers/net/wireless/b +#endif /* proto */ + +#endif /* _dhd_proto_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_sdio.c b/drivers/net/wireless/bcm4336/dhd_sdio.c ---- a/drivers/net/wireless/bcm4336/dhd_sdio.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_sdio.c 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_sdio.c b/drivers/net/wireless/bcm4336/dhd_sdio.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_sdio.c @@ -0,0 +1,8693 @@ +/* + * DHD Bus Module for SDIO @@ -170006,9 +171499,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_sdio.c b/drivers/net/wireless/bc + *idle_time = dhdp->bus->idletime; +} +#endif /* SOFTAP_TPUT_ENHANCE */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_static_buf.c b/drivers/net/wireless/bcm4336/dhd_static_buf.c ---- a/drivers/net/wireless/bcm4336/dhd_static_buf.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_static_buf.c 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_static_buf.c b/drivers/net/wireless/bcm4336/dhd_static_buf.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_static_buf.c @@ -0,0 +1,171 @@ +#include +#include @@ -170181,9 +171676,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_static_buf.c b/drivers/net/wirel +} + +__initcall(bcmdhd_wlan_init); -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_wlfc.c b/drivers/net/wireless/bcm4336/dhd_wlfc.c ---- a/drivers/net/wireless/bcm4336/dhd_wlfc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_wlfc.c 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_wlfc.c b/drivers/net/wireless/bcm4336/dhd_wlfc.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_wlfc.c @@ -0,0 +1,4094 @@ +/* + * DHD PROP_TXSTATUS Module. @@ -174279,9 +175776,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_wlfc.c b/drivers/net/wireless/bc + return BCME_OK; +} +#endif /* PROP_TXSTATUS */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_wlfc.h b/drivers/net/wireless/bcm4336/dhd_wlfc.h ---- a/drivers/net/wireless/bcm4336/dhd_wlfc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dhd_wlfc.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/dhd_wlfc.h b/drivers/net/wireless/bcm4336/dhd_wlfc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dhd_wlfc.h @@ -0,0 +1,505 @@ +/* +* $Copyright Open 2009 Broadcom Corporation$ @@ -174788,9 +176287,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dhd_wlfc.h b/drivers/net/wireless/bc +int dhd_wlfc_get_rxpkt_chk(dhd_pub_t *dhd, int *val); +int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val); +#endif /* __wlfc_host_driver_definitions_h__ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dngl_stats.h b/drivers/net/wireless/bcm4336/dngl_stats.h ---- a/drivers/net/wireless/bcm4336/dngl_stats.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dngl_stats.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/dngl_stats.h b/drivers/net/wireless/bcm4336/dngl_stats.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dngl_stats.h @@ -0,0 +1,25 @@ +/* + * Common stats definitions for clients of dongle @@ -174817,9 +176318,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dngl_stats.h b/drivers/net/wireless/ +} dngl_stats_t; + +#endif /* _dngl_stats_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/dngl_wlhdr.h b/drivers/net/wireless/bcm4336/dngl_wlhdr.h ---- a/drivers/net/wireless/bcm4336/dngl_wlhdr.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/dngl_wlhdr.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/dngl_wlhdr.h b/drivers/net/wireless/bcm4336/dngl_wlhdr.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/dngl_wlhdr.h @@ -0,0 +1,22 @@ +/* + * Dongle WL Header definitions @@ -174843,9 +176346,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/dngl_wlhdr.h b/drivers/net/wireless/ +#define WL_HEADER_TYPE 0 +#define WL_HEADER_VER 1 +#endif /* _dngl_wlhdr_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/hnd_pktpool.c b/drivers/net/wireless/bcm4336/hnd_pktpool.c ---- a/drivers/net/wireless/bcm4336/hnd_pktpool.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/hnd_pktpool.c 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/hnd_pktpool.c b/drivers/net/wireless/bcm4336/hnd_pktpool.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/hnd_pktpool.c @@ -0,0 +1,733 @@ +/* + * HND generic packet pool operation primitives @@ -175580,9 +177085,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/hnd_pktpool.c b/drivers/net/wireless + ASSERT(pktp); + return pktp->emptycb_disable; +} -diff -ENwbur a/drivers/net/wireless/bcm4336/hnd_pktq.c b/drivers/net/wireless/bcm4336/hnd_pktq.c ---- a/drivers/net/wireless/bcm4336/hnd_pktq.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/hnd_pktq.c 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/hnd_pktq.c b/drivers/net/wireless/bcm4336/hnd_pktq.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/hnd_pktq.c @@ -0,0 +1,586 @@ +/* + * HND generic pktq operation primitives @@ -176170,9 +177677,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/hnd_pktq.c b/drivers/net/wireless/bc + + return p; +} -diff -ENwbur a/drivers/net/wireless/bcm4336/hndpmu.c b/drivers/net/wireless/bcm4336/hndpmu.c ---- a/drivers/net/wireless/bcm4336/hndpmu.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/hndpmu.c 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/hndpmu.c b/drivers/net/wireless/bcm4336/hndpmu.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/hndpmu.c @@ -0,0 +1,291 @@ +/* + * Misc utility routines for accessing PMU corerev specific features @@ -176465,9 +177974,70 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/hndpmu.c b/drivers/net/wireless/bcm4 + drivestrength, str_tab[i].strength)); + } +} /* si_sdiod_drive_strength_init */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/aidmp.h b/drivers/net/wireless/bcm4336/include/aidmp.h ---- a/drivers/net/wireless/bcm4336/include/aidmp.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/aidmp.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/Makefile b/drivers/net/wireless/bcm4336/include/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/Makefile +@@ -0,0 +1,53 @@ ++#!/bin/bash ++# ++# This script serves following purpose: ++# ++# 1. It generates native version information by querying ++# automerger maintained database to see where src/include ++# came from ++# 2. For select components, as listed in compvers.sh ++# it generates component version files ++# ++# Copyright 2005, Broadcom, Inc. ++# ++# $Id: Makefile 347587 2012-07-27 09:13:31Z $ ++# ++ ++export SRCBASE:=.. ++ ++TARGETS := epivers.h ++ ++ifdef VERBOSE ++export VERBOSE ++endif ++ ++all release: epivers compvers ++ ++# Generate epivers.h for native branch url ++epivers: ++ bash epivers.sh ++ ++# Generate component versions based on component url ++compvers: ++ @if [ -s "compvers.sh" ]; then \ ++ echo "Generating component versions, if any"; \ ++ bash compvers.sh; \ ++ else \ ++ echo "Skipping component version generation"; \ ++ fi ++ ++# Generate epivers.h for native branch version ++clean_compvers: ++ @if [ -s "compvers.sh" ]; then \ ++ echo "bash compvers.sh clean"; \ ++ bash compvers.sh clean; \ ++ else \ ++ echo "Skipping component version clean"; \ ++ fi ++ ++clean: ++ rm -f $(TARGETS) *.prev ++ ++clean_all: clean clean_compvers ++ ++.PHONY: all release clean epivers compvers clean_compvers +diff --git a/drivers/net/wireless/bcm4336/include/aidmp.h b/drivers/net/wireless/bcm4336/include/aidmp.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/aidmp.h @@ -0,0 +1,368 @@ +/* + * Broadcom AMBA Interconnect definitions. @@ -176837,9 +178407,377 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/aidmp.h b/drivers/net/wirele +#define AI_OOBSEL_7_SHIFT 24 + +#endif /* _AIDMP_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmcdc.h b/drivers/net/wireless/bcm4336/include/bcmcdc.h ---- a/drivers/net/wireless/bcm4336/include/bcmcdc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmcdc.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcm_cfg.h b/drivers/net/wireless/bcm4336/include/bcm_cfg.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcm_cfg.h +@@ -0,0 +1,11 @@ ++/* ++ * BCM common config options ++ * ++ * $Copyright Open Broadcom Corporation$ ++ * ++ * $Id: bcm_cfg.h 351867 2012-08-21 18:46:16Z $ ++ */ ++ ++#ifndef _bcm_cfg_h_ ++#define _bcm_cfg_h_ ++#endif /* _bcm_cfg_h_ */ +diff --git a/drivers/net/wireless/bcm4336/include/bcm_mpool_pub.h b/drivers/net/wireless/bcm4336/include/bcm_mpool_pub.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcm_mpool_pub.h +@@ -0,0 +1,343 @@ ++/* ++ * Memory pools library, Public interface ++ * ++ * API Overview ++ * ++ * This package provides a memory allocation subsystem based on pools of ++ * homogenous objects. ++ * ++ * Instrumentation is available for reporting memory utilization both ++ * on a per-data-structure basis and system wide. ++ * ++ * There are two main types defined in this API. ++ * ++ * pool manager: A singleton object that acts as a factory for ++ * pool allocators. It also is used for global ++ * instrumentation, such as reporting all blocks ++ * in use across all data structures. The pool manager ++ * creates and provides individual memory pools ++ * upon request to application code. ++ * ++ * memory pool: An object for allocating homogenous memory blocks. ++ * ++ * Global identifiers in this module use the following prefixes: ++ * bcm_mpm_* Memory pool manager ++ * bcm_mp_* Memory pool ++ * ++ * There are two main types of memory pools: ++ * ++ * prealloc: The contiguous memory block of objects can either be supplied ++ * by the client or malloc'ed by the memory manager. The objects are ++ * allocated out of a block of memory and freed back to the block. ++ * ++ * heap: The memory pool allocator uses the heap (malloc/free) for memory. ++ * In this case, the pool allocator is just providing statistics ++ * and instrumentation on top of the heap, without modifying the heap ++ * allocation implementation. ++ * ++ * $Copyright Open Broadcom Corporation$ ++ * ++ * $Id: bcm_mpool_pub.h 407097 2013-06-11 18:43:16Z $ ++ */ ++ ++#ifndef _BCM_MPOOL_PUB_H ++#define _BCM_MPOOL_PUB_H 1 ++ ++#include /* needed for uint16 */ ++ ++ ++/* ++************************************************************************** ++* ++* Type definitions, handles ++* ++************************************************************************** ++*/ ++ ++/* Forward declaration of OSL handle. */ ++struct osl_info; ++ ++/* Forward declaration of string buffer. */ ++struct bcmstrbuf; ++ ++/* ++ * Opaque type definition for the pool manager handle. This object is used for global ++ * memory pool operations such as obtaining a new pool, deleting a pool, iterating and ++ * instrumentation/debugging. ++ */ ++struct bcm_mpm_mgr; ++typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h; ++ ++/* ++ * Opaque type definition for an instance of a pool. This handle is used for allocating ++ * and freeing memory through the pool, as well as management/instrumentation on this ++ * specific pool. ++ */ ++struct bcm_mp_pool; ++typedef struct bcm_mp_pool *bcm_mp_pool_h; ++ ++ ++/* ++ * To make instrumentation more readable, every memory ++ * pool must have a readable name. Pool names are up to ++ * 8 bytes including '\0' termination. (7 printable characters.) ++ */ ++#define BCM_MP_NAMELEN 8 ++ ++ ++/* ++ * Type definition for pool statistics. ++ */ ++typedef struct bcm_mp_stats { ++ char name[BCM_MP_NAMELEN]; /* Name of this pool. */ ++ unsigned int objsz; /* Object size allocated in this pool */ ++ uint16 nobj; /* Total number of objects in this pool */ ++ uint16 num_alloc; /* Number of objects currently allocated */ ++ uint16 high_water; /* Max number of allocated objects. */ ++ uint16 failed_alloc; /* Failed allocations. */ ++} bcm_mp_stats_t; ++ ++ ++/* ++************************************************************************** ++* ++* API Routines on the pool manager. ++* ++************************************************************************** ++*/ ++ ++/* ++ * bcm_mpm_init() - initialize the whole memory pool system. ++ * ++ * Parameters: ++ * osh: INPUT Operating system handle. Needed for heap memory allocation. ++ * max_pools: INPUT Maximum number of mempools supported. ++ * mgr: OUTPUT The handle is written with the new pools manager object/handle. ++ * ++ * Returns: ++ * BCME_OK Object initialized successfully. May be used. ++ * BCME_NOMEM Initialization failed due to no memory. Object must not be used. ++ */ ++int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp); ++ ++ ++/* ++ * bcm_mpm_deinit() - de-initialize the whole memory pool system. ++ * ++ * Parameters: ++ * mgr: INPUT Pointer to pool manager handle. ++ * ++ * Returns: ++ * BCME_OK Memory pool manager successfully de-initialized. ++ * other Indicated error occured during de-initialization. ++ */ ++int bcm_mpm_deinit(bcm_mpm_mgr_h *mgrp); ++ ++/* ++ * bcm_mpm_create_prealloc_pool() - Create a new pool for fixed size objects. The ++ * pool uses a contiguous block of pre-alloced ++ * memory. The memory block may either be provided ++ * by the client or dynamically allocated by the ++ * pool manager. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pool manager ++ * obj_sz: INPUT Size of objects that will be allocated by the new pool ++ * Must be >= sizeof(void *). ++ * nobj: INPUT Maximum number of concurrently existing objects to support ++ * memstart INPUT Pointer to the memory to use, or NULL to malloc() ++ * memsize INPUT Number of bytes referenced from memstart (for error checking). ++ * Must be 0 if 'memstart' is NULL. ++ * poolname INPUT For instrumentation, the name of the pool ++ * newp: OUTPUT The handle for the new pool, if creation is successful ++ * ++ * Returns: ++ * BCME_OK Pool created ok. ++ * other Pool not created due to indicated error. newpoolp set to NULL. ++ * ++ * ++ */ ++int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr, ++ unsigned int obj_sz, ++ int nobj, ++ void *memstart, ++ unsigned int memsize, ++ const char poolname[BCM_MP_NAMELEN], ++ bcm_mp_pool_h *newp); ++ ++ ++/* ++ * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after ++ * all memory objects have been freed back to the pool. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * pool: INPUT The handle of the pool to delete ++ * ++ * Returns: ++ * BCME_OK Pool deleted ok. ++ * other Pool not deleted due to indicated error. ++ * ++ */ ++int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); ++ ++/* ++ * bcm_mpm_create_heap_pool() - Create a new pool for fixed size objects. The memory ++ * pool allocator uses the heap (malloc/free) for memory. ++ * In this case, the pool allocator is just providing ++ * statistics and instrumentation on top of the heap, ++ * without modifying the heap allocation implementation. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pool manager ++ * obj_sz: INPUT Size of objects that will be allocated by the new pool ++ * poolname INPUT For instrumentation, the name of the pool ++ * newp: OUTPUT The handle for the new pool, if creation is successful ++ * ++ * Returns: ++ * BCME_OK Pool created ok. ++ * other Pool not created due to indicated error. newpoolp set to NULL. ++ * ++ * ++ */ ++int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz, ++ const char poolname[BCM_MP_NAMELEN], ++ bcm_mp_pool_h *newp); ++ ++ ++/* ++ * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after ++ * all memory objects have been freed back to the pool. ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * pool: INPUT The handle of the pool to delete ++ * ++ * Returns: ++ * BCME_OK Pool deleted ok. ++ * other Pool not deleted due to indicated error. ++ * ++ */ ++int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); ++ ++ ++/* ++ * bcm_mpm_stats() - Return stats for all pools ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * stats: OUTPUT Array of pool statistics. ++ * nentries: MOD Max elements in 'stats' array on INPUT. Actual number ++ * of array elements copied to 'stats' on OUTPUT. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error getting stats. ++ * ++ */ ++int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries); ++ ++ ++/* ++ * bcm_mpm_dump() - Display statistics on all pools ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager ++ * b: OUTPUT Output buffer. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during dump. ++ * ++ */ ++int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b); ++ ++ ++/* ++ * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to ++ * compensate for alignment requirements of the objects. ++ * This function provides the padded object size. If clients ++ * pre-allocate a memory slab for a memory pool, the ++ * padded object size should be used by the client to allocate ++ * the memory slab (in order to provide sufficent space for ++ * the maximum number of objects). ++ * ++ * Parameters: ++ * mgr: INPUT The handle to the pools manager. ++ * obj_sz: INPUT Input object size. ++ * padded_obj_sz: OUTPUT Padded object size. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * BCME_BADARG Bad arguments. ++ * ++ */ ++int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz); ++ ++ ++/* ++*************************************************************************** ++* ++* API Routines on a specific pool. ++* ++*************************************************************************** ++*/ ++ ++ ++/* ++ * bcm_mp_alloc() - Allocate a memory pool object. ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool. ++ * ++ * Returns: ++ * A pointer to the new object. NULL on error. ++ * ++ */ ++void* bcm_mp_alloc(bcm_mp_pool_h pool); ++ ++/* ++ * bcm_mp_free() - Free a memory pool object. ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool. ++ * objp: INPUT A pointer to the object to free. ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during free. ++ * ++ */ ++int bcm_mp_free(bcm_mp_pool_h pool, void *objp); ++ ++/* ++ * bcm_mp_stats() - Return stats for this pool ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool ++ * stats: OUTPUT Pool statistics ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error getting statistics. ++ * ++ */ ++int bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats); ++ ++ ++/* ++ * bcm_mp_dump() - Dump a pool ++ * ++ * Parameters: ++ * pool: INPUT The handle to the pool ++ * b OUTPUT Output buffer ++ * ++ * Returns: ++ * BCME_OK Ok ++ * other Error during dump. ++ * ++ */ ++int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b); ++ ++ ++#endif /* _BCM_MPOOL_PUB_H */ +diff --git a/drivers/net/wireless/bcm4336/include/bcmcdc.h b/drivers/net/wireless/bcm4336/include/bcmcdc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmcdc.h @@ -0,0 +1,114 @@ +/* + * CDC network driver ioctl/indication encoding @@ -176955,24 +178893,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmcdc.h b/drivers/net/wirel + (((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT))) + +#endif /* _bcmcdc_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcm_cfg.h b/drivers/net/wireless/bcm4336/include/bcm_cfg.h ---- a/drivers/net/wireless/bcm4336/include/bcm_cfg.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcm_cfg.h 2018-05-06 08:49:50.626754176 +0200 -@@ -0,0 +1,11 @@ -+/* -+ * BCM common config options -+ * -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * $Id: bcm_cfg.h 351867 2012-08-21 18:46:16Z $ -+ */ -+ -+#ifndef _bcm_cfg_h_ -+#define _bcm_cfg_h_ -+#endif /* _bcm_cfg_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmdefs.h b/drivers/net/wireless/bcm4336/include/bcmdefs.h ---- a/drivers/net/wireless/bcm4336/include/bcmdefs.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmdefs.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmdefs.h b/drivers/net/wireless/bcm4336/include/bcmdefs.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmdefs.h @@ -0,0 +1,320 @@ +/* + * Misc system wide definitions @@ -177294,9 +179219,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmdefs.h b/drivers/net/wire + + +#endif /* _bcmdefs_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmdevs.h b/drivers/net/wireless/bcm4336/include/bcmdevs.h ---- a/drivers/net/wireless/bcm4336/include/bcmdevs.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmdevs.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmdevs.h b/drivers/net/wireless/bcm4336/include/bcmdevs.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmdevs.h @@ -0,0 +1,1088 @@ +/* + * Broadcom device-specific manifest constants. @@ -178386,9 +180313,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmdevs.h b/drivers/net/wire +#define FLASH_BOOT_NFLASH 0x00000002 + +#endif /* _BCMDEVS_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmendian.h b/drivers/net/wireless/bcm4336/include/bcmendian.h ---- a/drivers/net/wireless/bcm4336/include/bcmendian.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmendian.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmendian.h b/drivers/net/wireless/bcm4336/include/bcmendian.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmendian.h @@ -0,0 +1,311 @@ +/* + * Byte order utilities @@ -178701,356 +180630,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmendian.h b/drivers/net/wi + +#endif /* !__GNUC__ */ +#endif /* !_BCMENDIAN_H_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcm_mpool_pub.h b/drivers/net/wireless/bcm4336/include/bcm_mpool_pub.h ---- a/drivers/net/wireless/bcm4336/include/bcm_mpool_pub.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcm_mpool_pub.h 2018-05-06 08:49:50.626754176 +0200 -@@ -0,0 +1,343 @@ -+/* -+ * Memory pools library, Public interface -+ * -+ * API Overview -+ * -+ * This package provides a memory allocation subsystem based on pools of -+ * homogenous objects. -+ * -+ * Instrumentation is available for reporting memory utilization both -+ * on a per-data-structure basis and system wide. -+ * -+ * There are two main types defined in this API. -+ * -+ * pool manager: A singleton object that acts as a factory for -+ * pool allocators. It also is used for global -+ * instrumentation, such as reporting all blocks -+ * in use across all data structures. The pool manager -+ * creates and provides individual memory pools -+ * upon request to application code. -+ * -+ * memory pool: An object for allocating homogenous memory blocks. -+ * -+ * Global identifiers in this module use the following prefixes: -+ * bcm_mpm_* Memory pool manager -+ * bcm_mp_* Memory pool -+ * -+ * There are two main types of memory pools: -+ * -+ * prealloc: The contiguous memory block of objects can either be supplied -+ * by the client or malloc'ed by the memory manager. The objects are -+ * allocated out of a block of memory and freed back to the block. -+ * -+ * heap: The memory pool allocator uses the heap (malloc/free) for memory. -+ * In this case, the pool allocator is just providing statistics -+ * and instrumentation on top of the heap, without modifying the heap -+ * allocation implementation. -+ * -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * $Id: bcm_mpool_pub.h 407097 2013-06-11 18:43:16Z $ -+ */ -+ -+#ifndef _BCM_MPOOL_PUB_H -+#define _BCM_MPOOL_PUB_H 1 -+ -+#include /* needed for uint16 */ -+ -+ -+/* -+************************************************************************** -+* -+* Type definitions, handles -+* -+************************************************************************** -+*/ -+ -+/* Forward declaration of OSL handle. */ -+struct osl_info; -+ -+/* Forward declaration of string buffer. */ -+struct bcmstrbuf; -+ -+/* -+ * Opaque type definition for the pool manager handle. This object is used for global -+ * memory pool operations such as obtaining a new pool, deleting a pool, iterating and -+ * instrumentation/debugging. -+ */ -+struct bcm_mpm_mgr; -+typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h; -+ -+/* -+ * Opaque type definition for an instance of a pool. This handle is used for allocating -+ * and freeing memory through the pool, as well as management/instrumentation on this -+ * specific pool. -+ */ -+struct bcm_mp_pool; -+typedef struct bcm_mp_pool *bcm_mp_pool_h; -+ -+ -+/* -+ * To make instrumentation more readable, every memory -+ * pool must have a readable name. Pool names are up to -+ * 8 bytes including '\0' termination. (7 printable characters.) -+ */ -+#define BCM_MP_NAMELEN 8 -+ -+ -+/* -+ * Type definition for pool statistics. -+ */ -+typedef struct bcm_mp_stats { -+ char name[BCM_MP_NAMELEN]; /* Name of this pool. */ -+ unsigned int objsz; /* Object size allocated in this pool */ -+ uint16 nobj; /* Total number of objects in this pool */ -+ uint16 num_alloc; /* Number of objects currently allocated */ -+ uint16 high_water; /* Max number of allocated objects. */ -+ uint16 failed_alloc; /* Failed allocations. */ -+} bcm_mp_stats_t; -+ -+ -+/* -+************************************************************************** -+* -+* API Routines on the pool manager. -+* -+************************************************************************** -+*/ -+ -+/* -+ * bcm_mpm_init() - initialize the whole memory pool system. -+ * -+ * Parameters: -+ * osh: INPUT Operating system handle. Needed for heap memory allocation. -+ * max_pools: INPUT Maximum number of mempools supported. -+ * mgr: OUTPUT The handle is written with the new pools manager object/handle. -+ * -+ * Returns: -+ * BCME_OK Object initialized successfully. May be used. -+ * BCME_NOMEM Initialization failed due to no memory. Object must not be used. -+ */ -+int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp); -+ -+ -+/* -+ * bcm_mpm_deinit() - de-initialize the whole memory pool system. -+ * -+ * Parameters: -+ * mgr: INPUT Pointer to pool manager handle. -+ * -+ * Returns: -+ * BCME_OK Memory pool manager successfully de-initialized. -+ * other Indicated error occured during de-initialization. -+ */ -+int bcm_mpm_deinit(bcm_mpm_mgr_h *mgrp); -+ -+/* -+ * bcm_mpm_create_prealloc_pool() - Create a new pool for fixed size objects. The -+ * pool uses a contiguous block of pre-alloced -+ * memory. The memory block may either be provided -+ * by the client or dynamically allocated by the -+ * pool manager. -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pool manager -+ * obj_sz: INPUT Size of objects that will be allocated by the new pool -+ * Must be >= sizeof(void *). -+ * nobj: INPUT Maximum number of concurrently existing objects to support -+ * memstart INPUT Pointer to the memory to use, or NULL to malloc() -+ * memsize INPUT Number of bytes referenced from memstart (for error checking). -+ * Must be 0 if 'memstart' is NULL. -+ * poolname INPUT For instrumentation, the name of the pool -+ * newp: OUTPUT The handle for the new pool, if creation is successful -+ * -+ * Returns: -+ * BCME_OK Pool created ok. -+ * other Pool not created due to indicated error. newpoolp set to NULL. -+ * -+ * -+ */ -+int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr, -+ unsigned int obj_sz, -+ int nobj, -+ void *memstart, -+ unsigned int memsize, -+ const char poolname[BCM_MP_NAMELEN], -+ bcm_mp_pool_h *newp); -+ -+ -+/* -+ * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after -+ * all memory objects have been freed back to the pool. -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pools manager -+ * pool: INPUT The handle of the pool to delete -+ * -+ * Returns: -+ * BCME_OK Pool deleted ok. -+ * other Pool not deleted due to indicated error. -+ * -+ */ -+int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); -+ -+/* -+ * bcm_mpm_create_heap_pool() - Create a new pool for fixed size objects. The memory -+ * pool allocator uses the heap (malloc/free) for memory. -+ * In this case, the pool allocator is just providing -+ * statistics and instrumentation on top of the heap, -+ * without modifying the heap allocation implementation. -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pool manager -+ * obj_sz: INPUT Size of objects that will be allocated by the new pool -+ * poolname INPUT For instrumentation, the name of the pool -+ * newp: OUTPUT The handle for the new pool, if creation is successful -+ * -+ * Returns: -+ * BCME_OK Pool created ok. -+ * other Pool not created due to indicated error. newpoolp set to NULL. -+ * -+ * -+ */ -+int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz, -+ const char poolname[BCM_MP_NAMELEN], -+ bcm_mp_pool_h *newp); -+ -+ -+/* -+ * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after -+ * all memory objects have been freed back to the pool. -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pools manager -+ * pool: INPUT The handle of the pool to delete -+ * -+ * Returns: -+ * BCME_OK Pool deleted ok. -+ * other Pool not deleted due to indicated error. -+ * -+ */ -+int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); -+ -+ -+/* -+ * bcm_mpm_stats() - Return stats for all pools -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pools manager -+ * stats: OUTPUT Array of pool statistics. -+ * nentries: MOD Max elements in 'stats' array on INPUT. Actual number -+ * of array elements copied to 'stats' on OUTPUT. -+ * -+ * Returns: -+ * BCME_OK Ok -+ * other Error getting stats. -+ * -+ */ -+int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries); -+ -+ -+/* -+ * bcm_mpm_dump() - Display statistics on all pools -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pools manager -+ * b: OUTPUT Output buffer. -+ * -+ * Returns: -+ * BCME_OK Ok -+ * other Error during dump. -+ * -+ */ -+int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b); -+ -+ -+/* -+ * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to -+ * compensate for alignment requirements of the objects. -+ * This function provides the padded object size. If clients -+ * pre-allocate a memory slab for a memory pool, the -+ * padded object size should be used by the client to allocate -+ * the memory slab (in order to provide sufficent space for -+ * the maximum number of objects). -+ * -+ * Parameters: -+ * mgr: INPUT The handle to the pools manager. -+ * obj_sz: INPUT Input object size. -+ * padded_obj_sz: OUTPUT Padded object size. -+ * -+ * Returns: -+ * BCME_OK Ok -+ * BCME_BADARG Bad arguments. -+ * -+ */ -+int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz); -+ -+ -+/* -+*************************************************************************** -+* -+* API Routines on a specific pool. -+* -+*************************************************************************** -+*/ -+ -+ -+/* -+ * bcm_mp_alloc() - Allocate a memory pool object. -+ * -+ * Parameters: -+ * pool: INPUT The handle to the pool. -+ * -+ * Returns: -+ * A pointer to the new object. NULL on error. -+ * -+ */ -+void* bcm_mp_alloc(bcm_mp_pool_h pool); -+ -+/* -+ * bcm_mp_free() - Free a memory pool object. -+ * -+ * Parameters: -+ * pool: INPUT The handle to the pool. -+ * objp: INPUT A pointer to the object to free. -+ * -+ * Returns: -+ * BCME_OK Ok -+ * other Error during free. -+ * -+ */ -+int bcm_mp_free(bcm_mp_pool_h pool, void *objp); -+ -+/* -+ * bcm_mp_stats() - Return stats for this pool -+ * -+ * Parameters: -+ * pool: INPUT The handle to the pool -+ * stats: OUTPUT Pool statistics -+ * -+ * Returns: -+ * BCME_OK Ok -+ * other Error getting statistics. -+ * -+ */ -+int bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats); -+ -+ -+/* -+ * bcm_mp_dump() - Dump a pool -+ * -+ * Parameters: -+ * pool: INPUT The handle to the pool -+ * b OUTPUT Output buffer -+ * -+ * Returns: -+ * BCME_OK Ok -+ * other Error during dump. -+ * -+ */ -+int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b); -+ -+ -+#endif /* _BCM_MPOOL_PUB_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmmsgbuf.h b/drivers/net/wireless/bcm4336/include/bcmmsgbuf.h ---- a/drivers/net/wireless/bcm4336/include/bcmmsgbuf.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmmsgbuf.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmmsgbuf.h b/drivers/net/wireless/bcm4336/include/bcmmsgbuf.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmmsgbuf.h @@ -0,0 +1,731 @@ +/* + * MSGBUF network driver ioctl/indication encoding @@ -179783,9 +181367,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmmsgbuf.h b/drivers/net/wi +#define MSGBUF_IOC_ACTION_MASK 0x1 + +#endif /* _bcmmsgbuf_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmpcie.h b/drivers/net/wireless/bcm4336/include/bcmpcie.h ---- a/drivers/net/wireless/bcm4336/include/bcmpcie.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmpcie.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmpcie.h b/drivers/net/wireless/bcm4336/include/bcmpcie.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmpcie.h @@ -0,0 +1,203 @@ +/* + * Broadcom PCIE @@ -179990,9 +181576,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmpcie.h b/drivers/net/wire + MIN(WRITE_SPACE_AVAIL(r, w, d), WRITE_SPACE_AVAIL_CONTINUOUS(r, w, d)) + +#endif /* _bcmpcie_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmpcispi.h b/drivers/net/wireless/bcm4336/include/bcmpcispi.h ---- a/drivers/net/wireless/bcm4336/include/bcmpcispi.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmpcispi.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmpcispi.h b/drivers/net/wireless/bcm4336/include/bcmpcispi.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmpcispi.h @@ -0,0 +1,163 @@ +/* + * Broadcom PCI-SPI Host Controller Register Definitions @@ -180157,9 +181745,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmpcispi.h b/drivers/net/wi +#define SPI_SPIN_BOUND 0xf4240 /* 1 million */ + +#endif /* _BCM_PCI_SPI_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmperf.h b/drivers/net/wireless/bcm4336/include/bcmperf.h ---- a/drivers/net/wireless/bcm4336/include/bcmperf.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmperf.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmperf.h b/drivers/net/wireless/bcm4336/include/bcmperf.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmperf.h @@ -0,0 +1,18 @@ +/* + * Performance counters software interface. @@ -180179,9 +181769,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmperf.h b/drivers/net/wire +#define BCMPERF_GETICACHE_HIT(x) ((x) = 0) +#define BCMPERF_GETINSTRCOUNT(x) ((x) = 0) +#endif /* _BCMPERF_H_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdbus.h b/drivers/net/wireless/bcm4336/include/bcmsdbus.h ---- a/drivers/net/wireless/bcm4336/include/bcmsdbus.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmsdbus.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmsdbus.h b/drivers/net/wireless/bcm4336/include/bcmsdbus.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmsdbus.h @@ -0,0 +1,125 @@ +/* + * Definitions for API from sdio common code (bcmsdh) to individual @@ -180308,9 +181900,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdbus.h b/drivers/net/wir +extern SDIOH_API_RC sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab); + +#endif /* _sdio_api_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdh.h b/drivers/net/wireless/bcm4336/include/bcmsdh.h ---- a/drivers/net/wireless/bcm4336/include/bcmsdh.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmsdh.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmsdh.h b/drivers/net/wireless/bcm4336/include/bcmsdh.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmsdh.h @@ -0,0 +1,239 @@ +/* + * SDIO host client driver interface of Broadcom HNBU @@ -180551,9 +182145,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdh.h b/drivers/net/wirel +extern int bcmsdh_gpioout(void *sd, uint32 gpio, bool enab); + +#endif /* _bcmsdh_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcm4336/include/bcmsdh_sdmmc.h ---- a/drivers/net/wireless/bcm4336/include/bcmsdh_sdmmc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmsdh_sdmmc.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcm4336/include/bcmsdh_sdmmc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmsdh_sdmmc.h @@ -0,0 +1,125 @@ +/* + * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel @@ -180680,9 +182276,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdh_sdmmc.h b/drivers/net +#endif + +#endif /* __BCMSDH_SDMMC_H__ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdpcm.h b/drivers/net/wireless/bcm4336/include/bcmsdpcm.h ---- a/drivers/net/wireless/bcm4336/include/bcmsdpcm.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmsdpcm.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmsdpcm.h b/drivers/net/wireless/bcm4336/include/bcmsdpcm.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmsdpcm.h @@ -0,0 +1,260 @@ +/* + * Broadcom SDIO/PCMCIA @@ -180944,9 +182542,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdpcm.h b/drivers/net/wir +extern sdpcm_shared_t sdpcm_shared; + +#endif /* _bcmsdpcm_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdspi.h b/drivers/net/wireless/bcm4336/include/bcmsdspi.h ---- a/drivers/net/wireless/bcm4336/include/bcmsdspi.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmsdspi.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmsdspi.h b/drivers/net/wireless/bcm4336/include/bcmsdspi.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmsdspi.h @@ -0,0 +1,117 @@ +/* + * SD-SPI Protocol Conversion - BCMSDH->SPI Translation Layer @@ -181065,9 +182665,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdspi.h b/drivers/net/wir +extern void spi_osfree(sdioh_info_t *sd); + +#endif /* _BCM_SD_SPI_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdstd.h b/drivers/net/wireless/bcm4336/include/bcmsdstd.h ---- a/drivers/net/wireless/bcm4336/include/bcmsdstd.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmsdstd.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmsdstd.h b/drivers/net/wireless/bcm4336/include/bcmsdstd.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmsdstd.h @@ -0,0 +1,264 @@ +/* + * 'Standard' SDIO HOST CONTROLLER driver @@ -181333,9 +182935,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmsdstd.h b/drivers/net/wir +extern sdioh_info_t *sdioh_attach(osl_t *osh, void *bar0, uint irq); +extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *sd); +#endif /* _BCM_SD_STD_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmspi.h b/drivers/net/wireless/bcm4336/include/bcmspi.h ---- a/drivers/net/wireless/bcm4336/include/bcmspi.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmspi.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmspi.h b/drivers/net/wireless/bcm4336/include/bcmspi.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmspi.h @@ -0,0 +1,22 @@ +/* + * Broadcom SPI Low-Level Hardware Driver API @@ -181359,9 +182963,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmspi.h b/drivers/net/wirel +extern void spi_waitbits(sdioh_info_t *sd, bool yield); + +#endif /* _BCM_SPI_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmutils.h b/drivers/net/wireless/bcm4336/include/bcmutils.h ---- a/drivers/net/wireless/bcm4336/include/bcmutils.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmutils.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmutils.h b/drivers/net/wireless/bcm4336/include/bcmutils.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmutils.h @@ -0,0 +1,1156 @@ +/* + * Misc useful os-independent macros and functions. @@ -182519,9 +184125,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmutils.h b/drivers/net/wir +#endif /* DEBUG_COUNTER */ + +#endif /* _bcmutils_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmwifi_channels.h b/drivers/net/wireless/bcm4336/include/bcmwifi_channels.h ---- a/drivers/net/wireless/bcm4336/include/bcmwifi_channels.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmwifi_channels.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmwifi_channels.h b/drivers/net/wireless/bcm4336/include/bcmwifi_channels.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmwifi_channels.h @@ -0,0 +1,530 @@ +/* + * Misc utility routines for WL and Apps @@ -183053,9 +184661,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmwifi_channels.h b/drivers +extern uint8 wf_chspec_channel(chanspec_t chspec); +#endif +#endif /* _bcmwifi_channels_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmwifi_rates.h b/drivers/net/wireless/bcm4336/include/bcmwifi_rates.h ---- a/drivers/net/wireless/bcm4336/include/bcmwifi_rates.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/bcmwifi_rates.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/bcmwifi_rates.h b/drivers/net/wireless/bcm4336/include/bcmwifi_rates.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/bcmwifi_rates.h @@ -0,0 +1,452 @@ +/* + * Indices for 802.11 a/b/g/n/ac 1-3 chain symmetric transmit rates @@ -183509,9 +185119,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/bcmwifi_rates.h b/drivers/ne +#endif /* __cplusplus */ + +#endif /* _bcmwifi_rates_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/brcm_nl80211.h b/drivers/net/wireless/bcm4336/include/brcm_nl80211.h ---- a/drivers/net/wireless/bcm4336/include/brcm_nl80211.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/brcm_nl80211.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/brcm_nl80211.h b/drivers/net/wireless/bcm4336/include/brcm_nl80211.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/brcm_nl80211.h @@ -0,0 +1,45 @@ +/* + * Definitions for nl80211 vendor command/event access to host driver @@ -183558,9 +185170,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/brcm_nl80211.h b/drivers/net +}; + +#endif /* _brcm_nl80211_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/circularbuf.h b/drivers/net/wireless/bcm4336/include/circularbuf.h ---- a/drivers/net/wireless/bcm4336/include/circularbuf.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/circularbuf.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/circularbuf.h b/drivers/net/wireless/bcm4336/include/circularbuf.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/circularbuf.h @@ -0,0 +1,97 @@ +/* + * Initialization and support routines for self-booting compressed image. @@ -183659,9 +185273,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/circularbuf.h b/drivers/net/ +circularbuf_revert_rp_ptr(circularbuf_t *handle, uint16 bytes); + +#endif /* __CIRCULARBUF_H_INCLUDED__ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/devctrl_if/wlioctl_defs.h b/drivers/net/wireless/bcm4336/include/devctrl_if/wlioctl_defs.h ---- a/drivers/net/wireless/bcm4336/include/devctrl_if/wlioctl_defs.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/devctrl_if/wlioctl_defs.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/devctrl_if/wlioctl_defs.h b/drivers/net/wireless/bcm4336/include/devctrl_if/wlioctl_defs.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/devctrl_if/wlioctl_defs.h @@ -0,0 +1,2103 @@ +/* + * Custom OID/ioctl definitions for @@ -185766,9 +187382,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/devctrl_if/wlioctl_defs.h b/ +#define AP_ISOLATE_SENDUP_MCAST 0x02 + +#endif /* wlioctl_defs_h */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/dhdioctl.h b/drivers/net/wireless/bcm4336/include/dhdioctl.h ---- a/drivers/net/wireless/bcm4336/include/dhdioctl.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/dhdioctl.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/dhdioctl.h b/drivers/net/wireless/bcm4336/include/dhdioctl.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/dhdioctl.h @@ -0,0 +1,123 @@ +/* + * Definitions for ioctls to access DHD iovars. @@ -185893,9 +187511,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/dhdioctl.h b/drivers/net/wir +#include + +#endif /* _dhdioctl_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/epivers.h b/drivers/net/wireless/bcm4336/include/epivers.h ---- a/drivers/net/wireless/bcm4336/include/epivers.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/epivers.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/epivers.h b/drivers/net/wireless/bcm4336/include/epivers.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/epivers.h @@ -0,0 +1,30 @@ +/* + * $Copyright Open Broadcom Corporation$ @@ -185927,9 +187547,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/epivers.h b/drivers/net/wire +#define EPI_VERSION_STR "1.201.59.5 (r506368)" + +#endif /* _epivers_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/epivers.h.in b/drivers/net/wireless/bcm4336/include/epivers.h.in ---- a/drivers/net/wireless/bcm4336/include/epivers.h.in 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/epivers.h.in 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/epivers.h.in b/drivers/net/wireless/bcm4336/include/epivers.h.in +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/epivers.h.in @@ -0,0 +1,30 @@ +/* + * $Copyright Open Broadcom Corporation$ @@ -185961,9 +187583,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/epivers.h.in b/drivers/net/w +#define EPI_VERSION_STR "@EPI_VERSION_STR@@EPI_VERSION_TYPE@ (@VC_VERSION_NUM@)" + +#endif /* _epivers_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/epivers.sh b/drivers/net/wireless/bcm4336/include/epivers.sh ---- a/drivers/net/wireless/bcm4336/include/epivers.sh 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/epivers.sh 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/epivers.sh b/drivers/net/wireless/bcm4336/include/epivers.sh +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/epivers.sh @@ -0,0 +1,333 @@ +#! /bin/bash +# @@ -186298,9 +187922,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/epivers.sh b/drivers/net/wir + dos2unix epivers.h > $NULL 2>&1 + fi +fi # epivers.h -diff -ENwbur a/drivers/net/wireless/bcm4336/include/event_log.h b/drivers/net/wireless/bcm4336/include/event_log.h ---- a/drivers/net/wireless/bcm4336/include/event_log.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/event_log.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/event_log.h b/drivers/net/wireless/bcm4336/include/event_log.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/event_log.h @@ -0,0 +1,293 @@ +/* + * EVENT_LOG system definitions @@ -186595,9 +188221,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/event_log.h b/drivers/net/wi +#endif /* __ASSEMBLER__ */ + +#endif /* _EVENT_LOG_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/hnd_armtrap.h b/drivers/net/wireless/bcm4336/include/hnd_armtrap.h ---- a/drivers/net/wireless/bcm4336/include/hnd_armtrap.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/hnd_armtrap.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/hnd_armtrap.h b/drivers/net/wireless/bcm4336/include/hnd_armtrap.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/hnd_armtrap.h @@ -0,0 +1,70 @@ +/* + * HND arm trap handling. @@ -186669,9 +188297,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/hnd_armtrap.h b/drivers/net/ +#endif /* !_LANGUAGE_ASSEMBLY */ + +#endif /* _hnd_armtrap_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/hnd_cons.h b/drivers/net/wireless/bcm4336/include/hnd_cons.h ---- a/drivers/net/wireless/bcm4336/include/hnd_cons.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/hnd_cons.h 2018-05-06 08:49:50.626754176 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/hnd_cons.h b/drivers/net/wireless/bcm4336/include/hnd_cons.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/hnd_cons.h @@ -0,0 +1,59 @@ +/* + * Console support for RTE - for host use only. @@ -186732,9 +188362,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/hnd_cons.h b/drivers/net/wir +} hnd_cons_t; + +#endif /* _hnd_cons_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/hnd_pktpool.h b/drivers/net/wireless/bcm4336/include/hnd_pktpool.h ---- a/drivers/net/wireless/bcm4336/include/hnd_pktpool.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/hnd_pktpool.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/hnd_pktpool.h b/drivers/net/wireless/bcm4336/include/hnd_pktpool.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/hnd_pktpool.h @@ -0,0 +1,186 @@ +/* + * HND generic packet pool operation primitives @@ -186922,9 +188554,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/hnd_pktpool.h b/drivers/net/ +#endif + +#endif /* _hnd_pktpool_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/hnd_pktq.h b/drivers/net/wireless/bcm4336/include/hnd_pktq.h ---- a/drivers/net/wireless/bcm4336/include/hnd_pktq.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/hnd_pktq.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/hnd_pktq.h b/drivers/net/wireless/bcm4336/include/hnd_pktq.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/hnd_pktq.h @@ -0,0 +1,168 @@ +/* + * HND generic pktq operation primitives @@ -187094,9 +188728,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/hnd_pktq.h b/drivers/net/wir +#endif + +#endif /* _hnd_pktq_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/hndpmu.h b/drivers/net/wireless/bcm4336/include/hndpmu.h ---- a/drivers/net/wireless/bcm4336/include/hndpmu.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/hndpmu.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/hndpmu.h b/drivers/net/wireless/bcm4336/include/hndpmu.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/hndpmu.h @@ -0,0 +1,23 @@ +/* + * HND SiliconBackplane PMU support. @@ -187121,9 +188757,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/hndpmu.h b/drivers/net/wirel +extern void si_pmu_slow_clk_reinit(si_t *sih, osl_t *osh); + +#endif /* _hndpmu_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/hndsoc.h b/drivers/net/wireless/bcm4336/include/hndsoc.h ---- a/drivers/net/wireless/bcm4336/include/hndsoc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/hndsoc.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/hndsoc.h b/drivers/net/wireless/bcm4336/include/hndsoc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/hndsoc.h @@ -0,0 +1,268 @@ +/* + * Broadcom HND chip & on-chip-interconnect-related definitions. @@ -187393,9 +189031,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/hndsoc.h b/drivers/net/wirel +#endif /* !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__) */ + +#endif /* _HNDSOC_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/linux_osl.h b/drivers/net/wireless/bcm4336/include/linux_osl.h ---- a/drivers/net/wireless/bcm4336/include/linux_osl.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/linux_osl.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/linux_osl.h b/drivers/net/wireless/bcm4336/include/linux_osl.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/linux_osl.h @@ -0,0 +1,1028 @@ +/* + * Linux OS Independent Layer @@ -188425,9 +190065,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/linux_osl.h b/drivers/net/wi + +#endif /* BCM_SECURE_DMA */ +#endif /* _linux_osl_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/linuxver.h b/drivers/net/wireless/bcm4336/include/linuxver.h ---- a/drivers/net/wireless/bcm4336/include/linuxver.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/linuxver.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/linuxver.h b/drivers/net/wireless/bcm4336/include/linuxver.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/linuxver.h @@ -0,0 +1,730 @@ +/* + * Linux-specific abstractions to gain some independence from linux kernel versions. @@ -189159,66 +190801,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/linuxver.h b/drivers/net/wir +#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) */ + +#endif /* _linuxver_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/Makefile b/drivers/net/wireless/bcm4336/include/Makefile ---- a/drivers/net/wireless/bcm4336/include/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/Makefile 2018-05-06 08:49:50.626754176 +0200 -@@ -0,0 +1,53 @@ -+#!/bin/bash -+# -+# This script serves following purpose: -+# -+# 1. It generates native version information by querying -+# automerger maintained database to see where src/include -+# came from -+# 2. For select components, as listed in compvers.sh -+# it generates component version files -+# -+# Copyright 2005, Broadcom, Inc. -+# -+# $Id: Makefile 347587 2012-07-27 09:13:31Z $ -+# -+ -+export SRCBASE:=.. -+ -+TARGETS := epivers.h -+ -+ifdef VERBOSE -+export VERBOSE -+endif -+ -+all release: epivers compvers -+ -+# Generate epivers.h for native branch url -+epivers: -+ bash epivers.sh -+ -+# Generate component versions based on component url -+compvers: -+ @if [ -s "compvers.sh" ]; then \ -+ echo "Generating component versions, if any"; \ -+ bash compvers.sh; \ -+ else \ -+ echo "Skipping component version generation"; \ -+ fi -+ -+# Generate epivers.h for native branch version -+clean_compvers: -+ @if [ -s "compvers.sh" ]; then \ -+ echo "bash compvers.sh clean"; \ -+ bash compvers.sh clean; \ -+ else \ -+ echo "Skipping component version clean"; \ -+ fi -+ -+clean: -+ rm -f $(TARGETS) *.prev -+ -+clean_all: clean clean_compvers -+ -+.PHONY: all release clean epivers compvers clean_compvers -diff -ENwbur a/drivers/net/wireless/bcm4336/include/miniopt.h b/drivers/net/wireless/bcm4336/include/miniopt.h ---- a/drivers/net/wireless/bcm4336/include/miniopt.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/miniopt.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/miniopt.h b/drivers/net/wireless/bcm4336/include/miniopt.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/miniopt.h @@ -0,0 +1,61 @@ +/* + * Command line options parser. @@ -189281,9 +190868,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/miniopt.h b/drivers/net/wire +#endif + +#endif /* MINI_OPT_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/msgtrace.h b/drivers/net/wireless/bcm4336/include/msgtrace.h ---- a/drivers/net/wireless/bcm4336/include/msgtrace.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/msgtrace.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/msgtrace.h b/drivers/net/wireless/bcm4336/include/msgtrace.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/msgtrace.h @@ -0,0 +1,60 @@ +/* + * Trace messages sent over HBUS @@ -189345,29 +190934,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/msgtrace.h b/drivers/net/wir +#include + +#endif /* _MSGTRACE_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/osl_decl.h b/drivers/net/wireless/bcm4336/include/osl_decl.h ---- a/drivers/net/wireless/bcm4336/include/osl_decl.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/osl_decl.h 2018-05-06 08:49:50.630754337 +0200 -@@ -0,0 +1,16 @@ -+/* -+ * osl forward declarations -+ * -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * $Id$ -+ */ -+ -+#ifndef _osl_decl_h_ -+#define _osl_decl_h_ -+ -+/* osl handle type forward declaration */ -+typedef struct osl_info osl_t; -+typedef struct osl_dmainfo osldma_t; -+ -+#endif -diff -ENwbur a/drivers/net/wireless/bcm4336/include/osl.h b/drivers/net/wireless/bcm4336/include/osl.h ---- a/drivers/net/wireless/bcm4336/include/osl.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/osl.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/osl.h b/drivers/net/wireless/bcm4336/include/osl.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/osl.h @@ -0,0 +1,143 @@ +/* + * OS Abstraction Layer @@ -189512,9 +191083,33 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/osl.h b/drivers/net/wireless +#endif + +#endif /* _osl_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/packed_section_end.h b/drivers/net/wireless/bcm4336/include/packed_section_end.h ---- a/drivers/net/wireless/bcm4336/include/packed_section_end.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/packed_section_end.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/osl_decl.h b/drivers/net/wireless/bcm4336/include/osl_decl.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/osl_decl.h +@@ -0,0 +1,16 @@ ++/* ++ * osl forward declarations ++ * ++ * $Copyright Open Broadcom Corporation$ ++ * ++ * $Id$ ++ */ ++ ++#ifndef _osl_decl_h_ ++#define _osl_decl_h_ ++ ++/* osl handle type forward declaration */ ++typedef struct osl_info osl_t; ++typedef struct osl_dmainfo osldma_t; ++ ++#endif +diff --git a/drivers/net/wireless/bcm4336/include/packed_section_end.h b/drivers/net/wireless/bcm4336/include/packed_section_end.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/packed_section_end.h @@ -0,0 +1,41 @@ +/* + * Declare directives for structure packing. No padding will be provided @@ -189557,9 +191152,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/packed_section_end.h b/drive + */ +#undef BWL_PRE_PACKED_STRUCT +#undef BWL_POST_PACKED_STRUCT -diff -ENwbur a/drivers/net/wireless/bcm4336/include/packed_section_start.h b/drivers/net/wireless/bcm4336/include/packed_section_start.h ---- a/drivers/net/wireless/bcm4336/include/packed_section_start.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/packed_section_start.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/packed_section_start.h b/drivers/net/wireless/bcm4336/include/packed_section_start.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/packed_section_start.h @@ -0,0 +1,45 @@ +/* + * Declare directives for structure packing. No padding will be provided @@ -189606,9 +191203,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/packed_section_start.h b/dri +#else + #error "Unknown compiler!" +#endif -diff -ENwbur a/drivers/net/wireless/bcm4336/include/pcicfg.h b/drivers/net/wireless/bcm4336/include/pcicfg.h ---- a/drivers/net/wireless/bcm4336/include/pcicfg.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/pcicfg.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/pcicfg.h b/drivers/net/wireless/bcm4336/include/pcicfg.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/pcicfg.h @@ -0,0 +1,600 @@ +/* + * pcicfg.h: PCI configuration constants and structures. @@ -190210,9 +191809,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/pcicfg.h b/drivers/net/wirel + } while (0) + +#endif /* _h_pcicfg_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/pcie_core.h b/drivers/net/wireless/bcm4336/include/pcie_core.h ---- a/drivers/net/wireless/bcm4336/include/pcie_core.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/pcie_core.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/pcie_core.h b/drivers/net/wireless/bcm4336/include/pcie_core.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/pcie_core.h @@ -0,0 +1,624 @@ +/* + * BCM43XX PCIE core hardware definitions. @@ -190838,164 +192439,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/pcie_core.h b/drivers/net/wi +#endif /* BCMDRIVER */ + +#endif /* _PCIE_CORE_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/802.11_bta.h b/drivers/net/wireless/bcm4336/include/proto/802.11_bta.h ---- a/drivers/net/wireless/bcm4336/include/proto/802.11_bta.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/802.11_bta.h 2018-05-06 08:49:50.630754337 +0200 -@@ -0,0 +1,27 @@ -+/* -+ * BT-AMP (BlueTooth Alternate Mac and Phy) 802.11 PAL (Protocol Adaptation Layer) -+ * -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * $Id: 802.11_bta.h 382882 2013-02-04 23:24:31Z $ -+*/ -+ -+#ifndef _802_11_BTA_H_ -+#define _802_11_BTA_H_ -+ -+#define BT_SIG_SNAP_MPROT "\xAA\xAA\x03\x00\x19\x58" -+ -+/* BT-AMP 802.11 PAL Protocols */ -+#define BTA_PROT_L2CAP 1 -+#define BTA_PROT_ACTIVITY_REPORT 2 -+#define BTA_PROT_SECURITY 3 -+#define BTA_PROT_LINK_SUPERVISION_REQUEST 4 -+#define BTA_PROT_LINK_SUPERVISION_REPLY 5 -+ -+/* BT-AMP 802.11 PAL AMP_ASSOC Type IDs */ -+#define BTA_TYPE_ID_MAC_ADDRESS 1 -+#define BTA_TYPE_ID_PREFERRED_CHANNELS 2 -+#define BTA_TYPE_ID_CONNECTED_CHANNELS 3 -+#define BTA_TYPE_ID_CAPABILITIES 4 -+#define BTA_TYPE_ID_VERSION 5 -+#endif /* _802_11_bta_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/802.11e.h b/drivers/net/wireless/bcm4336/include/proto/802.11e.h ---- a/drivers/net/wireless/bcm4336/include/proto/802.11e.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/802.11e.h 2018-05-06 08:49:50.630754337 +0200 -@@ -0,0 +1,120 @@ -+/* -+ * 802.11e protocol header file -+ * -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * $Id: 802.11e.h 382883 2013-02-04 23:26:09Z $ -+ */ -+ -+#ifndef _802_11e_H_ -+#define _802_11e_H_ -+ -+#ifndef _TYPEDEFS_H_ -+#include -+#endif -+ -+/* This marks the start of a packed structure section. */ -+#include -+ -+ -+/* WME Traffic Specification (TSPEC) element */ -+#define WME_TSPEC_HDR_LEN 2 /* WME TSPEC header length */ -+#define WME_TSPEC_BODY_OFF 2 /* WME TSPEC body offset */ -+ -+#define WME_CATEGORY_CODE_OFFSET 0 /* WME Category code offset */ -+#define WME_ACTION_CODE_OFFSET 1 /* WME Action code offset */ -+#define WME_TOKEN_CODE_OFFSET 2 /* WME Token code offset */ -+#define WME_STATUS_CODE_OFFSET 3 /* WME Status code offset */ -+ -+BWL_PRE_PACKED_STRUCT struct tsinfo { -+ uint8 octets[3]; -+} BWL_POST_PACKED_STRUCT; -+ -+typedef struct tsinfo tsinfo_t; -+ -+/* 802.11e TSPEC IE */ -+typedef BWL_PRE_PACKED_STRUCT struct tspec { -+ uint8 oui[DOT11_OUI_LEN]; /* WME_OUI */ -+ uint8 type; /* WME_TYPE */ -+ uint8 subtype; /* WME_SUBTYPE_TSPEC */ -+ uint8 version; /* WME_VERSION */ -+ tsinfo_t tsinfo; /* TS Info bit field */ -+ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ -+ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ -+ uint32 min_srv_interval; /* Minimum Service Interval (us) */ -+ uint32 max_srv_interval; /* Maximum Service Interval (us) */ -+ uint32 inactivity_interval; /* Inactivity Interval (us) */ -+ uint32 suspension_interval; /* Suspension Interval (us) */ -+ uint32 srv_start_time; /* Service Start Time (us) */ -+ uint32 min_data_rate; /* Minimum Data Rate (bps) */ -+ uint32 mean_data_rate; /* Mean Data Rate (bps) */ -+ uint32 peak_data_rate; /* Peak Data Rate (bps) */ -+ uint32 max_burst_size; /* Maximum Burst Size (bytes) */ -+ uint32 delay_bound; /* Delay Bound (us) */ -+ uint32 min_phy_rate; /* Minimum PHY Rate (bps) */ -+ uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0-8.0) */ -+ uint16 medium_time; /* Medium Time (32 us/s periods) */ -+} BWL_POST_PACKED_STRUCT tspec_t; -+ -+#define WME_TSPEC_LEN (sizeof(tspec_t)) /* not including 2-bytes of header */ -+ -+/* ts_info */ -+/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */ -+#define TS_INFO_TID_SHIFT 1 /* TS info. TID shift */ -+#define TS_INFO_TID_MASK (0xf << TS_INFO_TID_SHIFT) /* TS info. TID mask */ -+#define TS_INFO_CONTENTION_SHIFT 7 /* TS info. contention shift */ -+#define TS_INFO_CONTENTION_MASK (0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */ -+#define TS_INFO_DIRECTION_SHIFT 5 /* TS info. direction shift */ -+#define TS_INFO_DIRECTION_MASK (0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */ -+#define TS_INFO_PSB_SHIFT 2 /* TS info. PSB bit Shift */ -+#define TS_INFO_PSB_MASK (1 << TS_INFO_PSB_SHIFT) /* TS info. PSB mask */ -+#define TS_INFO_UPLINK (0 << TS_INFO_DIRECTION_SHIFT) /* TS info. uplink */ -+#define TS_INFO_DOWNLINK (1 << TS_INFO_DIRECTION_SHIFT) /* TS info. downlink */ -+#define TS_INFO_BIDIRECTIONAL (3 << TS_INFO_DIRECTION_SHIFT) /* TS info. bidirectional */ -+#define TS_INFO_USER_PRIO_SHIFT 3 /* TS info. user priority shift */ -+/* TS info. user priority mask */ -+#define TS_INFO_USER_PRIO_MASK (0x7 << TS_INFO_USER_PRIO_SHIFT) -+ -+/* Macro to get/set bit(s) field in TSINFO */ -+#define WLC_CAC_GET_TID(pt) ((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT) -+#define WLC_CAC_GET_DIR(pt) ((((pt).octets[0]) & \ -+ TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT) -+#define WLC_CAC_GET_PSB(pt) ((((pt).octets[1]) & TS_INFO_PSB_MASK) >> TS_INFO_PSB_SHIFT) -+#define WLC_CAC_GET_USER_PRIO(pt) ((((pt).octets[1]) & \ -+ TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT) -+ -+#define WLC_CAC_SET_TID(pt, id) ((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \ -+ ((id) << TS_INFO_TID_SHIFT)) -+#define WLC_CAC_SET_USER_PRIO(pt, prio) ((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \ -+ ((prio) << TS_INFO_USER_PRIO_SHIFT)) -+ -+/* 802.11e QBSS Load IE */ -+#define QBSS_LOAD_IE_LEN 5 /* QBSS Load IE length */ -+#define QBSS_LOAD_AAC_OFF 3 /* AAC offset in IE */ -+ -+#define CAC_ADDTS_RESP_TIMEOUT 1000 /* default ADDTS response timeout in ms */ -+ /* DEFVAL dot11ADDTSResponseTimeout = 1s */ -+ -+/* 802.11e ADDTS status code */ -+#define DOT11E_STATUS_ADMISSION_ACCEPTED 0 /* TSPEC Admission accepted status */ -+#define DOT11E_STATUS_ADDTS_INVALID_PARAM 1 /* TSPEC invalid parameter status */ -+#define DOT11E_STATUS_ADDTS_REFUSED_NSBW 3 /* ADDTS refused (non-sufficient BW) */ -+#define DOT11E_STATUS_ADDTS_REFUSED_AWHILE 47 /* ADDTS refused but could retry later */ -+#ifdef BCMCCX -+#define CCX_STATUS_ASSOC_DENIED_UNKNOWN 0xc8 /* unspecified QoS related failure */ -+#define CCX_STATUS_ASSOC_DENIED_AP_POLICY 0xc9 /* TSPEC refused due to AP policy */ -+#define CCX_STATUS_ASSOC_DENIED_NO_BW 0xca /* Assoc denied due to AP insufficient BW */ -+#define CCX_STATUS_ASSOC_DENIED_BAD_PARAM 0xcb /* one or more TSPEC with invalid parameter */ -+#endif /* BCMCCX */ -+ -+/* 802.11e DELTS status code */ -+#define DOT11E_STATUS_QSTA_LEAVE_QBSS 36 /* STA leave QBSS */ -+#define DOT11E_STATUS_END_TS 37 /* END TS */ -+#define DOT11E_STATUS_UNKNOWN_TS 38 /* UNKNOWN TS */ -+#define DOT11E_STATUS_QSTA_REQ_TIMEOUT 39 /* STA ADDTS request timeout */ -+ -+ -+/* This marks the end of a packed structure section. */ -+#include -+ -+#endif /* _802_11e_CAC_H_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/802.11.h b/drivers/net/wireless/bcm4336/include/proto/802.11.h ---- a/drivers/net/wireless/bcm4336/include/proto/802.11.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/802.11.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/802.11.h b/drivers/net/wireless/bcm4336/include/proto/802.11.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/802.11.h @@ -0,0 +1,3865 @@ +/* + * $Copyright Open Broadcom Corporation$ @@ -194862,9 +196310,170 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/802.11.h b/drivers/net +#include + +#endif /* _802_11_H_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/802.1d.h b/drivers/net/wireless/bcm4336/include/proto/802.1d.h ---- a/drivers/net/wireless/bcm4336/include/proto/802.1d.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/802.1d.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/802.11_bta.h b/drivers/net/wireless/bcm4336/include/proto/802.11_bta.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/802.11_bta.h +@@ -0,0 +1,27 @@ ++/* ++ * BT-AMP (BlueTooth Alternate Mac and Phy) 802.11 PAL (Protocol Adaptation Layer) ++ * ++ * $Copyright Open Broadcom Corporation$ ++ * ++ * $Id: 802.11_bta.h 382882 2013-02-04 23:24:31Z $ ++*/ ++ ++#ifndef _802_11_BTA_H_ ++#define _802_11_BTA_H_ ++ ++#define BT_SIG_SNAP_MPROT "\xAA\xAA\x03\x00\x19\x58" ++ ++/* BT-AMP 802.11 PAL Protocols */ ++#define BTA_PROT_L2CAP 1 ++#define BTA_PROT_ACTIVITY_REPORT 2 ++#define BTA_PROT_SECURITY 3 ++#define BTA_PROT_LINK_SUPERVISION_REQUEST 4 ++#define BTA_PROT_LINK_SUPERVISION_REPLY 5 ++ ++/* BT-AMP 802.11 PAL AMP_ASSOC Type IDs */ ++#define BTA_TYPE_ID_MAC_ADDRESS 1 ++#define BTA_TYPE_ID_PREFERRED_CHANNELS 2 ++#define BTA_TYPE_ID_CONNECTED_CHANNELS 3 ++#define BTA_TYPE_ID_CAPABILITIES 4 ++#define BTA_TYPE_ID_VERSION 5 ++#endif /* _802_11_bta_h_ */ +diff --git a/drivers/net/wireless/bcm4336/include/proto/802.11e.h b/drivers/net/wireless/bcm4336/include/proto/802.11e.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/802.11e.h +@@ -0,0 +1,120 @@ ++/* ++ * 802.11e protocol header file ++ * ++ * $Copyright Open Broadcom Corporation$ ++ * ++ * $Id: 802.11e.h 382883 2013-02-04 23:26:09Z $ ++ */ ++ ++#ifndef _802_11e_H_ ++#define _802_11e_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* WME Traffic Specification (TSPEC) element */ ++#define WME_TSPEC_HDR_LEN 2 /* WME TSPEC header length */ ++#define WME_TSPEC_BODY_OFF 2 /* WME TSPEC body offset */ ++ ++#define WME_CATEGORY_CODE_OFFSET 0 /* WME Category code offset */ ++#define WME_ACTION_CODE_OFFSET 1 /* WME Action code offset */ ++#define WME_TOKEN_CODE_OFFSET 2 /* WME Token code offset */ ++#define WME_STATUS_CODE_OFFSET 3 /* WME Status code offset */ ++ ++BWL_PRE_PACKED_STRUCT struct tsinfo { ++ uint8 octets[3]; ++} BWL_POST_PACKED_STRUCT; ++ ++typedef struct tsinfo tsinfo_t; ++ ++/* 802.11e TSPEC IE */ ++typedef BWL_PRE_PACKED_STRUCT struct tspec { ++ uint8 oui[DOT11_OUI_LEN]; /* WME_OUI */ ++ uint8 type; /* WME_TYPE */ ++ uint8 subtype; /* WME_SUBTYPE_TSPEC */ ++ uint8 version; /* WME_VERSION */ ++ tsinfo_t tsinfo; /* TS Info bit field */ ++ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ ++ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ ++ uint32 min_srv_interval; /* Minimum Service Interval (us) */ ++ uint32 max_srv_interval; /* Maximum Service Interval (us) */ ++ uint32 inactivity_interval; /* Inactivity Interval (us) */ ++ uint32 suspension_interval; /* Suspension Interval (us) */ ++ uint32 srv_start_time; /* Service Start Time (us) */ ++ uint32 min_data_rate; /* Minimum Data Rate (bps) */ ++ uint32 mean_data_rate; /* Mean Data Rate (bps) */ ++ uint32 peak_data_rate; /* Peak Data Rate (bps) */ ++ uint32 max_burst_size; /* Maximum Burst Size (bytes) */ ++ uint32 delay_bound; /* Delay Bound (us) */ ++ uint32 min_phy_rate; /* Minimum PHY Rate (bps) */ ++ uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0-8.0) */ ++ uint16 medium_time; /* Medium Time (32 us/s periods) */ ++} BWL_POST_PACKED_STRUCT tspec_t; ++ ++#define WME_TSPEC_LEN (sizeof(tspec_t)) /* not including 2-bytes of header */ ++ ++/* ts_info */ ++/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */ ++#define TS_INFO_TID_SHIFT 1 /* TS info. TID shift */ ++#define TS_INFO_TID_MASK (0xf << TS_INFO_TID_SHIFT) /* TS info. TID mask */ ++#define TS_INFO_CONTENTION_SHIFT 7 /* TS info. contention shift */ ++#define TS_INFO_CONTENTION_MASK (0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */ ++#define TS_INFO_DIRECTION_SHIFT 5 /* TS info. direction shift */ ++#define TS_INFO_DIRECTION_MASK (0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */ ++#define TS_INFO_PSB_SHIFT 2 /* TS info. PSB bit Shift */ ++#define TS_INFO_PSB_MASK (1 << TS_INFO_PSB_SHIFT) /* TS info. PSB mask */ ++#define TS_INFO_UPLINK (0 << TS_INFO_DIRECTION_SHIFT) /* TS info. uplink */ ++#define TS_INFO_DOWNLINK (1 << TS_INFO_DIRECTION_SHIFT) /* TS info. downlink */ ++#define TS_INFO_BIDIRECTIONAL (3 << TS_INFO_DIRECTION_SHIFT) /* TS info. bidirectional */ ++#define TS_INFO_USER_PRIO_SHIFT 3 /* TS info. user priority shift */ ++/* TS info. user priority mask */ ++#define TS_INFO_USER_PRIO_MASK (0x7 << TS_INFO_USER_PRIO_SHIFT) ++ ++/* Macro to get/set bit(s) field in TSINFO */ ++#define WLC_CAC_GET_TID(pt) ((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT) ++#define WLC_CAC_GET_DIR(pt) ((((pt).octets[0]) & \ ++ TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT) ++#define WLC_CAC_GET_PSB(pt) ((((pt).octets[1]) & TS_INFO_PSB_MASK) >> TS_INFO_PSB_SHIFT) ++#define WLC_CAC_GET_USER_PRIO(pt) ((((pt).octets[1]) & \ ++ TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT) ++ ++#define WLC_CAC_SET_TID(pt, id) ((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \ ++ ((id) << TS_INFO_TID_SHIFT)) ++#define WLC_CAC_SET_USER_PRIO(pt, prio) ((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \ ++ ((prio) << TS_INFO_USER_PRIO_SHIFT)) ++ ++/* 802.11e QBSS Load IE */ ++#define QBSS_LOAD_IE_LEN 5 /* QBSS Load IE length */ ++#define QBSS_LOAD_AAC_OFF 3 /* AAC offset in IE */ ++ ++#define CAC_ADDTS_RESP_TIMEOUT 1000 /* default ADDTS response timeout in ms */ ++ /* DEFVAL dot11ADDTSResponseTimeout = 1s */ ++ ++/* 802.11e ADDTS status code */ ++#define DOT11E_STATUS_ADMISSION_ACCEPTED 0 /* TSPEC Admission accepted status */ ++#define DOT11E_STATUS_ADDTS_INVALID_PARAM 1 /* TSPEC invalid parameter status */ ++#define DOT11E_STATUS_ADDTS_REFUSED_NSBW 3 /* ADDTS refused (non-sufficient BW) */ ++#define DOT11E_STATUS_ADDTS_REFUSED_AWHILE 47 /* ADDTS refused but could retry later */ ++#ifdef BCMCCX ++#define CCX_STATUS_ASSOC_DENIED_UNKNOWN 0xc8 /* unspecified QoS related failure */ ++#define CCX_STATUS_ASSOC_DENIED_AP_POLICY 0xc9 /* TSPEC refused due to AP policy */ ++#define CCX_STATUS_ASSOC_DENIED_NO_BW 0xca /* Assoc denied due to AP insufficient BW */ ++#define CCX_STATUS_ASSOC_DENIED_BAD_PARAM 0xcb /* one or more TSPEC with invalid parameter */ ++#endif /* BCMCCX */ ++ ++/* 802.11e DELTS status code */ ++#define DOT11E_STATUS_QSTA_LEAVE_QBSS 36 /* STA leave QBSS */ ++#define DOT11E_STATUS_END_TS 37 /* END TS */ ++#define DOT11E_STATUS_UNKNOWN_TS 38 /* UNKNOWN TS */ ++#define DOT11E_STATUS_QSTA_REQ_TIMEOUT 39 /* STA ADDTS request timeout */ ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _802_11e_CAC_H_ */ +diff --git a/drivers/net/wireless/bcm4336/include/proto/802.1d.h b/drivers/net/wireless/bcm4336/include/proto/802.1d.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/802.1d.h @@ -0,0 +1,32 @@ +/* + * $Copyright Open Broadcom Corporation$ @@ -194898,9 +196507,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/802.1d.h b/drivers/net + (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio)) + +#endif /* _802_1_D__ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/802.3.h b/drivers/net/wireless/bcm4336/include/proto/802.3.h ---- a/drivers/net/wireless/bcm4336/include/proto/802.3.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/802.3.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/802.3.h b/drivers/net/wireless/bcm4336/include/proto/802.3.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/802.3.h @@ -0,0 +1,34 @@ +/* + * $Copyright Open Broadcom Corporation$ @@ -194936,9 +196547,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/802.3.h b/drivers/net/ +#include + +#endif /* #ifndef _802_3_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmdhcp.h b/drivers/net/wireless/bcm4336/include/proto/bcmdhcp.h ---- a/drivers/net/wireless/bcm4336/include/proto/bcmdhcp.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/bcmdhcp.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/bcmdhcp.h b/drivers/net/wireless/bcm4336/include/proto/bcmdhcp.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/bcmdhcp.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2014, Broadcom Corporation @@ -195017,9 +196630,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmdhcp.h b/drivers/ne +#define DHCP6_PORT_CLIENT 546 /* DHCP6 client UDP port */ + +#endif /* #ifndef _bcmdhcp_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmeth.h b/drivers/net/wireless/bcm4336/include/proto/bcmeth.h ---- a/drivers/net/wireless/bcm4336/include/proto/bcmeth.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/bcmeth.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/bcmeth.h b/drivers/net/wireless/bcm4336/include/proto/bcmeth.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/bcmeth.h @@ -0,0 +1,94 @@ +/* + * Broadcom Ethernettype protocol definitions @@ -195115,9 +196730,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmeth.h b/drivers/net +#include + +#endif /* _BCMETH_H_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmevent.h b/drivers/net/wireless/bcm4336/include/proto/bcmevent.h ---- a/drivers/net/wireless/bcm4336/include/proto/bcmevent.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/bcmevent.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/bcmevent.h b/drivers/net/wireless/bcm4336/include/proto/bcmevent.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/bcmevent.h @@ -0,0 +1,518 @@ +/* + * Broadcom Event protocol definitions @@ -195637,9 +197254,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmevent.h b/drivers/n +#include + +#endif /* _BCMEVENT_H_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmip.h b/drivers/net/wireless/bcm4336/include/proto/bcmip.h ---- a/drivers/net/wireless/bcm4336/include/proto/bcmip.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/bcmip.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/bcmip.h b/drivers/net/wireless/bcm4336/include/proto/bcmip.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/bcmip.h @@ -0,0 +1,227 @@ +/* + * $Copyright Open Broadcom Corporation$ @@ -195868,9 +197487,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmip.h b/drivers/net/ + ((uint32)addr & 0x000000ff) + +#endif /* _bcmip_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmipv6.h b/drivers/net/wireless/bcm4336/include/proto/bcmipv6.h ---- a/drivers/net/wireless/bcm4336/include/proto/bcmipv6.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/bcmipv6.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/bcmipv6.h b/drivers/net/wireless/bcm4336/include/proto/bcmipv6.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/bcmipv6.h @@ -0,0 +1,142 @@ +/* + * $Copyright Open Broadcom Corporation$ @@ -196014,9 +197635,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmipv6.h b/drivers/ne +} + +#endif /* !defined(_bcmipv6_h_) */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmtcp.h b/drivers/net/wireless/bcm4336/include/proto/bcmtcp.h ---- a/drivers/net/wireless/bcm4336/include/proto/bcmtcp.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/bcmtcp.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/bcmtcp.h b/drivers/net/wireless/bcm4336/include/proto/bcmtcp.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/bcmtcp.h @@ -0,0 +1,72 @@ +/* + * Fundamental constants relating to TCP Protocol @@ -196090,9 +197713,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmtcp.h b/drivers/net +#define IS_TCPSEQ_LT(a, b) !IS_TCPSEQ_GE(a, b) /* a < b */ + +#endif /* #ifndef _bcmtcp_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmudp.h b/drivers/net/wireless/bcm4336/include/proto/bcmudp.h ---- a/drivers/net/wireless/bcm4336/include/proto/bcmudp.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/bcmudp.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/bcmudp.h b/drivers/net/wireless/bcm4336/include/proto/bcmudp.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/bcmudp.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2014, Broadcom Corporation @@ -196140,9 +197765,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bcmudp.h b/drivers/net +#include + +#endif /* #ifndef _bcmudp_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bt_amp_hci.h b/drivers/net/wireless/bcm4336/include/proto/bt_amp_hci.h ---- a/drivers/net/wireless/bcm4336/include/proto/bt_amp_hci.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/bt_amp_hci.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/bt_amp_hci.h b/drivers/net/wireless/bcm4336/include/proto/bt_amp_hci.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/bt_amp_hci.h @@ -0,0 +1,423 @@ +/* + * BT-AMP (BlueTooth Alternate Mac and Phy) HCI (Host/Controller Interface) @@ -196567,9 +198194,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/bt_amp_hci.h b/drivers +#include + +#endif /* _bt_amp_hci_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/eapol.h b/drivers/net/wireless/bcm4336/include/proto/eapol.h ---- a/drivers/net/wireless/bcm4336/include/proto/eapol.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/eapol.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/eapol.h b/drivers/net/wireless/bcm4336/include/proto/eapol.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/eapol.h @@ -0,0 +1,194 @@ +/* + * 802.1x EAPOL definitions @@ -196765,9 +198394,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/eapol.h b/drivers/net/ +#include + +#endif /* _eapol_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/ethernet.h b/drivers/net/wireless/bcm4336/include/proto/ethernet.h ---- a/drivers/net/wireless/bcm4336/include/proto/ethernet.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/ethernet.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/ethernet.h b/drivers/net/wireless/bcm4336/include/proto/ethernet.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/ethernet.h @@ -0,0 +1,210 @@ +/* + * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. @@ -196979,9 +198610,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/ethernet.h b/drivers/n +#include + +#endif /* _NET_ETHERNET_H_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/p2p.h b/drivers/net/wireless/bcm4336/include/proto/p2p.h ---- a/drivers/net/wireless/bcm4336/include/proto/p2p.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/p2p.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/p2p.h b/drivers/net/wireless/bcm4336/include/proto/p2p.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/p2p.h @@ -0,0 +1,692 @@ +/* + * $Copyright Open Broadcom Corporation$ @@ -197675,9 +199308,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/p2p.h b/drivers/net/wi +#include + +#endif /* _P2P_H_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/sdspi.h b/drivers/net/wireless/bcm4336/include/proto/sdspi.h ---- a/drivers/net/wireless/bcm4336/include/proto/sdspi.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/sdspi.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/sdspi.h b/drivers/net/wireless/bcm4336/include/proto/sdspi.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/sdspi.h @@ -0,0 +1,57 @@ +/* + * SD-SPI Protocol Standard @@ -197736,9 +199371,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/sdspi.h b/drivers/net/ +#define SDSPI_START_BIT_MASK 0x80 + +#endif /* _SD_SPI_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/vlan.h b/drivers/net/wireless/bcm4336/include/proto/vlan.h ---- a/drivers/net/wireless/bcm4336/include/proto/vlan.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/vlan.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/vlan.h b/drivers/net/wireless/bcm4336/include/proto/vlan.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/vlan.h @@ -0,0 +1,77 @@ +/* + * 802.1Q VLAN protocol definitions @@ -197817,9 +199454,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/vlan.h b/drivers/net/w +} while (0) + +#endif /* _vlan_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/wpa.h b/drivers/net/wireless/bcm4336/include/proto/wpa.h ---- a/drivers/net/wireless/bcm4336/include/proto/wpa.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/proto/wpa.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/proto/wpa.h b/drivers/net/wireless/bcm4336/include/proto/wpa.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/proto/wpa.h @@ -0,0 +1,199 @@ +/* + * Fundamental types and constants relating to WPA @@ -198020,9 +199659,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/proto/wpa.h b/drivers/net/wi +#include + +#endif /* _proto_wpa_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbchipc.h b/drivers/net/wireless/bcm4336/include/sbchipc.h ---- a/drivers/net/wireless/bcm4336/include/sbchipc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/sbchipc.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/sbchipc.h b/drivers/net/wireless/bcm4336/include/sbchipc.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/sbchipc.h @@ -0,0 +1,3629 @@ +/* + * SiliconBackplane Chipcommon core hardware definitions. @@ -201653,9 +203294,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbchipc.h b/drivers/net/wire +#define GCI_GPIO_STS_VALUE (1 << GCI_GPIO_STS_VALUE_BIT) + +#endif /* _SBCHIPC_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbconfig.h b/drivers/net/wireless/bcm4336/include/sbconfig.h ---- a/drivers/net/wireless/bcm4336/include/sbconfig.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/sbconfig.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/sbconfig.h b/drivers/net/wireless/bcm4336/include/sbconfig.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/sbconfig.h @@ -0,0 +1,264 @@ +/* + * Broadcom SiliconBackplane hardware register definitions. @@ -201921,9 +203564,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbconfig.h b/drivers/net/wir +#define SB_VEND_BCM 0x4243 /* Broadcom's SB vendor code */ + +#endif /* _SBCONFIG_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbhnddma.h b/drivers/net/wireless/bcm4336/include/sbhnddma.h ---- a/drivers/net/wireless/bcm4336/include/sbhnddma.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/sbhnddma.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/sbhnddma.h b/drivers/net/wireless/bcm4336/include/sbhnddma.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/sbhnddma.h @@ -0,0 +1,399 @@ +/* + * Generic Broadcom Home Networking Division (HND) DMA engine HW interface @@ -202324,9 +203969,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbhnddma.h b/drivers/net/wir +} dma_rxh_t; + +#endif /* _sbhnddma_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbpcmcia.h b/drivers/net/wireless/bcm4336/include/sbpcmcia.h ---- a/drivers/net/wireless/bcm4336/include/sbpcmcia.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/sbpcmcia.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/sbpcmcia.h b/drivers/net/wireless/bcm4336/include/sbpcmcia.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/sbpcmcia.h @@ -0,0 +1,352 @@ +/* + * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions. @@ -202680,9 +204327,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbpcmcia.h b/drivers/net/wir +#define SBTMH_INT_STATUS 0x40000 /* sb interrupt status */ + +#endif /* _SBPCMCIA_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbsdio.h b/drivers/net/wireless/bcm4336/include/sbsdio.h ---- a/drivers/net/wireless/bcm4336/include/sbsdio.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/sbsdio.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/sbsdio.h b/drivers/net/wireless/bcm4336/include/sbsdio.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/sbsdio.h @@ -0,0 +1,168 @@ +/* + * SDIO device core hardware definitions. @@ -202852,9 +204501,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbsdio.h b/drivers/net/wirel +#define SBSDIO_CORE_ADDR_MASK 0x1FFFF /* sdio core function one address mask */ + +#endif /* _SBSDIO_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbsdpcmdev.h b/drivers/net/wireless/bcm4336/include/sbsdpcmdev.h ---- a/drivers/net/wireless/bcm4336/include/sbsdpcmdev.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/sbsdpcmdev.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/sbsdpcmdev.h b/drivers/net/wireless/bcm4336/include/sbsdpcmdev.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/sbsdpcmdev.h @@ -0,0 +1,281 @@ +/* + * Broadcom SiliconBackplane SDIO/PCMCIA hardware-specific @@ -203137,9 +204788,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbsdpcmdev.h b/drivers/net/w +#endif /* !defined(NDISVER) || (NDISVER < 0x0630) */ + +#endif /* _sbsdpcmdev_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbsocram.h b/drivers/net/wireless/bcm4336/include/sbsocram.h ---- a/drivers/net/wireless/bcm4336/include/sbsocram.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/sbsocram.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/sbsocram.h b/drivers/net/wireless/bcm4336/include/sbsocram.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/sbsocram.h @@ -0,0 +1,182 @@ +/* + * BCM47XX Sonics SiliconBackplane embedded ram core @@ -203323,9 +204976,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/sbsocram.h b/drivers/net/wir + + +#endif /* _SBSOCRAM_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/sdio.h b/drivers/net/wireless/bcm4336/include/sdio.h ---- a/drivers/net/wireless/bcm4336/include/sdio.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/sdio.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/sdio.h b/drivers/net/wireless/bcm4336/include/sdio.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/sdio.h @@ -0,0 +1,604 @@ +/* + * SDIO spec header file @@ -203931,9 +205586,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/sdio.h b/drivers/net/wireles + +#endif /* def BCMSDIO */ +#endif /* _SDIO_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/sdioh.h b/drivers/net/wireless/bcm4336/include/sdioh.h ---- a/drivers/net/wireless/bcm4336/include/sdioh.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/sdioh.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/sdioh.h b/drivers/net/wireless/bcm4336/include/sdioh.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/sdioh.h @@ -0,0 +1,427 @@ +/* + * SDIO Host Controller Spec header file @@ -204362,9 +206019,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/sdioh.h b/drivers/net/wirele +} adma1_dscr_t; + +#endif /* _SDIOH_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/sdiovar.h b/drivers/net/wireless/bcm4336/include/sdiovar.h ---- a/drivers/net/wireless/bcm4336/include/sdiovar.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/sdiovar.h 2018-05-06 08:49:50.630754337 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/sdiovar.h b/drivers/net/wireless/bcm4336/include/sdiovar.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/sdiovar.h @@ -0,0 +1,40 @@ +/* + * Structure used by apps whose drivers access SDIO drivers. @@ -204406,9 +206065,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/sdiovar.h b/drivers/net/wire +#include + +#endif /* _sdiovar_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/siutils.h b/drivers/net/wireless/bcm4336/include/siutils.h ---- a/drivers/net/wireless/bcm4336/include/siutils.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/siutils.h 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/siutils.h b/drivers/net/wireless/bcm4336/include/siutils.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/siutils.h @@ -0,0 +1,571 @@ +/* + * Misc utility routines for accessing the SOC Interconnects @@ -204981,9 +206642,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/siutils.h b/drivers/net/wire + + +#endif /* _siutils_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/trxhdr.h b/drivers/net/wireless/bcm4336/include/trxhdr.h ---- a/drivers/net/wireless/bcm4336/include/trxhdr.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/trxhdr.h 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/trxhdr.h b/drivers/net/wireless/bcm4336/include/trxhdr.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/trxhdr.h @@ -0,0 +1,74 @@ +/* + * TRX image file header format. @@ -205059,9 +206722,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/trxhdr.h b/drivers/net/wirel +typedef struct trx_header TRXHDR, *PTRXHDR; + +#endif /* _TRX_HDR_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/typedefs.h b/drivers/net/wireless/bcm4336/include/typedefs.h ---- a/drivers/net/wireless/bcm4336/include/typedefs.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/typedefs.h 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/typedefs.h b/drivers/net/wireless/bcm4336/include/typedefs.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/typedefs.h @@ -0,0 +1,321 @@ +/* + * $Copyright Open Broadcom Corporation$ @@ -205384,9 +207049,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/typedefs.h b/drivers/net/wir +*/ +#include +#endif /* _TYPEDEFS_H_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/wlfc_proto.h b/drivers/net/wireless/bcm4336/include/wlfc_proto.h ---- a/drivers/net/wireless/bcm4336/include/wlfc_proto.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/wlfc_proto.h 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/wlfc_proto.h b/drivers/net/wireless/bcm4336/include/wlfc_proto.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/wlfc_proto.h @@ -0,0 +1,283 @@ +/* +* $Copyright Open 2009 Broadcom Corporation$ @@ -205671,9 +207338,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/wlfc_proto.h b/drivers/net/w +#define WLFC_GET_REORDERSUPP(x) (((x) >> WLFC_MODE_REORDERSUPP_SHIFT) & 1) + +#endif /* __wlfc_proto_definitions_h__ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/include/wlioctl.h b/drivers/net/wireless/bcm4336/include/wlioctl.h ---- a/drivers/net/wireless/bcm4336/include/wlioctl.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/include/wlioctl.h 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/include/wlioctl.h b/drivers/net/wireless/bcm4336/include/wlioctl.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/include/wlioctl.h @@ -0,0 +1,5930 @@ +/* + * Custom OID/ioctl definitions for @@ -211605,78 +213274,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/include/wlioctl.h b/drivers/net/wire +#include + +#endif /* _wlioctl_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/Kconfig b/drivers/net/wireless/bcm4336/Kconfig ---- a/drivers/net/wireless/bcm4336/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/Kconfig 2018-05-06 08:49:50.618753851 +0200 -@@ -0,0 +1,65 @@ -+config BCMDHD -+ tristate "Broadcom FullMAC wireless cards support" -+ ---help--- -+ This module adds support for wireless adapters based on -+ Broadcom FullMAC chipset. -+ -+config BCMDHD_FW_PATH -+ depends on BCMDHD -+ string "Firmware path" -+ default "/system/etc/firmware/fw_bcmdhd.bin" -+ ---help--- -+ Path to the firmware file. -+ -+config BCMDHD_NVRAM_PATH -+ depends on BCMDHD -+ string "NVRAM path" -+ default "/system/etc/firmware/nvram.txt" -+ ---help--- -+ Path to the calibration file. -+ -+config BCMDHD_WEXT -+ bool "Enable WEXT support" -+ depends on BCMDHD && CFG80211 = n -+ select WIRELESS_EXT -+ select WEXT_PRIV -+ help -+ Enables WEXT support -+ -+choice -+ prompt "Enable Chip Interface" -+ depends on BCMDHD -+ default BCMDHD_SDIO -+ ---help--- -+ Enable Chip Interface. -+ -+config BCMDHD_SDIO -+ bool "SDIO bus interface support" -+ depends on BCMDHD && MMC -+ -+config BCMDHD_PCIE -+ bool "PCIe bus interface support" -+ depends on BCMDHD && PCI -+ -+endchoice -+ -+choice -+ depends on BCMDHD && BCMDHD_SDIO -+ prompt "Interrupt type" -+ default BCMDHD_OOB -+ ---help--- -+ Interrupt type -+ -+config BCMDHD_OOB -+ depends on BCMDHD && BCMDHD_SDIO -+ bool "Out-of-Band Interrupt" -+ ---help--- -+ Interrupt from WL_HOST_WAKE. -+ -+config BCMDHD_SDIO_IRQ -+ depends on BCMDHD && BCMDHD_SDIO -+ bool "In-Band Interrupt" -+ ---help--- -+ Interrupt from SDIO DAT[1] -+ -+endchoice -diff -ENwbur a/drivers/net/wireless/bcm4336/linux_osl.c b/drivers/net/wireless/bcm4336/linux_osl.c ---- a/drivers/net/wireless/bcm4336/linux_osl.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/linux_osl.c 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/linux_osl.c b/drivers/net/wireless/bcm4336/linux_osl.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/linux_osl.c @@ -0,0 +1,2488 @@ +/* + * Linux OS Independent Layer @@ -214166,119 +215768,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/linux_osl.c b/drivers/net/wireless/b +} + +#endif /* BCM_SECURE_DMA */ -diff -ENwbur a/drivers/net/wireless/bcm4336/Makefile b/drivers/net/wireless/bcm4336/Makefile ---- a/drivers/net/wireless/bcm4336/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/Makefile 2018-05-06 08:49:50.618753851 +0200 -@@ -0,0 +1,106 @@ -+# bcmdhd -+# 1. WL_IFACE_COMB_NUM_CHANNELS must be added if Android version is 4.4 with Kernel version 3.0~3.4, -+# otherwise please remove it. -+ -+#CONFIG_BCMDHD_SDIO := y -+#CONFIG_BCMDHD_PCIE := y -+ -+DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER -DSDTEST \ -+ -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE \ -+ -DDHDTHREAD -DDHD_DEBUG -DSHOW_EVENTS -DBCMDBG -DGET_OTP_MAC_ENABLE \ -+ -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DSUPPORT_PM2_ONLY \ -+ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DPNO_SUPPORT -DDHDTCPACK_SUPPRESS \ -+ -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DRXFRAME_THREAD \ -+ -DSET_RANDOM_MAC_SOFTAP \ -+ -DENABLE_INSMOD_NO_FW_LOAD \ -+ -Idrivers/net/wireless/bcm4336 -Idrivers/net/wireless/bcm4336/include -+ -+DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o \ -+ dhd_linux.o dhd_linux_platdev.o dhd_linux_sched.o dhd_pno.o \ -+ dhd_common.o dhd_ip.o dhd_linux_wq.o dhd_custom_gpio.o \ -+ bcmevent.o hndpmu.o linux_osl.o wldev_common.o wl_android.o \ -+ hnd_pktq.o hnd_pktpool.o dhd_config.o -+ -+ifneq ($(CONFIG_BCMDHD_SDIO),) -+DHDCFLAGS += \ -+ -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR \ -+ -DBDC -DPROP_TXSTATUS -DDHD_USE_IDLECOUNT -DBCMSDIOH_TXGLOM \ -+ -DCUSTOM_SDIO_F2_BLKSIZE=128 -+ -+DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o \ -+ dhd_sdio.o dhd_cdc.o dhd_wlfc.o -+ -+ifeq ($(CONFIG_BCMDHD_OOB),y) -+DHDCFLAGS += -DOOB_INTR_ONLY -DHW_OOB -DCUSTOMER_OOB -+ifeq ($(CONFIG_BCMDHD_DISABLE_WOWLAN),y) -+DHDCFLAGS += -DDISABLE_WOWLAN -+endif -+else -+DHDCFLAGS += -DSDIO_ISR_THREAD -+endif -+endif -+ -+ifneq ($(CONFIG_BCMDHD_PCIE),) -+DHDCFLAGS += \ -+ -DPCIE_FULL_DONGLE -DBCMPCIE -DSHOW_LOGTRACE -DDPCIE_TX_DEFERRAL \ -+ -DCUSTOM_DPC_PRIO_SETTING=-1 -+ -+DHDOFILES += dhd_pcie.o dhd_pcie_linux.o pcie_core.o dhd_flowring.o \ -+ dhd_msgbuf.o -+endif -+ -+obj-$(CONFIG_BCMDHD) += bcmdhd.o -+bcmdhd-objs += $(DHDOFILES) -+ -+ifeq ($(CONFIG_MACH_MINI2451),y) -+DHDOFILES += dhd_gpio.o -+DHDCFLAGS += -DCUSTOMER_HW -DDHD_OF_SUPPORT -+#DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI -+DHDCFLAGS += -DPOWERUP_MAX_RETRY=1 -DPOWERUP_WAIT_MS=1200 -+endif -+ -+ifeq ($(CONFIG_ARCH_S5P6818),y) -+DHDOFILES += dhd_gpio.o -+DHDCFLAGS += -DCUSTOMER_HW -DDHD_OF_SUPPORT -+#DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI -+DHDCFLAGS += -DPOWERUP_MAX_RETRY=1 -DPOWERUP_WAIT_MS=1200 -+DHDCFLAGS += -DPOWER_OFF_IN_SUSPEND -+DHDCFLAGS += -DDHD_PRINTF_LL=KERN_DEBUG -+endif -+ -+ifeq ($(CONFIG_BCMDHD_AG),y) -+DHDCFLAGS += -DBAND_AG -+endif -+ -+ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y) -+# add dhd_static_buf to kernel image build -+#obj-y += dhd_static_buf.o -+DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DENHANCED_STATIC_BUF -+endif -+ -+ifneq ($(CONFIG_WIRELESS_EXT),) -+bcmdhd-objs += wl_iw.o -+DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW -+endif -+ifneq ($(CONFIG_CFG80211),) -+bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o wl_cfg_btcoex.o -+bcmdhd-objs += dhd_cfg80211.o dhd_cfg_vendor.o -+DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT -DWL_ENABLE_P2P_IF -+DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS -+DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-65 -+DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=15 -+DHDCFLAGS += -DCUSTOM_KEEP_ALIVE_SETTING=28000 -+DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=7 -+DHDCFLAGS += -DWL_SUPPORT_AUTO_CHANNEL -+DHDCFLAGS += -DWL_SUPPORT_BACKPORTED_KPATCHES -+DHDCFLAGS += -DESCAN_RESULT_PATCH -+DHDCFLAGS += -DVSDB -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST -+DHDCFLAGS += -DWLTDLS -DMIRACAST_AMPDU_SIZE=8 -DPROP_TXSTATUS_VSDB -+endif -+EXTRA_CFLAGS = $(DHDCFLAGS) -+ifeq ($(CONFIG_BCMDHD),m) -+DHDCFLAGS += -DMULTIPLE_SUPPLICANT -+EXTRA_LDFLAGS += --strip-debug -+else -+DHDCFLAGS += -DBUILD_IN_KERNEL -+endif -diff -ENwbur a/drivers/net/wireless/bcm4336/pcie_core.c b/drivers/net/wireless/bcm4336/pcie_core.c ---- a/drivers/net/wireless/bcm4336/pcie_core.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/pcie_core.c 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/pcie_core.c b/drivers/net/wireless/bcm4336/pcie_core.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/pcie_core.c @@ -0,0 +1,70 @@ +/** @file pcie_core.c + * @@ -214350,9 +215844,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/pcie_core.c b/drivers/net/wireless/b +} + +#endif /* BCMDRIVER */ -diff -ENwbur a/drivers/net/wireless/bcm4336/sbutils.c b/drivers/net/wireless/bcm4336/sbutils.c ---- a/drivers/net/wireless/bcm4336/sbutils.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/sbutils.c 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/sbutils.c b/drivers/net/wireless/bcm4336/sbutils.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/sbutils.c @@ -0,0 +1,1087 @@ +/* + * Misc utility routines for accessing chip-specific features @@ -215441,9 +216937,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/sbutils.c b/drivers/net/wireless/bcm + INTR_RESTORE(sii, intr_val); +} +#endif -diff -ENwbur a/drivers/net/wireless/bcm4336/siutils.c b/drivers/net/wireless/bcm4336/siutils.c ---- a/drivers/net/wireless/bcm4336/siutils.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/siutils.c 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/siutils.c b/drivers/net/wireless/bcm4336/siutils.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/siutils.c @@ -0,0 +1,3022 @@ +/* + * Misc utility routines for accessing chip-specific features @@ -218467,9 +219965,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/siutils.c b/drivers/net/wireless/bcm +si_pcie_prep_D3(si_t *sih, bool enter_D3) +{ +} -diff -ENwbur a/drivers/net/wireless/bcm4336/siutils_priv.h b/drivers/net/wireless/bcm4336/siutils_priv.h ---- a/drivers/net/wireless/bcm4336/siutils_priv.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/siutils_priv.h 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/siutils_priv.h b/drivers/net/wireless/bcm4336/siutils_priv.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/siutils_priv.h @@ -0,0 +1,265 @@ +/* + * Include file private to the SOC Interconnect support files. @@ -218736,9 +220236,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/siutils_priv.h b/drivers/net/wireles +#define ub_dumpregs(a, b) do {} while (0) + +#endif /* _siutils_priv_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/uamp_api.h b/drivers/net/wireless/bcm4336/uamp_api.h ---- a/drivers/net/wireless/bcm4336/uamp_api.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/uamp_api.h 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/uamp_api.h b/drivers/net/wireless/bcm4336/uamp_api.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/uamp_api.h @@ -0,0 +1,160 @@ +/* + * Name: uamp_api.h @@ -218900,9 +220402,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/uamp_api.h b/drivers/net/wireless/bc +#endif + +#endif /* UAMP_API_H */ -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_android.c b/drivers/net/wireless/bcm4336/wl_android.c ---- a/drivers/net/wireless/bcm4336/wl_android.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_android.c 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_android.c b/drivers/net/wireless/bcm4336/wl_android.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_android.c @@ -0,0 +1,3690 @@ +/* + * Linux cfg80211 driver - Android related functions @@ -222594,9 +224098,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_android.c b/drivers/net/wireless/ + wl_free_bss_cache(bss_cache_ctrl); +} +#endif -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_android.h b/drivers/net/wireless/bcm4336/wl_android.h ---- a/drivers/net/wireless/bcm4336/wl_android.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_android.h 2018-05-06 08:49:50.634754499 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_android.h b/drivers/net/wireless/bcm4336/wl_android.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_android.h @@ -0,0 +1,180 @@ +/* + * Linux cfg80211 driver - Android related functions @@ -222778,9 +224284,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_android.h b/drivers/net/wireless/ +void wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl); +#endif +#endif /* _wl_android_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfg80211.c b/drivers/net/wireless/bcm4336/wl_cfg80211.c ---- a/drivers/net/wireless/bcm4336/wl_cfg80211.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_cfg80211.c 2018-05-06 08:49:50.638754662 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_cfg80211.c b/drivers/net/wireless/bcm4336/wl_cfg80211.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_cfg80211.c @@ -0,0 +1,15542 @@ +/* + * Linux cfg80211 driver @@ -238324,9 +239832,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfg80211.c b/drivers/net/wireless + return wl_cfgnan_cmd_handler(ndev, g_bcm_cfg, cmd, cmd_len); +} +#endif /* WL_NAN */ -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfg80211.h b/drivers/net/wireless/bcm4336/wl_cfg80211.h ---- a/drivers/net/wireless/bcm4336/wl_cfg80211.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_cfg80211.h 2018-05-06 08:49:50.638754662 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_cfg80211.h b/drivers/net/wireless/bcm4336/wl_cfg80211.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_cfg80211.h @@ -0,0 +1,1076 @@ +/* + * Linux cfg80211 driver @@ -239404,9 +240914,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfg80211.h b/drivers/net/wireless +#endif /* WL_CFG80211_P2P_DEV_IF */ + +#endif /* _wl_cfg80211_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfg_btcoex.c b/drivers/net/wireless/bcm4336/wl_cfg_btcoex.c ---- a/drivers/net/wireless/bcm4336/wl_cfg_btcoex.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_cfg_btcoex.c 2018-05-06 08:49:50.638754662 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_cfg_btcoex.c b/drivers/net/wireless/bcm4336/wl_cfg_btcoex.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_cfg_btcoex.c @@ -0,0 +1,538 @@ +/* + * Linux cfg80211 driver - Dongle Host Driver (DHD) related @@ -239946,9 +241458,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfg_btcoex.c b/drivers/net/wirele + + return (strlen("OK")); +} -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfgp2p.c b/drivers/net/wireless/bcm4336/wl_cfgp2p.c ---- a/drivers/net/wireless/bcm4336/wl_cfgp2p.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_cfgp2p.c 2018-05-06 08:49:50.638754662 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_cfgp2p.c b/drivers/net/wireless/bcm4336/wl_cfgp2p.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_cfgp2p.c @@ -0,0 +1,2931 @@ +/* + * Linux cfgp2p driver @@ -242881,9 +244395,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfgp2p.c b/drivers/net/wireless/b + return 0; +} +#endif /* WL_CFG80211_P2P_DEV_IF */ -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfgp2p.h b/drivers/net/wireless/bcm4336/wl_cfgp2p.h ---- a/drivers/net/wireless/bcm4336/wl_cfgp2p.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_cfgp2p.h 2018-05-06 08:49:50.638754662 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_cfgp2p.h b/drivers/net/wireless/bcm4336/wl_cfgp2p.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_cfgp2p.h @@ -0,0 +1,398 @@ +/* + * Linux cfgp2p driver @@ -243283,9 +244799,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfgp2p.h b/drivers/net/wireless/b +#define IS_P2P_SSID(ssid, len) (!memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) && \ + (len == WL_P2P_WILDCARD_SSID_LEN)) +#endif /* _wl_cfgp2p_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfgvendor.h b/drivers/net/wireless/bcm4336/wl_cfgvendor.h ---- a/drivers/net/wireless/bcm4336/wl_cfgvendor.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_cfgvendor.h 2018-05-06 08:49:50.638754662 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_cfgvendor.h b/drivers/net/wireless/bcm4336/wl_cfgvendor.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_cfgvendor.h @@ -0,0 +1,33 @@ +/* + * Linux cfg80211 Vendor Extension Code @@ -243320,9 +244838,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_cfgvendor.h b/drivers/net/wireles +#endif /* VENDOR_EXT_SUPPORT */ + +#endif /* _wl_cfgvendor_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_dbg.h b/drivers/net/wireless/bcm4336/wl_dbg.h ---- a/drivers/net/wireless/bcm4336/wl_dbg.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_dbg.h 2018-05-06 08:49:50.638754662 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_dbg.h b/drivers/net/wireless/bcm4336/wl_dbg.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_dbg.h @@ -0,0 +1,392 @@ +/* + * Minimal debug/trace/assert driver definitions for @@ -243716,493 +245236,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_dbg.h b/drivers/net/wireless/bcm4 +extern uint32 wl_msg_level; +extern uint32 wl_msg_level2; +#endif /* _wl_dbg_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/wldev_common.c b/drivers/net/wireless/bcm4336/wldev_common.c ---- a/drivers/net/wireless/bcm4336/wldev_common.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wldev_common.c 2018-05-06 08:49:50.638754662 +0200 -@@ -0,0 +1,370 @@ -+/* -+ * Common function shared by Linux WEXT, cfg80211 and p2p drivers -+ * -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * $Id: wldev_common.c 504503 2014-09-24 11:28:56Z $ -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define htod32(i) (i) -+#define htod16(i) (i) -+#define dtoh32(i) (i) -+#define dtoh16(i) (i) -+#define htodchanspec(i) (i) -+#define dtohchanspec(i) (i) -+ -+#define WLDEV_ERROR(args) \ -+ do { \ -+ printk(KERN_ERR "WLDEV-ERROR) %s : ", __func__); \ -+ printk args; \ -+ } while (0) -+ -+extern int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd); -+ -+s32 wldev_ioctl( -+ struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set) -+{ -+ s32 ret = 0; -+ struct wl_ioctl ioc; -+ -+ -+ memset(&ioc, 0, sizeof(ioc)); -+ ioc.cmd = cmd; -+ ioc.buf = arg; -+ ioc.len = len; -+ ioc.set = set; -+ -+ ret = dhd_ioctl_entry_local(dev, &ioc, cmd); -+ -+ return ret; -+} -+ -+/* Format a iovar buffer, not bsscfg indexed. The bsscfg index will be -+ * taken care of in dhd_ioctl_entry. Internal use only, not exposed to -+ * wl_iw, wl_cfg80211 and wl_cfgp2p -+ */ -+static s32 wldev_mkiovar( -+ s8 *iovar_name, s8 *param, s32 paramlen, -+ s8 *iovar_buf, u32 buflen) -+{ -+ s32 iolen = 0; -+ -+ iolen = bcm_mkiovar(iovar_name, param, paramlen, iovar_buf, buflen); -+ return iolen; -+} -+ -+s32 wldev_iovar_getbuf( -+ struct net_device *dev, s8 *iovar_name, -+ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) -+{ -+ s32 ret = 0; -+ if (buf_sync) { -+ mutex_lock(buf_sync); -+ } -+ wldev_mkiovar(iovar_name, param, paramlen, buf, buflen); -+ ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE); -+ if (buf_sync) -+ mutex_unlock(buf_sync); -+ return ret; -+} -+ -+ -+s32 wldev_iovar_setbuf( -+ struct net_device *dev, s8 *iovar_name, -+ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) -+{ -+ s32 ret = 0; -+ s32 iovar_len; -+ if (buf_sync) { -+ mutex_lock(buf_sync); -+ } -+ iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen); -+ if (iovar_len > 0) -+ ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE); -+ else -+ ret = BCME_BUFTOOSHORT; -+ -+ if (buf_sync) -+ mutex_unlock(buf_sync); -+ return ret; -+} -+ -+s32 wldev_iovar_setint( -+ struct net_device *dev, s8 *iovar, s32 val) -+{ -+ s8 iovar_buf[WLC_IOCTL_SMLEN]; -+ -+ val = htod32(val); -+ memset(iovar_buf, 0, sizeof(iovar_buf)); -+ return wldev_iovar_setbuf(dev, iovar, &val, sizeof(val), iovar_buf, -+ sizeof(iovar_buf), NULL); -+} -+ -+ -+s32 wldev_iovar_getint( -+ struct net_device *dev, s8 *iovar, s32 *pval) -+{ -+ s8 iovar_buf[WLC_IOCTL_SMLEN]; -+ s32 err; -+ -+ memset(iovar_buf, 0, sizeof(iovar_buf)); -+ err = wldev_iovar_getbuf(dev, iovar, pval, sizeof(*pval), iovar_buf, -+ sizeof(iovar_buf), NULL); -+ if (err == 0) -+ { -+ memcpy(pval, iovar_buf, sizeof(*pval)); -+ *pval = dtoh32(*pval); -+ } -+ return err; -+} -+ -+/** Format a bsscfg indexed iovar buffer. The bsscfg index will be -+ * taken care of in dhd_ioctl_entry. Internal use only, not exposed to -+ * wl_iw, wl_cfg80211 and wl_cfgp2p -+ */ -+s32 wldev_mkiovar_bsscfg( -+ const s8 *iovar_name, s8 *param, s32 paramlen, -+ s8 *iovar_buf, s32 buflen, s32 bssidx) -+{ -+ const s8 *prefix = "bsscfg:"; -+ s8 *p; -+ u32 prefixlen; -+ u32 namelen; -+ u32 iolen; -+ -+ if (bssidx == 0) { -+ return wldev_mkiovar((s8*)iovar_name, (s8 *)param, paramlen, -+ (s8 *) iovar_buf, buflen); -+ } -+ -+ prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */ -+ namelen = (u32) strlen(iovar_name) + 1; /* lengh of iovar name + null */ -+ iolen = prefixlen + namelen + sizeof(u32) + paramlen; -+ -+ if (buflen < 0 || iolen > (u32)buflen) -+ { -+ WLDEV_ERROR(("%s: buffer is too short\n", __FUNCTION__)); -+ return BCME_BUFTOOSHORT; -+ } -+ -+ p = (s8 *)iovar_buf; -+ -+ /* copy prefix, no null */ -+ memcpy(p, prefix, prefixlen); -+ p += prefixlen; -+ -+ /* copy iovar name including null */ -+ memcpy(p, iovar_name, namelen); -+ p += namelen; -+ -+ /* bss config index as first param */ -+ bssidx = htod32(bssidx); -+ memcpy(p, &bssidx, sizeof(u32)); -+ p += sizeof(u32); -+ -+ /* parameter buffer follows */ -+ if (paramlen) -+ memcpy(p, param, paramlen); -+ -+ return iolen; -+ -+} -+ -+s32 wldev_iovar_getbuf_bsscfg( -+ struct net_device *dev, s8 *iovar_name, -+ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync) -+{ -+ s32 ret = 0; -+ if (buf_sync) { -+ mutex_lock(buf_sync); -+ } -+ -+ wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx); -+ ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE); -+ if (buf_sync) { -+ mutex_unlock(buf_sync); -+ } -+ return ret; -+ -+} -+ -+s32 wldev_iovar_setbuf_bsscfg( -+ struct net_device *dev, s8 *iovar_name, -+ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync) -+{ -+ s32 ret = 0; -+ s32 iovar_len; -+ if (buf_sync) { -+ mutex_lock(buf_sync); -+ } -+ iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx); -+ if (iovar_len > 0) -+ ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE); -+ else { -+ ret = BCME_BUFTOOSHORT; -+ } -+ -+ if (buf_sync) { -+ mutex_unlock(buf_sync); -+ } -+ return ret; -+} -+ -+s32 wldev_iovar_setint_bsscfg( -+ struct net_device *dev, s8 *iovar, s32 val, s32 bssidx) -+{ -+ s8 iovar_buf[WLC_IOCTL_SMLEN]; -+ -+ val = htod32(val); -+ memset(iovar_buf, 0, sizeof(iovar_buf)); -+ return wldev_iovar_setbuf_bsscfg(dev, iovar, &val, sizeof(val), iovar_buf, -+ sizeof(iovar_buf), bssidx, NULL); -+} -+ -+ -+s32 wldev_iovar_getint_bsscfg( -+ struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx) -+{ -+ s8 iovar_buf[WLC_IOCTL_SMLEN]; -+ s32 err; -+ -+ memset(iovar_buf, 0, sizeof(iovar_buf)); -+ err = wldev_iovar_getbuf_bsscfg(dev, iovar, pval, sizeof(*pval), iovar_buf, -+ sizeof(iovar_buf), bssidx, NULL); -+ if (err == 0) -+ { -+ memcpy(pval, iovar_buf, sizeof(*pval)); -+ *pval = dtoh32(*pval); -+ } -+ return err; -+} -+ -+int wldev_get_link_speed( -+ struct net_device *dev, int *plink_speed) -+{ -+ int error; -+ -+ if (!plink_speed) -+ return -ENOMEM; -+ error = wldev_ioctl(dev, WLC_GET_RATE, plink_speed, sizeof(int), 0); -+ if (unlikely(error)) -+ return error; -+ -+ /* Convert internal 500Kbps to Kbps */ -+ *plink_speed *= 500; -+ return error; -+} -+ -+int wldev_get_rssi( -+ struct net_device *dev, int *prssi) -+{ -+ scb_val_t scb_val; -+ int error; -+ -+ if (!prssi) -+ return -ENOMEM; -+ bzero(&scb_val, sizeof(scb_val_t)); -+ -+ error = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t), 0); -+ if (unlikely(error)) -+ return error; -+ -+ *prssi = dtoh32(scb_val.val); -+ return error; -+} -+ -+int wldev_get_ssid( -+ struct net_device *dev, wlc_ssid_t *pssid) -+{ -+ int error; -+ -+ if (!pssid) -+ return -ENOMEM; -+ error = wldev_ioctl(dev, WLC_GET_SSID, pssid, sizeof(wlc_ssid_t), 0); -+ if (unlikely(error)) -+ return error; -+ pssid->SSID_len = dtoh32(pssid->SSID_len); -+ return error; -+} -+ -+int wldev_get_band( -+ struct net_device *dev, uint *pband) -+{ -+ int error; -+ -+ error = wldev_ioctl(dev, WLC_GET_BAND, pband, sizeof(uint), 0); -+ return error; -+} -+ -+int wldev_set_band( -+ struct net_device *dev, uint band) -+{ -+ int error = -1; -+ -+ if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) { -+ error = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true); -+ if (!error) -+ dhd_bus_band_set(dev, band); -+ } -+ return error; -+} -+ -+int wldev_set_country( -+ struct net_device *dev, char *country_code, bool notify, bool user_enforced) -+{ -+ int error = -1; -+ wl_country_t cspec = {{0}, 0, {0}}; -+ scb_val_t scbval; -+ char smbuf[WLC_IOCTL_SMLEN]; -+ -+ if (!country_code) -+ return error; -+ -+ bzero(&scbval, sizeof(scb_val_t)); -+ error = wldev_iovar_getbuf(dev, "country", NULL, 0, &cspec, sizeof(cspec), NULL); -+ if (error < 0) { -+ WLDEV_ERROR(("%s: get country failed = %d\n", __FUNCTION__, error)); -+ return error; -+ } -+ -+ if ((error < 0) || -+ (strncmp(country_code, cspec.country_abbrev, WLC_CNTRY_BUF_SZ) != 0)) { -+ -+ if (user_enforced) { -+ bzero(&scbval, sizeof(scb_val_t)); -+ error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); -+ if (error < 0) { -+ WLDEV_ERROR(("%s: set country failed due to Disassoc error %d\n", -+ __FUNCTION__, error)); -+ return error; -+ } -+ } -+ -+ cspec.rev = -1; -+ memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ); -+ memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ); -+ dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec); -+ error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec), -+ smbuf, sizeof(smbuf), NULL); -+ if (error < 0) { -+ WLDEV_ERROR(("%s: set country for %s as %s rev %d failed\n", -+ __FUNCTION__, country_code, cspec.ccode, cspec.rev)); -+ return error; -+ } -+ dhd_conf_fix_country(dhd_get_pub(dev)); -+ dhd_conf_get_country(dhd_get_pub(dev), &cspec); -+ dhd_bus_country_set(dev, &cspec, notify); -+ WLDEV_ERROR(("%s: set country for %s as %s rev %d\n", -+ __FUNCTION__, country_code, cspec.ccode, cspec.rev)); -+ } -+ return 0; -+} -diff -ENwbur a/drivers/net/wireless/bcm4336/wldev_common.h b/drivers/net/wireless/bcm4336/wldev_common.h ---- a/drivers/net/wireless/bcm4336/wldev_common.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wldev_common.h 2018-05-06 08:49:50.638754662 +0200 -@@ -0,0 +1,106 @@ -+/* -+ * Common function shared by Linux WEXT, cfg80211 and p2p drivers -+ * -+ * $Copyright Open Broadcom Corporation$ -+ * -+ * $Id: wldev_common.h 504503 2014-09-24 11:28:56Z $ -+ */ -+#ifndef __WLDEV_COMMON_H__ -+#define __WLDEV_COMMON_H__ -+ -+#include -+ -+/* wl_dev_ioctl - get/set IOCTLs, will call net_device's do_ioctl (or -+ * netdev_ops->ndo_do_ioctl in new kernels) -+ * @dev: the net_device handle -+ */ -+s32 wldev_ioctl( -+ struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set); -+ -+/** Retrieve named IOVARs, this function calls wl_dev_ioctl with -+ * WLC_GET_VAR IOCTL code -+ */ -+s32 wldev_iovar_getbuf( -+ struct net_device *dev, s8 *iovar_name, -+ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync); -+ -+/** Set named IOVARs, this function calls wl_dev_ioctl with -+ * WLC_SET_VAR IOCTL code -+ */ -+s32 wldev_iovar_setbuf( -+ struct net_device *dev, s8 *iovar_name, -+ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync); -+ -+s32 wldev_iovar_setint( -+ struct net_device *dev, s8 *iovar, s32 val); -+ -+s32 wldev_iovar_getint( -+ struct net_device *dev, s8 *iovar, s32 *pval); -+ -+/** The following function can be implemented if there is a need for bsscfg -+ * indexed IOVARs -+ */ -+ -+s32 wldev_mkiovar_bsscfg( -+ const s8 *iovar_name, s8 *param, s32 paramlen, -+ s8 *iovar_buf, s32 buflen, s32 bssidx); -+ -+/** Retrieve named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with -+ * WLC_GET_VAR IOCTL code -+ */ -+s32 wldev_iovar_getbuf_bsscfg( -+ struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen, -+ void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync); -+ -+/** Set named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with -+ * WLC_SET_VAR IOCTL code -+ */ -+s32 wldev_iovar_setbuf_bsscfg( -+ struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen, -+ void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync); -+ -+s32 wldev_iovar_getint_bsscfg( -+ struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx); -+ -+s32 wldev_iovar_setint_bsscfg( -+ struct net_device *dev, s8 *iovar, s32 val, s32 bssidx); -+ -+extern int dhd_net_set_fw_path(struct net_device *dev, char *fw); -+extern int dhd_net_bus_suspend(struct net_device *dev); -+extern int dhd_net_bus_resume(struct net_device *dev, uint8 stage); -+extern int dhd_net_wifi_platform_set_power(struct net_device *dev, bool on, -+ unsigned long delay_msec); -+extern void dhd_get_customized_country_code(struct net_device *dev, char *country_iso_code, -+ wl_country_t *cspec); -+extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, bool notify); -+extern void dhd_bus_band_set(struct net_device *dev, uint band); -+extern int wldev_set_country(struct net_device *dev, char *country_code, bool notify, -+ bool user_enforced); -+extern int net_os_wake_lock(struct net_device *dev); -+extern int net_os_wake_unlock(struct net_device *dev); -+extern int net_os_wake_lock_timeout(struct net_device *dev); -+extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val); -+extern int net_os_set_dtim_skip(struct net_device *dev, int val); -+extern int net_os_set_suspend_disable(struct net_device *dev, int val); -+extern int net_os_set_suspend(struct net_device *dev, int val, int force); -+extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, -+ int max, int *bytes_left); -+ -+/* Get the link speed from dongle, speed is in kpbs */ -+int wldev_get_link_speed(struct net_device *dev, int *plink_speed); -+ -+int wldev_get_rssi(struct net_device *dev, int *prssi); -+ -+int wldev_get_ssid(struct net_device *dev, wlc_ssid_t *pssid); -+ -+int wldev_get_band(struct net_device *dev, uint *pband); -+ -+int wldev_set_band(struct net_device *dev, uint band); -+ -+#if defined(CUSTOM_PLATFORM_NV_TEGRA) -+int wldev_miracast_tuning(struct net_device *dev, char *command, int total_len); -+int wldev_get_assoc_resp_ie(struct net_device *dev, char *command, int total_len); -+int wldev_get_rx_rate_stats(struct net_device *dev, char *command, int total_len); -+#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */ -+ -+#endif /* __WLDEV_COMMON_H__ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_iw.c b/drivers/net/wireless/bcm4336/wl_iw.c ---- a/drivers/net/wireless/bcm4336/wl_iw.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_iw.c 2018-05-06 08:49:50.638754662 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_iw.c b/drivers/net/wireless/bcm4336/wl_iw.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_iw.c @@ -0,0 +1,3909 @@ +/* + * Linux Wireless Extensions support @@ -248113,9 +249151,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_iw.c b/drivers/net/wireless/bcm43 +} + +#endif /* USE_IW */ -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_iw.h b/drivers/net/wireless/bcm4336/wl_iw.h ---- a/drivers/net/wireless/bcm4336/wl_iw.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_iw.h 2018-05-06 08:49:50.638754662 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_iw.h b/drivers/net/wireless/bcm4336/wl_iw.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_iw.h @@ -0,0 +1,143 @@ +/* + * Linux Wireless Extensions support @@ -248260,9 +249300,11 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_iw.h b/drivers/net/wireless/bcm43 +#endif + +#endif /* _wl_iw_h_ */ -diff -ENwbur a/drivers/net/wireless/bcm4336/wl_linux_mon.c b/drivers/net/wireless/bcm4336/wl_linux_mon.c ---- a/drivers/net/wireless/bcm4336/wl_linux_mon.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/net/wireless/bcm4336/wl_linux_mon.c 2018-05-06 08:49:50.638754662 +0200 +diff --git a/drivers/net/wireless/bcm4336/wl_linux_mon.c b/drivers/net/wireless/bcm4336/wl_linux_mon.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wl_linux_mon.c @@ -0,0 +1,385 @@ +/* + * Broadcom Dongle Host Driver (DHD), Linux monitor network interface @@ -248649,32 +249691,521 @@ diff -ENwbur a/drivers/net/wireless/bcm4336/wl_linux_mon.c b/drivers/net/wireles + mutex_unlock(&g_monitor.lock); + return 0; +} -diff -ENwbur a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c 2018-05-06 08:47:37.769361990 +0200 -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c 2018-05-06 08:49:50.650755149 +0200 -@@ -3164,6 +3164,9 @@ - if (status == BRCMF_E_STATUS_ABORT) - goto exit; - +diff --git a/drivers/net/wireless/bcm4336/wldev_common.c b/drivers/net/wireless/bcm4336/wldev_common.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wldev_common.c +@@ -0,0 +1,370 @@ ++/* ++ * Common function shared by Linux WEXT, cfg80211 and p2p drivers ++ * ++ * $Copyright Open Broadcom Corporation$ ++ * ++ * $Id: wldev_common.c 504503 2014-09-24 11:28:56Z $ ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define htod32(i) (i) ++#define htod16(i) (i) ++#define dtoh32(i) (i) ++#define dtoh16(i) (i) ++#define htodchanspec(i) (i) ++#define dtohchanspec(i) (i) ++ ++#define WLDEV_ERROR(args) \ ++ do { \ ++ printk(KERN_ERR "WLDEV-ERROR) %s : ", __func__); \ ++ printk args; \ ++ } while (0) ++ ++extern int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd); ++ ++s32 wldev_ioctl( ++ struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set) ++{ ++ s32 ret = 0; ++ struct wl_ioctl ioc; ++ ++ ++ memset(&ioc, 0, sizeof(ioc)); ++ ioc.cmd = cmd; ++ ioc.buf = arg; ++ ioc.len = len; ++ ioc.set = set; ++ ++ ret = dhd_ioctl_entry_local(dev, &ioc, cmd); ++ ++ return ret; ++} ++ ++/* Format a iovar buffer, not bsscfg indexed. The bsscfg index will be ++ * taken care of in dhd_ioctl_entry. Internal use only, not exposed to ++ * wl_iw, wl_cfg80211 and wl_cfgp2p ++ */ ++static s32 wldev_mkiovar( ++ s8 *iovar_name, s8 *param, s32 paramlen, ++ s8 *iovar_buf, u32 buflen) ++{ ++ s32 iolen = 0; ++ ++ iolen = bcm_mkiovar(iovar_name, param, paramlen, iovar_buf, buflen); ++ return iolen; ++} ++ ++s32 wldev_iovar_getbuf( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) ++{ ++ s32 ret = 0; ++ if (buf_sync) { ++ mutex_lock(buf_sync); ++ } ++ wldev_mkiovar(iovar_name, param, paramlen, buf, buflen); ++ ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE); ++ if (buf_sync) ++ mutex_unlock(buf_sync); ++ return ret; ++} ++ ++ ++s32 wldev_iovar_setbuf( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) ++{ ++ s32 ret = 0; ++ s32 iovar_len; ++ if (buf_sync) { ++ mutex_lock(buf_sync); ++ } ++ iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen); ++ if (iovar_len > 0) ++ ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE); ++ else ++ ret = BCME_BUFTOOSHORT; ++ ++ if (buf_sync) ++ mutex_unlock(buf_sync); ++ return ret; ++} ++ ++s32 wldev_iovar_setint( ++ struct net_device *dev, s8 *iovar, s32 val) ++{ ++ s8 iovar_buf[WLC_IOCTL_SMLEN]; ++ ++ val = htod32(val); ++ memset(iovar_buf, 0, sizeof(iovar_buf)); ++ return wldev_iovar_setbuf(dev, iovar, &val, sizeof(val), iovar_buf, ++ sizeof(iovar_buf), NULL); ++} ++ ++ ++s32 wldev_iovar_getint( ++ struct net_device *dev, s8 *iovar, s32 *pval) ++{ ++ s8 iovar_buf[WLC_IOCTL_SMLEN]; ++ s32 err; ++ ++ memset(iovar_buf, 0, sizeof(iovar_buf)); ++ err = wldev_iovar_getbuf(dev, iovar, pval, sizeof(*pval), iovar_buf, ++ sizeof(iovar_buf), NULL); ++ if (err == 0) ++ { ++ memcpy(pval, iovar_buf, sizeof(*pval)); ++ *pval = dtoh32(*pval); ++ } ++ return err; ++} ++ ++/** Format a bsscfg indexed iovar buffer. The bsscfg index will be ++ * taken care of in dhd_ioctl_entry. Internal use only, not exposed to ++ * wl_iw, wl_cfg80211 and wl_cfgp2p ++ */ ++s32 wldev_mkiovar_bsscfg( ++ const s8 *iovar_name, s8 *param, s32 paramlen, ++ s8 *iovar_buf, s32 buflen, s32 bssidx) ++{ ++ const s8 *prefix = "bsscfg:"; ++ s8 *p; ++ u32 prefixlen; ++ u32 namelen; ++ u32 iolen; ++ ++ if (bssidx == 0) { ++ return wldev_mkiovar((s8*)iovar_name, (s8 *)param, paramlen, ++ (s8 *) iovar_buf, buflen); ++ } ++ ++ prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */ ++ namelen = (u32) strlen(iovar_name) + 1; /* lengh of iovar name + null */ ++ iolen = prefixlen + namelen + sizeof(u32) + paramlen; ++ ++ if (buflen < 0 || iolen > (u32)buflen) ++ { ++ WLDEV_ERROR(("%s: buffer is too short\n", __FUNCTION__)); ++ return BCME_BUFTOOSHORT; ++ } ++ ++ p = (s8 *)iovar_buf; ++ ++ /* copy prefix, no null */ ++ memcpy(p, prefix, prefixlen); ++ p += prefixlen; ++ ++ /* copy iovar name including null */ ++ memcpy(p, iovar_name, namelen); ++ p += namelen; ++ ++ /* bss config index as first param */ ++ bssidx = htod32(bssidx); ++ memcpy(p, &bssidx, sizeof(u32)); ++ p += sizeof(u32); ++ ++ /* parameter buffer follows */ ++ if (paramlen) ++ memcpy(p, param, paramlen); ++ ++ return iolen; ++ ++} ++ ++s32 wldev_iovar_getbuf_bsscfg( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync) ++{ ++ s32 ret = 0; ++ if (buf_sync) { ++ mutex_lock(buf_sync); ++ } ++ ++ wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx); ++ ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE); ++ if (buf_sync) { ++ mutex_unlock(buf_sync); ++ } ++ return ret; ++ ++} ++ ++s32 wldev_iovar_setbuf_bsscfg( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync) ++{ ++ s32 ret = 0; ++ s32 iovar_len; ++ if (buf_sync) { ++ mutex_lock(buf_sync); ++ } ++ iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx); ++ if (iovar_len > 0) ++ ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE); ++ else { ++ ret = BCME_BUFTOOSHORT; ++ } ++ ++ if (buf_sync) { ++ mutex_unlock(buf_sync); ++ } ++ return ret; ++} ++ ++s32 wldev_iovar_setint_bsscfg( ++ struct net_device *dev, s8 *iovar, s32 val, s32 bssidx) ++{ ++ s8 iovar_buf[WLC_IOCTL_SMLEN]; ++ ++ val = htod32(val); ++ memset(iovar_buf, 0, sizeof(iovar_buf)); ++ return wldev_iovar_setbuf_bsscfg(dev, iovar, &val, sizeof(val), iovar_buf, ++ sizeof(iovar_buf), bssidx, NULL); ++} ++ ++ ++s32 wldev_iovar_getint_bsscfg( ++ struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx) ++{ ++ s8 iovar_buf[WLC_IOCTL_SMLEN]; ++ s32 err; ++ ++ memset(iovar_buf, 0, sizeof(iovar_buf)); ++ err = wldev_iovar_getbuf_bsscfg(dev, iovar, pval, sizeof(*pval), iovar_buf, ++ sizeof(iovar_buf), bssidx, NULL); ++ if (err == 0) ++ { ++ memcpy(pval, iovar_buf, sizeof(*pval)); ++ *pval = dtoh32(*pval); ++ } ++ return err; ++} ++ ++int wldev_get_link_speed( ++ struct net_device *dev, int *plink_speed) ++{ ++ int error; ++ ++ if (!plink_speed) ++ return -ENOMEM; ++ error = wldev_ioctl(dev, WLC_GET_RATE, plink_speed, sizeof(int), 0); ++ if (unlikely(error)) ++ return error; ++ ++ /* Convert internal 500Kbps to Kbps */ ++ *plink_speed *= 500; ++ return error; ++} ++ ++int wldev_get_rssi( ++ struct net_device *dev, int *prssi) ++{ ++ scb_val_t scb_val; ++ int error; ++ ++ if (!prssi) ++ return -ENOMEM; ++ bzero(&scb_val, sizeof(scb_val_t)); ++ ++ error = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t), 0); ++ if (unlikely(error)) ++ return error; ++ ++ *prssi = dtoh32(scb_val.val); ++ return error; ++} ++ ++int wldev_get_ssid( ++ struct net_device *dev, wlc_ssid_t *pssid) ++{ ++ int error; ++ ++ if (!pssid) ++ return -ENOMEM; ++ error = wldev_ioctl(dev, WLC_GET_SSID, pssid, sizeof(wlc_ssid_t), 0); ++ if (unlikely(error)) ++ return error; ++ pssid->SSID_len = dtoh32(pssid->SSID_len); ++ return error; ++} ++ ++int wldev_get_band( ++ struct net_device *dev, uint *pband) ++{ ++ int error; ++ ++ error = wldev_ioctl(dev, WLC_GET_BAND, pband, sizeof(uint), 0); ++ return error; ++} ++ ++int wldev_set_band( ++ struct net_device *dev, uint band) ++{ ++ int error = -1; ++ ++ if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) { ++ error = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true); ++ if (!error) ++ dhd_bus_band_set(dev, band); ++ } ++ return error; ++} ++ ++int wldev_set_country( ++ struct net_device *dev, char *country_code, bool notify, bool user_enforced) ++{ ++ int error = -1; ++ wl_country_t cspec = {{0}, 0, {0}}; ++ scb_val_t scbval; ++ char smbuf[WLC_IOCTL_SMLEN]; ++ ++ if (!country_code) ++ return error; ++ ++ bzero(&scbval, sizeof(scb_val_t)); ++ error = wldev_iovar_getbuf(dev, "country", NULL, 0, &cspec, sizeof(cspec), NULL); ++ if (error < 0) { ++ WLDEV_ERROR(("%s: get country failed = %d\n", __FUNCTION__, error)); ++ return error; ++ } ++ ++ if ((error < 0) || ++ (strncmp(country_code, cspec.country_abbrev, WLC_CNTRY_BUF_SZ) != 0)) { ++ ++ if (user_enforced) { ++ bzero(&scbval, sizeof(scb_val_t)); ++ error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); ++ if (error < 0) { ++ WLDEV_ERROR(("%s: set country failed due to Disassoc error %d\n", ++ __FUNCTION__, error)); ++ return error; ++ } ++ } ++ ++ cspec.rev = -1; ++ memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ); ++ memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ); ++ dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec); ++ error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec), ++ smbuf, sizeof(smbuf), NULL); ++ if (error < 0) { ++ WLDEV_ERROR(("%s: set country for %s as %s rev %d failed\n", ++ __FUNCTION__, country_code, cspec.ccode, cspec.rev)); ++ return error; ++ } ++ dhd_conf_fix_country(dhd_get_pub(dev)); ++ dhd_conf_get_country(dhd_get_pub(dev), &cspec); ++ dhd_bus_country_set(dev, &cspec, notify); ++ WLDEV_ERROR(("%s: set country for %s as %s rev %d\n", ++ __FUNCTION__, country_code, cspec.ccode, cspec.rev)); ++ } ++ return 0; ++} +diff --git a/drivers/net/wireless/bcm4336/wldev_common.h b/drivers/net/wireless/bcm4336/wldev_common.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/net/wireless/bcm4336/wldev_common.h +@@ -0,0 +1,106 @@ ++/* ++ * Common function shared by Linux WEXT, cfg80211 and p2p drivers ++ * ++ * $Copyright Open Broadcom Corporation$ ++ * ++ * $Id: wldev_common.h 504503 2014-09-24 11:28:56Z $ ++ */ ++#ifndef __WLDEV_COMMON_H__ ++#define __WLDEV_COMMON_H__ ++ ++#include ++ ++/* wl_dev_ioctl - get/set IOCTLs, will call net_device's do_ioctl (or ++ * netdev_ops->ndo_do_ioctl in new kernels) ++ * @dev: the net_device handle ++ */ ++s32 wldev_ioctl( ++ struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set); ++ ++/** Retrieve named IOVARs, this function calls wl_dev_ioctl with ++ * WLC_GET_VAR IOCTL code ++ */ ++s32 wldev_iovar_getbuf( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync); ++ ++/** Set named IOVARs, this function calls wl_dev_ioctl with ++ * WLC_SET_VAR IOCTL code ++ */ ++s32 wldev_iovar_setbuf( ++ struct net_device *dev, s8 *iovar_name, ++ void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync); ++ ++s32 wldev_iovar_setint( ++ struct net_device *dev, s8 *iovar, s32 val); ++ ++s32 wldev_iovar_getint( ++ struct net_device *dev, s8 *iovar, s32 *pval); ++ ++/** The following function can be implemented if there is a need for bsscfg ++ * indexed IOVARs ++ */ ++ ++s32 wldev_mkiovar_bsscfg( ++ const s8 *iovar_name, s8 *param, s32 paramlen, ++ s8 *iovar_buf, s32 buflen, s32 bssidx); ++ ++/** Retrieve named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with ++ * WLC_GET_VAR IOCTL code ++ */ ++s32 wldev_iovar_getbuf_bsscfg( ++ struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen, ++ void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync); ++ ++/** Set named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with ++ * WLC_SET_VAR IOCTL code ++ */ ++s32 wldev_iovar_setbuf_bsscfg( ++ struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen, ++ void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync); ++ ++s32 wldev_iovar_getint_bsscfg( ++ struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx); ++ ++s32 wldev_iovar_setint_bsscfg( ++ struct net_device *dev, s8 *iovar, s32 val, s32 bssidx); ++ ++extern int dhd_net_set_fw_path(struct net_device *dev, char *fw); ++extern int dhd_net_bus_suspend(struct net_device *dev); ++extern int dhd_net_bus_resume(struct net_device *dev, uint8 stage); ++extern int dhd_net_wifi_platform_set_power(struct net_device *dev, bool on, ++ unsigned long delay_msec); ++extern void dhd_get_customized_country_code(struct net_device *dev, char *country_iso_code, ++ wl_country_t *cspec); ++extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, bool notify); ++extern void dhd_bus_band_set(struct net_device *dev, uint band); ++extern int wldev_set_country(struct net_device *dev, char *country_code, bool notify, ++ bool user_enforced); ++extern int net_os_wake_lock(struct net_device *dev); ++extern int net_os_wake_unlock(struct net_device *dev); ++extern int net_os_wake_lock_timeout(struct net_device *dev); ++extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val); ++extern int net_os_set_dtim_skip(struct net_device *dev, int val); ++extern int net_os_set_suspend_disable(struct net_device *dev, int val); ++extern int net_os_set_suspend(struct net_device *dev, int val, int force); ++extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, ++ int max, int *bytes_left); ++ ++/* Get the link speed from dongle, speed is in kpbs */ ++int wldev_get_link_speed(struct net_device *dev, int *plink_speed); ++ ++int wldev_get_rssi(struct net_device *dev, int *prssi); ++ ++int wldev_get_ssid(struct net_device *dev, wlc_ssid_t *pssid); ++ ++int wldev_get_band(struct net_device *dev, uint *pband); ++ ++int wldev_set_band(struct net_device *dev, uint band); ++ ++#if defined(CUSTOM_PLATFORM_NV_TEGRA) ++int wldev_miracast_tuning(struct net_device *dev, char *command, int total_len); ++int wldev_get_assoc_resp_ie(struct net_device *dev, char *command, int total_len); ++int wldev_get_rx_rate_stats(struct net_device *dev, char *command, int total_len); ++#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */ ++ ++#endif /* __WLDEV_COMMON_H__ */ +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 111111111111..222222222222 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -3161,6 +3161,9 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, + + status = e->status; + + if (status == BRCMF_E_STATUS_ABORT) + goto exit; + - if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { - brcmf_err("scan not ready, bsscfgidx=%d\n", ifp->bsscfgidx); - return -EPERM; -@@ -5876,7 +5879,7 @@ + if (status == BRCMF_E_STATUS_ABORT) + goto exit; + +@@ -5882,7 +5885,7 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) s32 err = 0; - + cfg->scan_request = NULL; - cfg->pwr_save = true; + cfg->pwr_save = !cfg->pub->settings->powersave_default_off; cfg->active_scan = true; /* we do active scan per default */ cfg->dongle_up = false; /* dongle is not up yet */ err = brcmf_init_priv_mem(cfg); -@@ -6617,8 +6620,9 @@ +@@ -6624,8 +6627,9 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) BIT(NL80211_BSS_SELECT_ATTR_BAND_PREF) | BIT(NL80211_BSS_SELECT_ATTR_RSSI_ADJUST); - + + if( ! ifp->drvr->settings->powersave_default_off ) + wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; wiphy->flags |= WIPHY_FLAG_NETNS_OK | @@ -248682,13 +250213,14 @@ diff -ENwbur a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/dri WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS)) -diff -ENwbur a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c 2018-05-06 08:47:37.769361990 +0200 -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c 2018-05-06 08:49:50.650755149 +0200 -@@ -1217,6 +1217,14 @@ +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +index 111111111111..222222222222 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +@@ -1217,6 +1217,14 @@ static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip) core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3); brcmf_chip_resetcore(core, 0, 0, 0); - + + if( chip->pub.chip == BRCM_CC_43430_CHIP_ID && chip->pub.chiprev == 0 ) { + /* ap6212: fix occasional I/O timeout occuring after this reset. + * Usually appropriate delay (~50ms) provides sdio_enable_func() @@ -248699,22 +250231,23 @@ diff -ENwbur a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers + } return true; } - -diff -ENwbur a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c 2018-05-06 08:47:37.769361990 +0200 -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c 2018-05-06 08:49:50.650755149 +0200 -@@ -80,6 +80,10 @@ + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +index 111111111111..222222222222 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -80,6 +80,10 @@ module_param_named(ignore_probe_fail, brcmf_ignore_probe_fail, int, 0); MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging"); #endif - + +static int brcmf_powersave_default = -1; +module_param_named(powersave_default, brcmf_powersave_default, int, 0); +MODULE_PARM_DESC(powersave_default, "Set powersave default on/off on wiphy"); + static struct brcmfmac_platform_data *brcmfmac_pdata; struct brcmf_mp_global_t brcmf_mp_global; - -@@ -319,6 +323,8 @@ + +@@ -319,6 +323,8 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, /* No platform data for this device, try OF (Open Firwmare) */ brcmf_of_probe(dev, bus_type, settings); } @@ -248722,11 +250255,12 @@ diff -ENwbur a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drive + settings->powersave_default_off = !brcmf_powersave_default; return settings; } - -diff -ENwbur a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h 2018-05-06 08:47:37.769361990 +0200 -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h 2018-05-06 08:49:50.650755149 +0200 -@@ -59,6 +59,7 @@ + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +index 111111111111..222222222222 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +@@ -59,6 +59,7 @@ struct brcmf_mp_device { int fcmode; bool roamoff; bool ignore_probe_fail; @@ -248734,45 +250268,25 @@ diff -ENwbur a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drive struct brcmfmac_pd_cc *country_codes; union { struct brcmfmac_sdio_pd sdio; -diff -ENwbur a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c 2018-05-06 08:47:37.773362153 +0200 -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c 2018-05-06 08:49:50.654755310 +0200 -@@ -39,6 +39,9 @@ +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +index 111111111111..222222222222 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +@@ -39,6 +39,9 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0) sdio->drive_strength = val; - + + settings->powersave_default_off = of_property_read_bool(np, + "brcm,powersave-default-off"); + /* make sure there are interrupts defined in the node */ if (!of_find_property(np, "interrupts", NULL)) return; -diff -ENwbur a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig ---- a/drivers/net/wireless/Kconfig 2018-05-06 08:47:37.717359879 +0200 -+++ b/drivers/net/wireless/Kconfig 2018-05-06 08:49:50.574752064 +0200 -@@ -33,6 +33,7 @@ - source "drivers/net/wireless/admtek/Kconfig" - source "drivers/net/wireless/ath/Kconfig" - source "drivers/net/wireless/atmel/Kconfig" -+source "drivers/net/wireless/bcm4336/Kconfig" - source "drivers/net/wireless/broadcom/Kconfig" - source "drivers/net/wireless/cisco/Kconfig" - source "drivers/net/wireless/intel/Kconfig" -diff -ENwbur a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile ---- a/drivers/net/wireless/Makefile 2018-05-06 08:47:37.717359879 +0200 -+++ b/drivers/net/wireless/Makefile 2018-05-06 08:49:50.574752064 +0200 -@@ -6,6 +6,7 @@ - obj-$(CONFIG_WLAN_VENDOR_ADMTEK) += admtek/ - obj-$(CONFIG_WLAN_VENDOR_ATH) += ath/ - obj-$(CONFIG_WLAN_VENDOR_ATMEL) += atmel/ -+obj-$(CONFIG_BCMDHD) += bcm4336/ - obj-$(CONFIG_WLAN_VENDOR_BROADCOM) += broadcom/ - obj-$(CONFIG_WLAN_VENDOR_CISCO) += cisco/ - obj-$(CONFIG_WLAN_VENDOR_INTEL) += intel/ -diff -ENwbur a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig ---- a/drivers/phy/samsung/Kconfig 2018-05-06 08:47:37.941368973 +0200 -+++ b/drivers/phy/samsung/Kconfig 2018-05-06 08:49:50.826762291 +0200 -@@ -93,3 +93,9 @@ +diff --git a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/phy/samsung/Kconfig ++++ b/drivers/phy/samsung/Kconfig +@@ -93,3 +93,9 @@ config PHY_EXYNOS5250_SATA Exynos5250 based SoCs.This SerDes/Phy supports SATA 1.5 Gb/s, SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host port to accept one SATA device. @@ -248782,19 +250296,22 @@ diff -ENwbur a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig + depends on PHY_SAMSUNG_USB2 + default ARCH_S5P4418 || ARCH_S5P6818 + -diff -ENwbur a/drivers/phy/samsung/Makefile b/drivers/phy/samsung/Makefile ---- a/drivers/phy/samsung/Makefile 2018-05-06 08:47:37.941368973 +0200 -+++ b/drivers/phy/samsung/Makefile 2018-05-06 08:49:50.826762291 +0200 -@@ -8,5 +8,6 @@ +diff --git a/drivers/phy/samsung/Makefile b/drivers/phy/samsung/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/phy/samsung/Makefile ++++ b/drivers/phy/samsung/Makefile +@@ -8,5 +8,6 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o +phy-exynos-usb2-$(CONFIG_PHY_NX_USB2) += phy-nexell-usb2.o obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o -diff -ENwbur a/drivers/phy/samsung/phy-nexell-usb2.c b/drivers/phy/samsung/phy-nexell-usb2.c ---- a/drivers/phy/samsung/phy-nexell-usb2.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/phy/samsung/phy-nexell-usb2.c 2018-05-06 08:49:50.826762291 +0200 +diff --git a/drivers/phy/samsung/phy-nexell-usb2.c b/drivers/phy/samsung/phy-nexell-usb2.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/phy/samsung/phy-nexell-usb2.c @@ -0,0 +1,398 @@ +/* + * Nexell SoC USB 1.1/2.0 PHY driver @@ -249194,10 +250711,11 @@ diff -ENwbur a/drivers/phy/samsung/phy-nexell-usb2.c b/drivers/phy/samsung/phy-n + .num_phys = NX_NUM_PHYS, + .phys = nx_phys, +}; -diff -ENwbur a/drivers/phy/samsung/phy-samsung-usb2.c b/drivers/phy/samsung/phy-samsung-usb2.c ---- a/drivers/phy/samsung/phy-samsung-usb2.c 2018-05-06 08:47:37.945369136 +0200 -+++ b/drivers/phy/samsung/phy-samsung-usb2.c 2018-05-06 08:49:50.826762291 +0200 -@@ -38,21 +38,34 @@ +diff --git a/drivers/phy/samsung/phy-samsung-usb2.c b/drivers/phy/samsung/phy-samsung-usb2.c +index 111111111111..222222222222 100644 +--- a/drivers/phy/samsung/phy-samsung-usb2.c ++++ b/drivers/phy/samsung/phy-samsung-usb2.c +@@ -38,21 +38,34 @@ static int samsung_usb2_phy_power_on(struct phy *phy) ret = clk_prepare_enable(drv->clk); if (ret) goto err_main_clk; @@ -249224,16 +250742,16 @@ diff -ENwbur a/drivers/phy/samsung/phy-samsung-usb2.c b/drivers/phy/samsung/phy- goto err_power_on; } + } - + return 0; - + err_power_on: clk_disable_unprepare(drv->ref_clk); +skip_err_power_on: err_instance_clk: clk_disable_unprepare(drv->clk); err_main_clk: -@@ -77,7 +90,12 @@ +@@ -77,7 +90,12 @@ static int samsung_usb2_phy_power_off(struct phy *phy) if (ret) return ret; } @@ -249246,23 +250764,23 @@ diff -ENwbur a/drivers/phy/samsung/phy-samsung-usb2.c b/drivers/phy/samsung/phy- clk_disable_unprepare(drv->clk); if (drv->vbus) ret = regulator_disable(drv->vbus); -@@ -137,6 +155,12 @@ +@@ -136,6 +154,12 @@ static const struct of_device_id samsung_usb2_phy_of_match[] = { + .compatible = "samsung,s5pv210-usb2-phy", .data = &s5pv210_usb2_phy_config, }, - #endif ++#endif +#ifdef CONFIG_PHY_NX_USB2 + { + .compatible = "nexell,nexell-usb2-phy", + .data = &nexell_usb2_phy_config, + }, -+#endif + #endif { }, }; - MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match); -@@ -178,6 +202,16 @@ +@@ -178,6 +202,16 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev) return PTR_ERR(drv->reg_phy); } - + + if (of_device_is_compatible(pdev->dev.of_node, + "nexell,nexell-usb2-phy")) { + drv->clk = devm_clk_get(dev, "phy"); @@ -249276,17 +250794,17 @@ diff -ENwbur a/drivers/phy/samsung/phy-samsung-usb2.c b/drivers/phy/samsung/phy- drv->reg_pmu = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "samsung,pmureg-phandle"); if (IS_ERR(drv->reg_pmu)) { -@@ -221,6 +255,8 @@ +@@ -221,6 +255,8 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev) drv->vbus = NULL; } - + +skip_syscon_refclk: + for (i = 0; i < drv->cfg->num_phys; i++) { char *label = drv->cfg->phys[i].label; struct samsung_usb2_phy_instance *p = &drv->instances[i]; -@@ -235,6 +271,10 @@ - +@@ -235,6 +271,10 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev) + p->cfg = &drv->cfg->phys[i]; p->drv = drv; + if (of_device_is_compatible(pdev->dev.of_node, @@ -249296,37 +250814,42 @@ diff -ENwbur a/drivers/phy/samsung/phy-samsung-usb2.c b/drivers/phy/samsung/phy- phy_set_bus_width(p->phy, 8); phy_set_drvdata(p->phy, p); } -diff -ENwbur a/drivers/phy/samsung/phy-samsung-usb2.h b/drivers/phy/samsung/phy-samsung-usb2.h ---- a/drivers/phy/samsung/phy-samsung-usb2.h 2018-05-06 08:47:37.945369136 +0200 -+++ b/drivers/phy/samsung/phy-samsung-usb2.h 2018-05-06 08:49:50.826762291 +0200 -@@ -70,4 +70,5 @@ +diff --git a/drivers/phy/samsung/phy-samsung-usb2.h b/drivers/phy/samsung/phy-samsung-usb2.h +index 111111111111..222222222222 100644 +--- a/drivers/phy/samsung/phy-samsung-usb2.h ++++ b/drivers/phy/samsung/phy-samsung-usb2.h +@@ -70,4 +70,5 @@ extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config; extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config; extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config; extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config; +extern const struct samsung_usb2_phy_config nexell_usb2_phy_config; #endif -diff -ENwbur a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig ---- a/drivers/pinctrl/Kconfig 2018-05-06 08:47:37.945369136 +0200 -+++ b/drivers/pinctrl/Kconfig 2018-05-06 08:49:50.826762291 +0200 -@@ -370,6 +370,7 @@ +diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/pinctrl/Kconfig ++++ b/drivers/pinctrl/Kconfig +@@ -370,6 +370,7 @@ source "drivers/pinctrl/uniphier/Kconfig" source "drivers/pinctrl/vt8500/Kconfig" source "drivers/pinctrl/mediatek/Kconfig" source "drivers/pinctrl/zte/Kconfig" +source "drivers/pinctrl/nexell/Kconfig" - + config PINCTRL_XWAY bool -diff -ENwbur a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile ---- a/drivers/pinctrl/Makefile 2018-05-06 08:47:37.945369136 +0200 -+++ b/drivers/pinctrl/Makefile 2018-05-06 08:49:50.826762291 +0200 -@@ -66,3 +66,4 @@ +diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -66,3 +66,4 @@ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_ARCH_VT8500) += vt8500/ obj-$(CONFIG_PINCTRL_MTK) += mediatek/ obj-$(CONFIG_PINCTRL_ZX) += zte/ +obj-$(CONFIG_PINCTRL_NEXELL) += nexell/ -diff -ENwbur a/drivers/pinctrl/nexell/Kconfig b/drivers/pinctrl/nexell/Kconfig ---- a/drivers/pinctrl/nexell/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/pinctrl/nexell/Kconfig 2018-05-06 08:49:50.838762778 +0200 +diff --git a/drivers/pinctrl/nexell/Kconfig b/drivers/pinctrl/nexell/Kconfig +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/pinctrl/nexell/Kconfig @@ -0,0 +1,7 @@ +# +# NEXELL Pin control drivers @@ -249335,18 +250858,22 @@ diff -ENwbur a/drivers/pinctrl/nexell/Kconfig b/drivers/pinctrl/nexell/Kconfig + bool "Nexell SoC pinctrl driver" + select PINMUX + select PINCONF -diff -ENwbur a/drivers/pinctrl/nexell/Makefile b/drivers/pinctrl/nexell/Makefile ---- a/drivers/pinctrl/nexell/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/pinctrl/nexell/Makefile 2018-05-06 08:49:50.838762778 +0200 +diff --git a/drivers/pinctrl/nexell/Makefile b/drivers/pinctrl/nexell/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/pinctrl/nexell/Makefile @@ -0,0 +1,5 @@ +# +# NEXELL Pin control drivers +# + +obj-$(CONFIG_PINCTRL_NEXELL) += pinctrl-s5pxx18.o pinctrl-nexell.o -diff -ENwbur a/drivers/pinctrl/nexell/pinctrl-nexell.c b/drivers/pinctrl/nexell/pinctrl-nexell.c ---- a/drivers/pinctrl/nexell/pinctrl-nexell.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/pinctrl/nexell/pinctrl-nexell.c 2018-05-06 08:49:50.838762778 +0200 +diff --git a/drivers/pinctrl/nexell/pinctrl-nexell.c b/drivers/pinctrl/nexell/pinctrl-nexell.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/pinctrl/nexell/pinctrl-nexell.c @@ -0,0 +1,1196 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -250544,9 +252071,11 @@ diff -ENwbur a/drivers/pinctrl/nexell/pinctrl-nexell.c b/drivers/pinctrl/nexell/ +MODULE_AUTHOR("Bon-gyu, KOO "); +MODULE_DESCRIPTION("Nexell pinctrl driver"); +MODULE_LICENSE("GPL v2"); -diff -ENwbur a/drivers/pinctrl/nexell/pinctrl-nexell.h b/drivers/pinctrl/nexell/pinctrl-nexell.h ---- a/drivers/pinctrl/nexell/pinctrl-nexell.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/pinctrl/nexell/pinctrl-nexell.h 2018-05-06 08:49:50.838762778 +0200 +diff --git a/drivers/pinctrl/nexell/pinctrl-nexell.h b/drivers/pinctrl/nexell/pinctrl-nexell.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/pinctrl/nexell/pinctrl-nexell.h @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -250769,9 +252298,11 @@ diff -ENwbur a/drivers/pinctrl/nexell/pinctrl-nexell.h b/drivers/pinctrl/nexell/ +extern const struct nexell_pin_ctrl s5pxx18_pin_ctrl[]; + +#endif /* __PINCTRL_NEXELL_H */ -diff -ENwbur a/drivers/pinctrl/nexell/pinctrl-s5pxx18.c b/drivers/pinctrl/nexell/pinctrl-s5pxx18.c ---- a/drivers/pinctrl/nexell/pinctrl-s5pxx18.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/pinctrl/nexell/pinctrl-s5pxx18.c 2018-05-06 08:49:50.838762778 +0200 +diff --git a/drivers/pinctrl/nexell/pinctrl-s5pxx18.c b/drivers/pinctrl/nexell/pinctrl-s5pxx18.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/pinctrl/nexell/pinctrl-s5pxx18.c @@ -0,0 +1,2143 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -252916,9 +254447,11 @@ diff -ENwbur a/drivers/pinctrl/nexell/pinctrl-s5pxx18.c b/drivers/pinctrl/nexell + .resume = s5pxx18_resume, + } +}; -diff -ENwbur a/drivers/pinctrl/nexell/pinctrl-s5pxx18.h b/drivers/pinctrl/nexell/pinctrl-s5pxx18.h ---- a/drivers/pinctrl/nexell/pinctrl-s5pxx18.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/pinctrl/nexell/pinctrl-s5pxx18.h 2018-05-06 08:49:50.838762778 +0200 +diff --git a/drivers/pinctrl/nexell/pinctrl-s5pxx18.h b/drivers/pinctrl/nexell/pinctrl-s5pxx18.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/pinctrl/nexell/pinctrl-s5pxx18.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -253021,9 +254554,11 @@ diff -ENwbur a/drivers/pinctrl/nexell/pinctrl-s5pxx18.h b/drivers/pinctrl/nexell +#endif + + -diff -ENwbur a/drivers/pinctrl/nexell/s5pxx18-gpio.h b/drivers/pinctrl/nexell/s5pxx18-gpio.h ---- a/drivers/pinctrl/nexell/s5pxx18-gpio.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/pinctrl/nexell/s5pxx18-gpio.h 2018-05-06 08:49:50.838762778 +0200 +diff --git a/drivers/pinctrl/nexell/s5pxx18-gpio.h b/drivers/pinctrl/nexell/s5pxx18-gpio.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/pinctrl/nexell/s5pxx18-gpio.h @@ -0,0 +1,520 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -253545,30 +255080,32 @@ diff -ENwbur a/drivers/pinctrl/nexell/s5pxx18-gpio.h b/drivers/pinctrl/nexell/s5 +extern void nx_alive_clear_wakeup_status(void); + +#endif /* __S5Pxx18_GPIO_H */ -diff -ENwbur a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig ---- a/drivers/pwm/Kconfig 2018-05-06 08:47:38.013371896 +0200 -+++ b/drivers/pwm/Kconfig 2018-05-06 08:49:50.894765050 +0200 -@@ -380,7 +380,7 @@ - +diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/pwm/Kconfig ++++ b/drivers/pwm/Kconfig +@@ -380,7 +380,7 @@ config PWM_ROCKCHIP + config PWM_SAMSUNG tristate "Samsung PWM support" - depends on PLAT_SAMSUNG || ARCH_EXYNOS + depends on PLAT_SAMSUNG || ARCH_EXYNOS || ARCH_S5P4418 || ARCH_S5P6818 help Generic PWM framework driver for Samsung. - -diff -ENwbur a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c ---- a/drivers/pwm/pwm-samsung.c 2018-05-06 08:47:38.017372059 +0200 -+++ b/drivers/pwm/pwm-samsung.c 2018-05-06 08:49:50.898765212 +0200 + +diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c +index 111111111111..222222222222 100644 +--- a/drivers/pwm/pwm-samsung.c ++++ b/drivers/pwm/pwm-samsung.c @@ -25,6 +25,7 @@ #include #include #include +#include - + /* For struct samsung_timer_variant and samsung_pwm_lock. */ #include -@@ -80,6 +81,10 @@ +@@ -80,6 +81,10 @@ struct samsung_pwm_channel { * @base_clk: base clock used to drive the timers * @tclk0: external clock 0 (can be ERR_PTR if not present) * @tclk1: external clock 1 (can be ERR_PTR if not present) @@ -253579,7 +255116,7 @@ diff -ENwbur a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c */ struct samsung_pwm_chip { struct pwm_chip chip; -@@ -91,6 +96,17 @@ +@@ -91,6 +96,17 @@ struct samsung_pwm_chip { struct clk *base_clk; struct clk *tclk0; struct clk *tclk1; @@ -253595,12 +255132,12 @@ diff -ENwbur a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c + u32 tcmpb[SAMSUNG_PWM_NUM]; + u32 is_enabled; }; - + #ifndef CONFIG_CLKSRC_SAMSUNG_PWM -@@ -140,6 +156,22 @@ +@@ -140,6 +156,22 @@ static void pwm_samsung_set_divisor(struct samsung_pwm_chip *pwm, spin_unlock_irqrestore(&samsung_pwm_lock, flags); } - + +static void pwm_samsung_set_tclk(struct samsung_pwm_chip *pwm, + unsigned int chan) +{ @@ -253620,10 +255157,10 @@ diff -ENwbur a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c static int pwm_samsung_is_tdiv(struct samsung_pwm_chip *chip, unsigned int chan) { struct samsung_pwm_variant *variant = &chip->variant; -@@ -168,6 +200,117 @@ +@@ -168,6 +200,117 @@ static unsigned long pwm_samsung_get_tin_rate(struct samsung_pwm_chip *chip, return rate / (reg + 1); } - + +static unsigned long calc_base_freq(unsigned long clk_freq, + unsigned long req_freq) +{ @@ -253738,10 +255275,10 @@ diff -ENwbur a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c static unsigned long pwm_samsung_calc_tin(struct samsung_pwm_chip *chip, unsigned int chan, unsigned long freq) { -@@ -176,6 +319,17 @@ +@@ -176,6 +319,17 @@ static unsigned long pwm_samsung_calc_tin(struct samsung_pwm_chip *chip, struct clk *clk; u8 div; - + + /* + * patch for s5p6818 + * according to the pwm clock request, determine use tclk. @@ -253756,7 +255293,7 @@ diff -ENwbur a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c if (!pwm_samsung_is_tdiv(chip, chan)) { clk = (chan < 2) ? chip->tclk0 : chip->tclk1; if (!IS_ERR(clk)) { -@@ -473,6 +627,8 @@ +@@ -472,6 +626,8 @@ static const struct of_device_id samsung_pwm_matches[] = { { .compatible = "samsung,s5p6440-pwm", .data = &s5p64x0_variant }, { .compatible = "samsung,s5pc100-pwm", .data = &s5pc100_variant }, { .compatible = "samsung,exynos4210-pwm", .data = &s5p64x0_variant }, @@ -253765,10 +255302,10 @@ diff -ENwbur a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c {}, }; MODULE_DEVICE_TABLE(of, samsung_pwm_matches); -@@ -562,14 +718,76 @@ +@@ -561,14 +717,76 @@ static int pwm_samsung_probe(struct platform_device *pdev) return ret; } - + - for (chan = 0; chan < SAMSUNG_PWM_NUM; ++chan) - if (chip->variant.output_mask & BIT(chan)) - pwm_samsung_set_invert(chip, chan, true); @@ -253776,7 +255313,7 @@ diff -ENwbur a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c /* Following clocks are optional. */ chip->tclk0 = devm_clk_get(&pdev->dev, "pwm-tclk0"); chip->tclk1 = devm_clk_get(&pdev->dev, "pwm-tclk1"); - + + if (of_device_is_compatible(pdev->dev.of_node, "nexell,s5p4418-pwm")) { + /* Following clocks are optional. */ + chip->tclk2 = devm_clk_get(&pdev->dev, "pwm-tclk2"); @@ -253844,11 +255381,11 @@ diff -ENwbur a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c + pwm_samsung_set_invert(chip, chan, true); + platform_set_drvdata(pdev, chip); - + ret = pwmchip_add(&chip->chip); -@@ -602,12 +820,109 @@ +@@ -601,12 +819,109 @@ static int pwm_samsung_remove(struct platform_device *pdev) } - + #ifdef CONFIG_PM_SLEEP +static int pwm_samsung_suspend(struct device *dev) +{ @@ -253902,7 +255439,7 @@ diff -ENwbur a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c struct samsung_pwm_chip *our_chip = dev_get_drvdata(dev); struct pwm_chip *chip = &our_chip->chip; unsigned int i; - + + /* + * patch for s5p4418/s5p6818 + * s5p4418/s5p6818 pwm must be reset before enabled @@ -253956,18 +255493,52 @@ diff -ENwbur a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c for (i = 0; i < SAMSUNG_PWM_NUM; i++) { struct pwm_device *pwm = &chip->pwms[i]; struct samsung_pwm_channel *chan = pwm_get_chip_data(pwm); -@@ -636,7 +951,7 @@ +@@ -635,7 +950,7 @@ static int pwm_samsung_resume(struct device *dev) } #endif - + -static SIMPLE_DEV_PM_OPS(pwm_samsung_pm_ops, NULL, pwm_samsung_resume); +static SIMPLE_DEV_PM_OPS(pwm_samsung_pm_ops, pwm_samsung_suspend, pwm_samsung_resume); - + static struct platform_driver pwm_samsung_driver = { .driver = { -diff -ENwbur a/drivers/regulator/axp228-regu.c b/drivers/regulator/axp228-regu.c ---- a/drivers/regulator/axp228-regu.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/regulator/axp228-regu.c 2018-05-06 08:49:50.902765374 +0200 +diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/regulator/Kconfig ++++ b/drivers/regulator/Kconfig +@@ -163,6 +163,15 @@ config REGULATOR_AXP20X + This driver provides support for the voltage regulators on the + AXP20X PMIC. + ++config REGULATOR_AXP228 ++ tristate "X-Powers AXP228 Power regulator" ++ select MFD_AXP228 ++ help ++ This driver supports regulator driver for the X-Powers AXP228 ++ Power Management device. ++ It delivers digitally programmable output, ++ the voltage is programmed via I2C interface. ++ + config REGULATOR_BCM590XX + tristate "Broadcom BCM590xx PMU Regulators" + depends on MFD_BCM590XX +diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/regulator/Makefile ++++ b/drivers/regulator/Makefile +@@ -122,6 +122,7 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o + obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o + obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o + obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o ++obj-$(CONFIG_REGULATOR_AXP228) += axp228-regu.o + + + ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG +diff --git a/drivers/regulator/axp228-regu.c b/drivers/regulator/axp228-regu.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/regulator/axp228-regu.c @@ -0,0 +1,814 @@ +/* + * axp228-regu.c -- PMIC driver for the X-Powers AXP228 @@ -254783,48 +256354,21 @@ diff -ENwbur a/drivers/regulator/axp228-regu.c b/drivers/regulator/axp228-regu.c +MODULE_AUTHOR("King Zhong"); +MODULE_DESCRIPTION("Regulator Driver for X-powers AXP22 PMIC"); +MODULE_ALIAS("platform:axp-regulator"); -diff -ENwbur a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig ---- a/drivers/regulator/Kconfig 2018-05-06 08:47:38.021372221 +0200 -+++ b/drivers/regulator/Kconfig 2018-05-06 08:49:50.902765374 +0200 -@@ -163,6 +163,15 @@ - This driver provides support for the voltage regulators on the - AXP20X PMIC. - -+config REGULATOR_AXP228 -+ tristate "X-Powers AXP228 Power regulator" -+ select MFD_AXP228 -+ help -+ This driver supports regulator driver for the X-Powers AXP228 -+ Power Management device. -+ It delivers digitally programmable output, -+ the voltage is programmed via I2C interface. -+ - config REGULATOR_BCM590XX - tristate "Broadcom BCM590xx PMU Regulators" - depends on MFD_BCM590XX -diff -ENwbur a/drivers/regulator/Makefile b/drivers/regulator/Makefile ---- a/drivers/regulator/Makefile 2018-05-06 08:47:38.021372221 +0200 -+++ b/drivers/regulator/Makefile 2018-05-06 08:49:50.902765374 +0200 -@@ -122,6 +122,7 @@ - obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o - obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o - obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o -+obj-$(CONFIG_REGULATOR_AXP228) += axp228-regu.o - - - ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG -diff -ENwbur a/drivers/reset/Makefile b/drivers/reset/Makefile ---- a/drivers/reset/Makefile 2018-05-06 08:47:38.033372709 +0200 -+++ b/drivers/reset/Makefile 2018-05-06 08:49:50.914765862 +0200 -@@ -21,4 +21,4 @@ +diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/reset/Makefile ++++ b/drivers/reset/Makefile +@@ -21,4 +21,4 @@ obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o - +obj-$(CONFIG_ARCH_S5P6818) += reset-nexell.o -diff -ENwbur a/drivers/reset/reset-nexell.c b/drivers/reset/reset-nexell.c ---- a/drivers/reset/reset-nexell.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/reset/reset-nexell.c 2018-05-06 08:49:50.914765862 +0200 +diff --git a/drivers/reset/reset-nexell.c b/drivers/reset/reset-nexell.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/reset/reset-nexell.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -255018,13 +256562,14 @@ diff -ENwbur a/drivers/reset/reset-nexell.c b/drivers/reset/reset-nexell.c +MODULE_AUTHOR("Bon-gyu, KOO "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rtc"); -diff -ENwbur a/drivers/soc/Kconfig b/drivers/soc/Kconfig ---- a/drivers/soc/Kconfig 2018-05-06 08:47:38.209379854 +0200 -+++ b/drivers/soc/Kconfig 2018-05-06 08:49:51.090773002 +0200 -@@ -17,5 +17,6 @@ +diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/soc/Kconfig ++++ b/drivers/soc/Kconfig +@@ -17,5 +17,6 @@ source "drivers/soc/ti/Kconfig" source "drivers/soc/ux500/Kconfig" source "drivers/soc/versatile/Kconfig" source "drivers/soc/zte/Kconfig" +source "drivers/soc/nexell/Kconfig" - + endmenu -diff -ENwbur a/drivers/soc/Makefile b/drivers/soc/Makefile ---- a/drivers/soc/Makefile 2018-05-06 08:47:38.209379854 +0200 -+++ b/drivers/soc/Makefile 2018-05-06 08:49:51.090773002 +0200 -@@ -23,3 +23,4 @@ +diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/soc/Makefile ++++ b/drivers/soc/Makefile +@@ -23,3 +23,4 @@ obj-$(CONFIG_SOC_TI) += ti/ obj-$(CONFIG_ARCH_U8500) += ux500/ obj-$(CONFIG_PLAT_VERSATILE) += versatile/ obj-$(CONFIG_ARCH_ZX) += zte/ +obj-$(CONFIG_ARCH_S5P6818) += nexell/ -diff -ENwbur a/drivers/soc/nexell/Kconfig b/drivers/soc/nexell/Kconfig ---- a/drivers/soc/nexell/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/soc/nexell/Kconfig 2018-05-06 08:49:51.094773166 +0200 +diff --git a/drivers/soc/nexell/Kconfig b/drivers/soc/nexell/Kconfig +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/soc/nexell/Kconfig @@ -0,0 +1,3 @@ +if ARCH_S5P6818 +source "drivers/soc/nexell/s5pxx18/Kconfig" +endif -diff -ENwbur a/drivers/soc/nexell/Makefile b/drivers/soc/nexell/Makefile ---- a/drivers/soc/nexell/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/soc/nexell/Makefile 2018-05-06 08:49:51.094773166 +0200 +diff --git a/drivers/soc/nexell/Makefile b/drivers/soc/nexell/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/soc/nexell/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_ARCH_S5P6818) += s5pxx18/ +obj-$(CONFIG_ARCH_S5P4418) += s5pxx18/ -diff -ENwbur a/drivers/soc/nexell/s5pxx18/cpu-sys.c b/drivers/soc/nexell/s5pxx18/cpu-sys.c ---- a/drivers/soc/nexell/s5pxx18/cpu-sys.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/soc/nexell/s5pxx18/cpu-sys.c 2018-05-06 08:49:51.094773166 +0200 +diff --git a/drivers/soc/nexell/s5pxx18/Kconfig b/drivers/soc/nexell/s5pxx18/Kconfig +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/soc/nexell/s5pxx18/Kconfig +@@ -0,0 +1,3 @@ ++menu "NEXELL s5pxx18" ++ ++endmenu +diff --git a/drivers/soc/nexell/s5pxx18/Makefile b/drivers/soc/nexell/s5pxx18/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/soc/nexell/s5pxx18/Makefile +@@ -0,0 +1,2 @@ ++obj-y += tieoff_init.o ++obj-y += cpu-sys.o +diff --git a/drivers/soc/nexell/s5pxx18/cpu-sys.c b/drivers/soc/nexell/s5pxx18/cpu-sys.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/soc/nexell/s5pxx18/cpu-sys.c @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -256069,22 +257642,11 @@ diff -ENwbur a/drivers/soc/nexell/s5pxx18/cpu-sys.c b/drivers/soc/nexell/s5pxx18 + return 0; +} +core_initcall(cpu_sys_init_setup); -diff -ENwbur a/drivers/soc/nexell/s5pxx18/Kconfig b/drivers/soc/nexell/s5pxx18/Kconfig ---- a/drivers/soc/nexell/s5pxx18/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/soc/nexell/s5pxx18/Kconfig 2018-05-06 08:49:51.094773166 +0200 -@@ -0,0 +1,3 @@ -+menu "NEXELL s5pxx18" -+ -+endmenu -diff -ENwbur a/drivers/soc/nexell/s5pxx18/Makefile b/drivers/soc/nexell/s5pxx18/Makefile ---- a/drivers/soc/nexell/s5pxx18/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/soc/nexell/s5pxx18/Makefile 2018-05-06 08:49:51.094773166 +0200 -@@ -0,0 +1,2 @@ -+obj-y += tieoff_init.o -+obj-y += cpu-sys.o -diff -ENwbur a/drivers/soc/nexell/s5pxx18/tieoff_init.c b/drivers/soc/nexell/s5pxx18/tieoff_init.c ---- a/drivers/soc/nexell/s5pxx18/tieoff_init.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/drivers/soc/nexell/s5pxx18/tieoff_init.c 2018-05-06 08:49:51.094773166 +0200 +diff --git a/drivers/soc/nexell/s5pxx18/tieoff_init.c b/drivers/soc/nexell/s5pxx18/tieoff_init.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/soc/nexell/s5pxx18/tieoff_init.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -256249,33 +257811,35 @@ diff -ENwbur a/drivers/soc/nexell/s5pxx18/tieoff_init.c b/drivers/soc/nexell/s5p + return 0; +} +early_initcall(cpu_early_initcall_setup); -diff -ENwbur a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig ---- a/drivers/thermal/Kconfig 2018-05-06 08:47:38.497391546 +0200 -+++ b/drivers/thermal/Kconfig 2018-05-06 08:49:51.374784527 +0200 -@@ -419,7 +419,7 @@ +diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/thermal/Kconfig ++++ b/drivers/thermal/Kconfig +@@ -419,7 +419,7 @@ source "drivers/thermal/ti-soc-thermal/Kconfig" endmenu - + menu "Samsung thermal drivers" -depends on ARCH_EXYNOS || COMPILE_TEST +depends on ARCH_EXYNOS || ARCH_S5P6818 || COMPILE_TEST source "drivers/thermal/samsung/Kconfig" endmenu - -diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c ---- a/drivers/thermal/samsung/exynos_tmu.c 2018-05-06 08:47:38.501391709 +0200 -+++ b/drivers/thermal/samsung/exynos_tmu.c 2018-05-06 08:49:51.378784688 +0200 + +diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c +index 111111111111..222222222222 100644 +--- a/drivers/thermal/samsung/exynos_tmu.c ++++ b/drivers/thermal/samsung/exynos_tmu.c @@ -37,6 +37,7 @@ - + #include "exynos_tmu.h" #include "../thermal_core.h" +#include "../thermal_hwmon.h" - + /* Exynos generic registers */ #define EXYNOS_TMU_REG_TRIMINFO 0x0 @@ -165,6 +166,12 @@ #define EXYNOS7_EMUL_DATA_SHIFT 7 #define EXYNOS7_EMUL_DATA_MASK 0x1ff - + +/* s5p6818 specific */ +#define S5P6818_TMU_REG_INTEN 0xB0 +#define S5P6818_TMU_REG_INTSTAT 0xB4 @@ -256285,7 +257849,7 @@ diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/ex #define MCELSIUS 1000 /** * struct exynos_tmu_data : A structure to hold the private data of the TMU -@@ -213,6 +213,8 @@ struct exynos_tmu_data { +@@ -206,6 +213,8 @@ struct exynos_tmu_data { struct regulator *regulator; struct thermal_zone_device *tzd; unsigned int ntrip; @@ -256294,7 +257858,7 @@ diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/ex bool enabled; int (*tmu_initialize)(struct platform_device *pdev); -@@ -770,6 +779,10 @@ +@@ -774,6 +783,10 @@ static void exynos4210_tmu_control(struct platform_device *pdev, bool on) con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT); interrupt_en = 0; /* Disable all interrupts */ } @@ -256305,10 +257869,10 @@ diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/ex writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN); writel(con, data->base + EXYNOS_TMU_REG_CONTROL); } -@@ -893,6 +906,14 @@ - if (!data || !data->tmu_read) +@@ -898,6 +911,14 @@ static int exynos_get_temp(void *p, int *temp) + if (!data || !data->tmu_read || !data->enabled) return -EINVAL; - + + if( ! data->isInitialized ) { + /* We are probably within thermal_zone_of_sensor_register call. + * Return fake temperature, low enough to not trigger shutdown sequence @@ -256319,8 +257883,8 @@ diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/ex + } mutex_lock(&data->lock); clk_enable(data->clk); - -@@ -947,6 +968,8 @@ + +@@ -956,6 +977,8 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data, emul_con = EXYNOS5433_TMU_EMUL_CON; else if (data->soc == SOC_ARCH_EXYNOS7) emul_con = EXYNOS7_TMU_REG_EMUL_CON; @@ -256328,8 +257892,8 @@ diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/ex + emul_con = S5P6818_TMU_REG_EMUL_CON; else emul_con = EXYNOS_EMUL_CON; - -@@ -1060,6 +1083,9 @@ + +@@ -1069,6 +1092,9 @@ static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data) } else if (data->soc == SOC_ARCH_EXYNOS5433) { tmu_intstat = EXYNOS5433_TMU_REG_INTPEND; tmu_intclear = EXYNOS5433_TMU_REG_INTPEND; @@ -256339,7 +257903,7 @@ diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/ex } else { tmu_intstat = EXYNOS_TMU_REG_INTSTAT; tmu_intclear = EXYNOS_TMU_REG_INTCLEAR; -@@ -1107,6 +1133,7 @@ +@@ -1116,6 +1142,7 @@ static const struct of_device_id exynos_tmu_match[] = { { .compatible = "samsung,exynos5433-tmu", }, { .compatible = "samsung,exynos5440-tmu", }, { .compatible = "samsung,exynos7-tmu", }, @@ -256347,7 +257911,7 @@ diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/ex { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, exynos_tmu_match); -@@ -1134,7 +1161,8 @@ +@@ -1143,7 +1170,8 @@ static int exynos_of_get_soc_type(struct device_node *np) return SOC_ARCH_EXYNOS5440; else if (of_device_is_compatible(np, "samsung,exynos7-tmu")) return SOC_ARCH_EXYNOS7; @@ -256356,8 +257920,8 @@ diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/ex + return SOC_ARCH_S5P6818; return -EINVAL; } - -@@ -1226,6 +1254,7 @@ + +@@ -1235,6 +1263,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) case SOC_ARCH_EXYNOS5250: case SOC_ARCH_EXYNOS5260: case SOC_ARCH_EXYNOS5420: @@ -256365,9 +257929,9 @@ diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/ex case SOC_ARCH_EXYNOS5420_TRIMINFO: data->tmu_initialize = exynos4412_tmu_initialize; data->tmu_control = exynos4210_tmu_control; -@@ -1401,6 +1430,13 @@ +@@ -1410,6 +1439,13 @@ static int exynos_tmu_probe(struct platform_device *pdev) } - + exynos_tmu_control(pdev, true); + data->isInitialized = true; + if( (ret = thermal_add_hwmon_sysfs(data->tzd)) == 0 ) { @@ -256377,33 +257941,35 @@ diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/ex + dev_err(&pdev->dev, "Failed to add in sysfs as hwmon: %d\n", ret); + } return 0; - + err_thermal: -@@ -1424,6 +1460,8 @@ +@@ -1433,6 +1469,8 @@ static int exynos_tmu_remove(struct platform_device *pdev) struct exynos_tmu_data *data = platform_get_drvdata(pdev); struct thermal_zone_device *tzd = data->tzd; - + + if( data->isAddedToSysfs ) + thermal_remove_hwmon_sysfs(tzd); thermal_zone_of_sensor_unregister(&pdev->dev, tzd); exynos_tmu_control(pdev, false); - -diff -ENwbur a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h ---- a/drivers/thermal/samsung/exynos_tmu.h 2018-05-06 08:47:38.501391709 +0200 -+++ b/drivers/thermal/samsung/exynos_tmu.h 2018-05-06 08:49:51.378784688 +0200 -@@ -36,6 +36,7 @@ + +diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h +index 111111111111..222222222222 100644 +--- a/drivers/thermal/samsung/exynos_tmu.h ++++ b/drivers/thermal/samsung/exynos_tmu.h +@@ -36,6 +36,7 @@ enum soc_type { SOC_ARCH_EXYNOS5433, SOC_ARCH_EXYNOS5440, SOC_ARCH_EXYNOS7, + SOC_ARCH_S5P6818, }; - + /** -diff -ENwbur a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig ---- a/drivers/tty/serial/Kconfig 2018-05-06 08:47:38.517392359 +0200 -+++ b/drivers/tty/serial/Kconfig 2018-05-06 08:49:51.394785339 +0200 -@@ -241,7 +241,7 @@ - +diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/tty/serial/Kconfig ++++ b/drivers/tty/serial/Kconfig +@@ -241,7 +241,7 @@ config SERIAL_CLPS711X_CONSOLE + config SERIAL_SAMSUNG tristate "Samsung SoC serial support" - depends on PLAT_SAMSUNG || ARCH_EXYNOS @@ -256411,7 +257977,7 @@ diff -ENwbur a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig select SERIAL_CORE help Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, -@@ -259,6 +259,7 @@ +@@ -259,6 +259,7 @@ config SERIAL_SAMSUNG_UARTS_4 config SERIAL_SAMSUNG_UARTS int depends on SERIAL_SAMSUNG @@ -256419,10 +257985,11 @@ diff -ENwbur a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416 default 3 help -diff -ENwbur a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c ---- a/drivers/tty/serial/samsung.c 2018-05-06 08:47:38.529392846 +0200 -+++ b/drivers/tty/serial/samsung.c 2018-05-06 08:49:51.406785825 +0200 -@@ -1553,6 +1553,32 @@ +diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c +index 111111111111..222222222222 100644 +--- a/drivers/tty/serial/samsung.c ++++ b/drivers/tty/serial/samsung.c +@@ -1553,6 +1553,32 @@ s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = { .flags = UPF_BOOT_AUTOCONF, .line = 3, } @@ -256455,10 +258022,11 @@ diff -ENwbur a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c } #endif }; -@@ -1845,6 +1871,24 @@ +@@ -1848,6 +1874,24 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) + else if (ourport->info->fifosize) ourport->port.fifosize = ourport->info->fifosize; - - /* + ++ /* + * patch for s5p6818 + * s5p6818 uart needs reset before enabled + */ @@ -256476,13 +258044,12 @@ diff -ENwbur a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c + reset_control_put(rst); + } +#endif -+ /* + /* * DMA transfers must be aligned at least to cache line size, * so find minimal transfer size suitable for DMA mode - */ -@@ -1933,6 +1977,23 @@ +@@ -1941,6 +1985,23 @@ static int s3c24xx_serial_resume_noirq(struct device *dev) struct s3c24xx_uart_port *ourport = to_ourport(port); - + if (port) { + /* + * patch for s5p6818 @@ -256504,10 +258071,10 @@ diff -ENwbur a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c /* restore IRQ mask */ if (s3c24xx_serial_has_interrupt_mask(port)) { unsigned int uintm = 0xf; -@@ -2353,6 +2414,36 @@ +@@ -2365,6 +2426,36 @@ static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = { #define EXYNOS5433_SERIAL_DRV_DATA (kernel_ulong_t)NULL #endif - + +#if defined(CONFIG_ARCH_S5P6818) +static struct s3c24xx_serial_drv_data nexell_serial_drv_data = { + .info = &(struct s3c24xx_uart_info) { @@ -256541,7 +258108,7 @@ diff -ENwbur a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c static const struct platform_device_id s3c24xx_serial_driver_ids[] = { { .name = "s3c2410-uart", -@@ -2375,6 +2466,9 @@ +@@ -2387,6 +2478,9 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = { }, { .name = "exynos5433-uart", .driver_data = EXYNOS5433_SERIAL_DRV_DATA, @@ -256551,7 +258118,7 @@ diff -ENwbur a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c }, { }, }; -@@ -2396,6 +2490,8 @@ +@@ -2408,6 +2502,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = { .data = (void *)EXYNOS4210_SERIAL_DRV_DATA }, { .compatible = "samsung,exynos5433-uart", .data = (void *)EXYNOS5433_SERIAL_DRV_DATA }, @@ -256560,52 +258127,55 @@ diff -ENwbur a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c {}, }; MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match); -@@ -2511,6 +2607,8 @@ +@@ -2523,6 +2619,8 @@ OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart", s5pv210_early_console_setup); OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart", s5pv210_early_console_setup); +OF_EARLYCON_DECLARE(s5p6818, "nexell,s5p6818-uart", + s5pv210_early_console_setup); #endif - + MODULE_ALIAS("platform:samsung-uart"); -diff -ENwbur a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h ---- a/drivers/tty/serial/samsung.h 2018-05-06 08:47:38.529392846 +0200 -+++ b/drivers/tty/serial/samsung.h 2018-05-06 08:49:51.406785825 +0200 +diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h +index 111111111111..222222222222 100644 +--- a/drivers/tty/serial/samsung.h ++++ b/drivers/tty/serial/samsung.h @@ -13,6 +13,7 @@ */ - + #include +#include - + struct s3c24xx_uart_info { char *name; -@@ -32,6 +33,7 @@ +@@ -32,6 +33,7 @@ struct s3c24xx_uart_info { /* uart port features */ - + unsigned int has_divslot:1; + unsigned int has_reset_control:1; - + /* uart controls */ int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *); -diff -ENwbur a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h ---- a/drivers/usb/dwc2/core.h 2018-05-06 08:47:38.549393658 +0200 -+++ b/drivers/usb/dwc2/core.h 2018-05-06 08:49:51.426786637 +0200 -@@ -1023,6 +1023,7 @@ +diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h +index 111111111111..222222222222 100644 +--- a/drivers/usb/dwc2/core.h ++++ b/drivers/usb/dwc2/core.h +@@ -1026,6 +1026,7 @@ struct dwc2_hsotg { u32 hfnum_other_samples_b; u64 hfnum_other_frrem_accum_b; #endif + u32 ext_vbus_io; #endif /* CONFIG_USB_DWC2_HOST || CONFIG_USB_DWC2_DUAL_ROLE */ - + #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ -diff -ENwbur a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c ---- a/drivers/usb/dwc2/gadget.c 2018-05-06 08:47:38.549393658 +0200 -+++ b/drivers/usb/dwc2/gadget.c 2018-05-06 08:49:51.426786637 +0200 -@@ -4742,6 +4742,16 @@ +diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c +index 111111111111..222222222222 100644 +--- a/drivers/usb/dwc2/gadget.c ++++ b/drivers/usb/dwc2/gadget.c +@@ -4753,6 +4753,16 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg) if (hsotg->lx_state != DWC2_L0) return 0; - + + if (of_device_is_compatible(hsotg->dev->of_node, + "nexell,nexell-dwc2otg")) { + u32 usb_status = readl(hsotg->regs + GOTGCTL); @@ -256618,8 +258188,8 @@ diff -ENwbur a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c + if (hsotg->driver) { int ep; - -@@ -4761,6 +4771,12 @@ + +@@ -4772,6 +4782,12 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg) if (hsotg->eps_out[ep]) dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); } @@ -256630,9 +258200,9 @@ diff -ENwbur a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c + phy_power_off(hsotg->phy); + } } - + return 0; -@@ -4782,6 +4798,12 @@ +@@ -4793,6 +4809,12 @@ int dwc2_hsotg_resume(struct dwc2_hsotg *hsotg) if (hsotg->enabled) dwc2_hsotg_core_connect(hsotg); spin_unlock_irqrestore(&hsotg->lock, flags); @@ -256643,23 +258213,24 @@ diff -ENwbur a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c + phy_init(hsotg->phy); + } } - + return 0; -diff -ENwbur a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c ---- a/drivers/usb/dwc2/hcd.c 2018-05-06 08:47:38.549393658 +0200 -+++ b/drivers/usb/dwc2/hcd.c 2018-05-06 08:49:51.426786637 +0200 +diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c +index 111111111111..222222222222 100644 +--- a/drivers/usb/dwc2/hcd.c ++++ b/drivers/usb/dwc2/hcd.c @@ -48,6 +48,7 @@ #include #include #include +#include - + #include #include -@@ -2418,6 +2419,11 @@ +@@ -2457,6 +2458,11 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg) if (hsotg->op_state == OTG_STATE_A_HOST) { u32 hprt0 = dwc2_read_hprt0(hsotg); - + + if (of_device_is_compatible(hsotg->dev->of_node, + "nexell,nexell-dwc2otg")) { + if (gpio_is_valid(hsotg->ext_vbus_io)) @@ -256668,7 +258239,7 @@ diff -ENwbur a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c dev_dbg(hsotg->dev, "Init: Power Port (%d)\n", !!(hprt0 & HPRT0_PWR)); if (!(hprt0 & HPRT0_PWR)) { -@@ -3274,6 +3280,11 @@ +@@ -3374,6 +3380,11 @@ static void dwc2_conn_id_status_change(struct work_struct *work) dev_err(hsotg->dev, "Connection id status change timed out\n"); hsotg->op_state = OTG_STATE_B_PERIPHERAL; @@ -256680,8 +258251,8 @@ diff -ENwbur a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c dwc2_core_init(hsotg, false); dwc2_enable_global_interrupts(hsotg); spin_lock_irqsave(&hsotg->lock, flags); -@@ -4381,10 +4392,168 @@ - +@@ -4484,7 +4495,165 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd) + usleep_range(1000, 3000); } +#if defined(CONFIG_PM) && (defined(CONFIG_ARCH_S5P4418) || \ @@ -256769,10 +258340,10 @@ diff -ENwbur a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c + DPTXFSIZN(idx)); + } +} - - static int _dwc2_hcd_suspend(struct usb_hcd *hcd) - { - struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + ++static int _dwc2_hcd_suspend(struct usb_hcd *hcd) ++{ ++ struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + + dev_dbg(hsotg->dev, "%s %d\n", __func__, __LINE__); + @@ -256843,27 +258414,25 @@ diff -ENwbur a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c + return 0; +} +#else -+static int _dwc2_hcd_suspend(struct usb_hcd *hcd) -+{ -+ struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); - unsigned long flags; - int ret = 0; - u32 hprt0; -@@ -4514,6 +4683,7 @@ - + static int _dwc2_hcd_suspend(struct usb_hcd *hcd) + { + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); +@@ -4617,6 +4786,7 @@ unlock: + return ret; } +#endif - + /* Returns the current frame number */ static int _dwc2_hcd_get_frame_number(struct usb_hcd *hcd) -diff -ENwbur a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c ---- a/drivers/usb/dwc2/params.c 2018-05-06 08:47:38.549393658 +0200 -+++ b/drivers/usb/dwc2/params.c 2018-05-06 08:49:51.430786798 +0200 -@@ -113,6 +113,20 @@ +diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c +index 111111111111..222222222222 100644 +--- a/drivers/usb/dwc2/params.c ++++ b/drivers/usb/dwc2/params.c +@@ -113,6 +113,20 @@ static void dwc2_set_amlogic_params(struct dwc2_hsotg *hsotg) p->uframe_sched = false; } - + +static void dwc2_set_nexell_params(struct dwc2_hsotg *hsotg) +{ + struct dwc2_core_params *p = &hsotg->params; @@ -256881,7 +258450,7 @@ diff -ENwbur a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c static void dwc2_set_amcc_params(struct dwc2_hsotg *hsotg) { struct dwc2_core_params *p = &hsotg->params; -@@ -144,6 +158,7 @@ +@@ -144,6 +158,7 @@ const struct of_device_id dwc2_of_match_table[] = { { .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params }, { .compatible = "snps,dwc2" }, { .compatible = "samsung,s3c6400-hsotg" }, @@ -256889,21 +258458,22 @@ diff -ENwbur a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c { .compatible = "amlogic,meson8-usb", .data = dwc2_set_amlogic_params }, { .compatible = "amlogic,meson8b-usb", -diff -ENwbur a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c ---- a/drivers/usb/dwc2/platform.c 2018-05-06 08:47:38.553393820 +0200 -+++ b/drivers/usb/dwc2/platform.c 2018-05-06 08:49:51.430786798 +0200 +diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c +index 111111111111..222222222222 100644 +--- a/drivers/usb/dwc2/platform.c ++++ b/drivers/usb/dwc2/platform.c @@ -46,6 +46,7 @@ #include #include #include +#include - + #include - -@@ -136,6 +137,21 @@ + +@@ -136,6 +137,21 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) return ret; } - + + if (of_device_is_compatible(hsotg->dev->of_node, + "nexell,nexell-dwc2otg")) { +#ifdef CONFIG_RESET_CONTROLLER @@ -256922,10 +258492,10 @@ diff -ENwbur a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c if (hsotg->uphy) { ret = usb_phy_init(hsotg->uphy); } else if (hsotg->plat && hsotg->plat->phy_init) { -@@ -402,6 +418,27 @@ +@@ -402,6 +418,27 @@ static int dwc2_driver_probe(struct platform_device *dev) if (retval) return retval; - + + if (of_device_is_compatible(hsotg->dev->of_node, + "nexell,nexell-dwc2otg")) { +#ifdef CONFIG_GPIOLIB @@ -256950,9 +258520,32 @@ diff -ENwbur a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c retval = dwc2_lowlevel_hw_enable(hsotg); if (retval) return retval; -diff -ENwbur a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c ---- a/drivers/usb/host/ehci-exynos.c 2018-05-06 08:47:38.573394633 +0200 -+++ b/drivers/usb/host/ehci-exynos.c 2018-05-06 08:49:51.450787610 +0200 +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -262,7 +262,7 @@ config USB_EHCI_SH + + config USB_EHCI_EXYNOS + tristate "EHCI support for Samsung S5P/EXYNOS SoC Series" +- depends on ARCH_S5PV210 || ARCH_EXYNOS ++ depends on ARCH_S5PV210 || ARCH_EXYNOS || ARCH_S5P4418 || ARCH_S5P6818 + help + Enable support for the Samsung Exynos SOC's on-chip EHCI controller. + +@@ -567,7 +567,7 @@ config USB_OHCI_SH + + config USB_OHCI_EXYNOS + tristate "OHCI support for Samsung S5P/EXYNOS SoC Series" +- depends on ARCH_S5PV210 || ARCH_EXYNOS ++ depends on ARCH_S5PV210 || ARCH_EXYNOS || ARCH_S5P4418 || ARCH_S5P6818 + help + Enable support for the Samsung Exynos SOC's on-chip OHCI controller. + +diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c +index 111111111111..222222222222 100644 +--- a/drivers/usb/host/ehci-exynos.c ++++ b/drivers/usb/host/ehci-exynos.c @@ -23,6 +23,9 @@ #include #include @@ -256960,9 +258553,9 @@ diff -ENwbur a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c +#ifdef CONFIG_RESET_CONTROLLER +#include +#endif - + #include "ehci.h" - + @@ -36,6 +39,9 @@ #define EHCI_INSNREG00_ENABLE_DMA_BURST \ (EHCI_INSNREG00_ENA_INCR16 | EHCI_INSNREG00_ENA_INCR8 | \ @@ -256970,13 +258563,13 @@ diff -ENwbur a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c +#if defined(CONFIG_ARCH_S5P4418) || defined(CONFIG_ARCH_S5P6818) +#define EHCI_INSNREG08(base) (base + 0xb0) +#endif - + static const char hcd_name[] = "ehci-exynos"; static struct hc_driver __read_mostly exynos_ehci_hc_driver; -@@ -98,6 +104,20 @@ +@@ -98,6 +104,20 @@ static int exynos_ehci_phy_enable(struct device *dev) int i; int ret = 0; - + + if (of_device_is_compatible(dev->of_node, + "nexell,nexell-ehci")) { +#ifdef CONFIG_RESET_CONTROLLER @@ -256994,10 +258587,10 @@ diff -ENwbur a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c for (i = 0; ret == 0 && i < PHY_NUMBER; i++) if (!IS_ERR(exynos_ehci->phy[i])) ret = phy_power_on(exynos_ehci->phy[i]); -@@ -306,10 +326,26 @@ +@@ -306,10 +326,26 @@ static const struct dev_pm_ops exynos_ehci_pm_ops = { .resume = exynos_ehci_resume, }; - + +#if defined(CONFIG_ARCH_S5P4418) || defined(CONFIG_ARCH_S5P6818) +int hsic_port_power(struct usb_hcd *hcd, int portnum, bool enable) +{ @@ -257021,7 +258614,7 @@ diff -ENwbur a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c {}, }; MODULE_DEVICE_TABLE(of, exynos_ehci_match); -@@ -327,6 +363,9 @@ +@@ -327,6 +363,9 @@ static struct platform_driver exynos_ehci_driver = { }; static const struct ehci_driver_overrides exynos_overrides __initconst = { .extra_priv_size = sizeof(struct exynos_ehci_hcd), @@ -257029,32 +258622,12 @@ diff -ENwbur a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c + .port_power = hsic_port_power, +#endif }; - + static int __init ehci_exynos_init(void) -diff -ENwbur a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig ---- a/drivers/usb/host/Kconfig 2018-05-06 08:47:38.573394633 +0200 -+++ b/drivers/usb/host/Kconfig 2018-05-06 08:49:51.450787610 +0200 -@@ -262,7 +262,7 @@ - - config USB_EHCI_EXYNOS - tristate "EHCI support for Samsung S5P/EXYNOS SoC Series" -- depends on ARCH_S5PV210 || ARCH_EXYNOS -+ depends on ARCH_S5PV210 || ARCH_EXYNOS || ARCH_S5P4418 || ARCH_S5P6818 - help - Enable support for the Samsung Exynos SOC's on-chip EHCI controller. - -@@ -567,7 +567,7 @@ - - config USB_OHCI_EXYNOS - tristate "OHCI support for Samsung S5P/EXYNOS SoC Series" -- depends on ARCH_S5PV210 || ARCH_EXYNOS -+ depends on ARCH_S5PV210 || ARCH_EXYNOS || ARCH_S5P4418 || ARCH_S5P6818 - help - Enable support for the Samsung Exynos SOC's on-chip OHCI controller. - -diff -ENwbur a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c ---- a/drivers/usb/host/ohci-exynos.c 2018-05-06 08:47:38.581394957 +0200 -+++ b/drivers/usb/host/ohci-exynos.c 2018-05-06 08:49:51.458787935 +0200 +diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c +index 111111111111..222222222222 100644 +--- a/drivers/usb/host/ohci-exynos.c ++++ b/drivers/usb/host/ohci-exynos.c @@ -21,6 +21,9 @@ #include #include @@ -257062,13 +258635,13 @@ diff -ENwbur a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c +#ifdef CONFIG_RESET_CONTROLLER +#include +#endif - + #include "ohci.h" - -@@ -87,6 +90,20 @@ + +@@ -87,6 +90,20 @@ static int exynos_ohci_phy_enable(struct device *dev) int i; int ret = 0; - + + if (of_device_is_compatible(dev->of_node, + "nexell,nexell-ohci")) { +#ifdef CONFIG_RESET_CONTROLLER @@ -257086,20 +258659,20 @@ diff -ENwbur a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c for (i = 0; ret == 0 && i < PHY_NUMBER; i++) if (!IS_ERR(exynos_ohci->phy[i])) ret = phy_power_on(exynos_ohci->phy[i]); -@@ -215,10 +232,12 @@ - +@@ -215,10 +232,12 @@ static int exynos_ohci_remove(struct platform_device *pdev) + static void exynos_ohci_shutdown(struct platform_device *pdev) { +#if !(defined(CONFIG_ARCH_S5P4418) || defined(CONFIG_ARCH_S5P6818)) struct usb_hcd *hcd = platform_get_drvdata(pdev); - + if (hcd->driver->shutdown) hcd->driver->shutdown(hcd); +#endif } - + #ifdef CONFIG_PM -@@ -276,6 +295,7 @@ +@@ -276,6 +295,7 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = { static const struct of_device_id exynos_ohci_match[] = { { .compatible = "samsung,exynos4210-ohci" }, { .compatible = "samsung,exynos5440-ohci" }, @@ -257107,21 +258680,24 @@ diff -ENwbur a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c {}, }; MODULE_DEVICE_TABLE(of, exynos_ohci_match); -diff -ENwbur a/drivers/video/Kconfig b/drivers/video/Kconfig ---- a/drivers/video/Kconfig 2018-05-06 08:47:38.629396905 +0200 -+++ b/drivers/video/Kconfig 2018-05-06 08:49:51.506789882 +0200 -@@ -20,6 +20,8 @@ - +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -20,6 +20,8 @@ source "drivers/gpu/ipu-v3/Kconfig" + source "drivers/gpu/drm/Kconfig" - + +source "drivers/gpu/arm/Kconfig" + menu "Frame buffer Devices" source "drivers/video/fbdev/Kconfig" endmenu -diff -ENwbur a/include/drm/nexell_drm.h b/include/drm/nexell_drm.h ---- a/include/drm/nexell_drm.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/drm/nexell_drm.h 2018-05-06 08:49:51.802801894 +0200 +diff --git a/include/drm/nexell_drm.h b/include/drm/nexell_drm.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/drm/nexell_drm.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -257146,9 +258722,11 @@ diff -ENwbur a/include/drm/nexell_drm.h b/include/drm/nexell_drm.h +#include + +#endif -diff -ENwbur a/include/dt-bindings/interrupt-controller/s5p6818-irq.h b/include/dt-bindings/interrupt-controller/s5p6818-irq.h ---- a/include/dt-bindings/interrupt-controller/s5p6818-irq.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/dt-bindings/interrupt-controller/s5p6818-irq.h 2018-05-06 08:49:51.810802219 +0200 +diff --git a/include/dt-bindings/interrupt-controller/s5p6818-irq.h b/include/dt-bindings/interrupt-controller/s5p6818-irq.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/dt-bindings/interrupt-controller/s5p6818-irq.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -257287,9 +258865,11 @@ diff -ENwbur a/include/dt-bindings/interrupt-controller/s5p6818-irq.h b/include/ +#define IRQ_TOTAL_NR (IRQ_RESERVED_START + IRQ_RESERVED_NR) + +#endif -diff -ENwbur a/include/dt-bindings/media/nexell-vip.h b/include/dt-bindings/media/nexell-vip.h ---- a/include/dt-bindings/media/nexell-vip.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/dt-bindings/media/nexell-vip.h 2018-05-06 08:49:51.810802219 +0200 +diff --git a/include/dt-bindings/media/nexell-vip.h b/include/dt-bindings/media/nexell-vip.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/dt-bindings/media/nexell-vip.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -257335,9 +258915,11 @@ diff -ENwbur a/include/dt-bindings/media/nexell-vip.h b/include/dt-bindings/medi +#define NX_ACTION_TYPE_CLOCK 0xffff0003 + +#endif /* __DT_BINDINGS_MEDIA_NEXELL_V4L2_H__ */ -diff -ENwbur a/include/dt-bindings/reset/nexell,s5p6818-reset.h b/include/dt-bindings/reset/nexell,s5p6818-reset.h ---- a/include/dt-bindings/reset/nexell,s5p6818-reset.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/dt-bindings/reset/nexell,s5p6818-reset.h 2018-05-06 08:49:51.814802381 +0200 +diff --git a/include/dt-bindings/reset/nexell,s5p6818-reset.h b/include/dt-bindings/reset/nexell,s5p6818-reset.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/dt-bindings/reset/nexell,s5p6818-reset.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -257427,9 +259009,11 @@ diff -ENwbur a/include/dt-bindings/reset/nexell,s5p6818-reset.h b/include/dt-bin +#define RESET_ID_VIP0 68 +#define RESET_ID_VIP2 69 +#define RESET_ID_END (RESET_ID_VIP2) -diff -ENwbur a/include/dt-bindings/soc/s5p6818-base.h b/include/dt-bindings/soc/s5p6818-base.h ---- a/include/dt-bindings/soc/s5p6818-base.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/dt-bindings/soc/s5p6818-base.h 2018-05-06 08:49:51.814802381 +0200 +diff --git a/include/dt-bindings/soc/s5p6818-base.h b/include/dt-bindings/soc/s5p6818-base.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/dt-bindings/soc/s5p6818-base.h @@ -0,0 +1,395 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -257826,9 +259410,11 @@ diff -ENwbur a/include/dt-bindings/soc/s5p6818-base.h b/include/dt-bindings/soc/ + PL080_CONTROL_PROT_SYS) + +#endif -diff -ENwbur a/include/dt-bindings/tieoff/s5p6818-tieoff.h b/include/dt-bindings/tieoff/s5p6818-tieoff.h ---- a/include/dt-bindings/tieoff/s5p6818-tieoff.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/dt-bindings/tieoff/s5p6818-tieoff.h 2018-05-06 08:49:51.818802542 +0200 +diff --git a/include/dt-bindings/tieoff/s5p6818-tieoff.h b/include/dt-bindings/tieoff/s5p6818-tieoff.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/dt-bindings/tieoff/s5p6818-tieoff.h @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -258239,13 +259825,14 @@ diff -ENwbur a/include/dt-bindings/tieoff/s5p6818-tieoff.h b/include/dt-bindings +#define NX_TIEOFF_Inst_VR_MBUS_AXILPI_S0_CSYSACK ((1<<16) | (131*32+21)) + +#endif /* _S5P6818_TIEOFF_H */ -diff -ENwbur a/include/linux/devfreq.h b/include/linux/devfreq.h ---- a/include/linux/devfreq.h 2018-05-06 08:47:38.953410059 +0200 -+++ b/include/linux/devfreq.h 2018-05-06 08:49:51.830803031 +0200 -@@ -234,6 +234,13 @@ +diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h +index 111111111111..222222222222 100644 +--- a/include/linux/devfreq.h ++++ b/include/linux/devfreq.h +@@ -234,6 +234,13 @@ struct devfreq_simple_ondemand_data { }; #endif - + +#if IS_ENABLED(CONFIG_ARM_S5Pxx18_DEVFREQ) +struct devfreq_notifier_block { + struct notifier_block nb; @@ -258256,9 +259843,11 @@ diff -ENwbur a/include/linux/devfreq.h b/include/linux/devfreq.h #if IS_ENABLED(CONFIG_DEVFREQ_GOV_PASSIVE) /** * struct devfreq_passive_data - void *data fed to struct devfreq -diff -ENwbur a/include/linux/fence.h b/include/linux/fence.h ---- a/include/linux/fence.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/linux/fence.h 2018-05-06 08:49:51.838803354 +0200 +diff --git a/include/linux/fence.h b/include/linux/fence.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/linux/fence.h @@ -0,0 +1,377 @@ +/* + * Fence mechanism for dma-buf to allow for asynchronous dma access @@ -258637,9 +260226,11 @@ diff -ENwbur a/include/linux/fence.h b/include/linux/fence.h + } while (0) + +#endif /* __LINUX_FENCE_H */ -diff -ENwbur a/include/linux/mfd/axp228-cfg.h b/include/linux/mfd/axp228-cfg.h ---- a/include/linux/mfd/axp228-cfg.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/linux/mfd/axp228-cfg.h 2018-05-06 08:49:51.862804329 +0200 +diff --git a/include/linux/mfd/axp228-cfg.h b/include/linux/mfd/axp228-cfg.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/linux/mfd/axp228-cfg.h @@ -0,0 +1,179 @@ +/* + * axp228-cfg.h -- PMIC driver for the X-Powers AXP228 @@ -258721,9 +260312,9 @@ diff -ENwbur a/include/linux/mfd/axp228-cfg.h b/include/linux/mfd/axp228-cfg.h + +#define USBVOLLIMEN 1 + -+#define USBVOLLIM 4700 /* AXP22:4000~4700£¬100/step */ ++#define USBVOLLIM 4700 /* AXP22:4000~4700£¬100/step */ + -+#define USBVOLLIMPC 4700 /* AXP22:4000~4700£¬100/step */ ++#define USBVOLLIMPC 4700 /* AXP22:4000~4700£¬100/step */ + +#define USBCURLIMEN 0 + @@ -258820,9 +260411,11 @@ diff -ENwbur a/include/linux/mfd/axp228-cfg.h b/include/linux/mfd/axp228-cfg.h +/* #define DBG_AXP_PSY */ + +#endif -diff -ENwbur a/include/linux/mfd/axp228-mfd.h b/include/linux/mfd/axp228-mfd.h ---- a/include/linux/mfd/axp228-mfd.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/linux/mfd/axp228-mfd.h 2018-05-06 08:49:51.862804329 +0200 +diff --git a/include/linux/mfd/axp228-mfd.h b/include/linux/mfd/axp228-mfd.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/linux/mfd/axp228-mfd.h @@ -0,0 +1,307 @@ +/* + * axp228-mfd.h -- PMIC driver for the X-Powers AXP228 @@ -259131,10 +260724,11 @@ diff -ENwbur a/include/linux/mfd/axp228-mfd.h b/include/linux/mfd/axp228-mfd.h +extern int axp_clr_bits(struct device *dev, int reg, uint8_t bit_mask); +extern struct i2c_client *axp; +#endif /* __LINUX_PMIC_AXP_H */ -diff -ENwbur a/include/linux/pm_qos.h b/include/linux/pm_qos.h ---- a/include/linux/pm_qos.h 2018-05-06 08:47:39.025412983 +0200 -+++ b/include/linux/pm_qos.h 2018-05-06 08:49:51.902805952 +0200 -@@ -16,6 +16,11 @@ +diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h +index 111111111111..222222222222 100644 +--- a/include/linux/pm_qos.h ++++ b/include/linux/pm_qos.h +@@ -16,6 +16,11 @@ enum { PM_QOS_NETWORK_LATENCY, PM_QOS_NETWORK_THROUGHPUT, PM_QOS_MEMORY_BANDWIDTH, @@ -259143,10 +260737,10 @@ diff -ENwbur a/include/linux/pm_qos.h b/include/linux/pm_qos.h + PM_QOS_CPU_ONLINE_MAX, + PM_QOS_CPU_FREQ_MIN, + PM_QOS_CPU_FREQ_MAX, - + /* insert new class ID */ PM_QOS_NUM_CLASSES, -@@ -34,10 +39,15 @@ +@@ -34,10 +39,15 @@ enum pm_qos_flags_status { #define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 #define PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE 0 @@ -259159,12 +260753,14 @@ diff -ENwbur a/include/linux/pm_qos.h b/include/linux/pm_qos.h +#define PM_QOS_CPU_ONLINE_MAX_DEFAULT_VALUE -1 +#define PM_QOS_CPU_FREQ_MIN_DEFAULT_VALUE 0 +#define PM_QOS_CPU_FREQ_MAX_DEFAULT_VALUE INT_MAX - + #define PM_QOS_FLAG_NO_POWER_OFF (1 << 0) #define PM_QOS_FLAG_REMOTE_WAKEUP (1 << 1) -diff -ENwbur a/include/linux/regulator/axp228-regu.h b/include/linux/regulator/axp228-regu.h ---- a/include/linux/regulator/axp228-regu.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/linux/regulator/axp228-regu.h 2018-05-06 08:49:51.910806277 +0200 +diff --git a/include/linux/regulator/axp228-regu.h b/include/linux/regulator/axp228-regu.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/linux/regulator/axp228-regu.h @@ -0,0 +1,197 @@ +/* + * axp228-regu.h -- PMIC driver for the X-Powers AXP228 @@ -259363,9 +260959,11 @@ diff -ENwbur a/include/linux/regulator/axp228-regu.h b/include/linux/regulator/a +}; + +#endif -diff -ENwbur a/include/linux/soc/nexell/cpufreq.h b/include/linux/soc/nexell/cpufreq.h ---- a/include/linux/soc/nexell/cpufreq.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/linux/soc/nexell/cpufreq.h 2018-05-06 08:49:51.922806763 +0200 +diff --git a/include/linux/soc/nexell/cpufreq.h b/include/linux/soc/nexell/cpufreq.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/linux/soc/nexell/cpufreq.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -259427,9 +261025,11 @@ diff -ENwbur a/include/linux/soc/nexell/cpufreq.h b/include/linux/soc/nexell/cpu +void nx_bus_remove_notifier(void *data); + +#endif -diff -ENwbur a/include/linux/soc/nexell/nx-media-device.h b/include/linux/soc/nexell/nx-media-device.h ---- a/include/linux/soc/nexell/nx-media-device.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/linux/soc/nexell/nx-media-device.h 2018-05-06 08:49:51.922806763 +0200 +diff --git a/include/linux/soc/nexell/nx-media-device.h b/include/linux/soc/nexell/nx-media-device.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/linux/soc/nexell/nx-media-device.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -259459,9 +261059,11 @@ diff -ENwbur a/include/linux/soc/nexell/nx-media-device.h b/include/linux/soc/ne +}; + +#endif -diff -ENwbur a/include/linux/soc/nexell/sec_reg.h b/include/linux/soc/nexell/sec_reg.h ---- a/include/linux/soc/nexell/sec_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/linux/soc/nexell/sec_reg.h 2018-05-06 08:49:51.922806763 +0200 +diff --git a/include/linux/soc/nexell/sec_reg.h b/include/linux/soc/nexell/sec_reg.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/linux/soc/nexell/sec_reg.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -259486,19 +261088,20 @@ diff -ENwbur a/include/linux/soc/nexell/sec_reg.h b/include/linux/soc/nexell/sec +int read_sec_reg(void __iomem *reg); +#endif + -diff -ENwbur a/include/linux/stmmac.h b/include/linux/stmmac.h ---- a/include/linux/stmmac.h 2018-05-06 08:47:39.045413795 +0200 -+++ b/include/linux/stmmac.h 2018-05-06 08:49:51.926806925 +0200 -@@ -144,6 +144,8 @@ +diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h +index 111111111111..222222222222 100644 +--- a/include/linux/stmmac.h ++++ b/include/linux/stmmac.h +@@ -144,6 +144,8 @@ struct stmmac_txq_cfg { u32 prio; }; - + +struct ethtool_wolinfo; + struct plat_stmmacenet_data { int bus_id; int phy_addr; -@@ -190,5 +192,7 @@ +@@ -191,5 +193,7 @@ struct plat_stmmacenet_data { bool tso_en; int mac_port_sel_speed; bool en_tx_lpi_clockgating; @@ -259506,9 +261109,11 @@ diff -ENwbur a/include/linux/stmmac.h b/include/linux/stmmac.h + int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); }; #endif -diff -ENwbur a/include/soc/nexell/panel-nanopi.h b/include/soc/nexell/panel-nanopi.h ---- a/include/soc/nexell/panel-nanopi.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/soc/nexell/panel-nanopi.h 2018-05-06 08:49:51.974808873 +0200 +diff --git a/include/soc/nexell/panel-nanopi.h b/include/soc/nexell/panel-nanopi.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/soc/nexell/panel-nanopi.h @@ -0,0 +1,33 @@ +#ifndef _PANEL_NANOPI_H +#define _PANEL_NANOPI_H @@ -259543,9 +261148,11 @@ diff -ENwbur a/include/soc/nexell/panel-nanopi.h b/include/soc/nexell/panel-nano +bool nanopi_panelrgb_issensor_1wire(int onewireType); + +#endif // _PANEL_NANOPI_H -diff -ENwbur a/include/soc/nexell/tieoff.h b/include/soc/nexell/tieoff.h ---- a/include/soc/nexell/tieoff.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/soc/nexell/tieoff.h 2018-05-06 08:49:51.974808873 +0200 +diff --git a/include/soc/nexell/tieoff.h b/include/soc/nexell/tieoff.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/soc/nexell/tieoff.h @@ -0,0 +1,16 @@ +/* + * Header file for the Nexell tieoff control @@ -259563,9 +261170,11 @@ diff -ENwbur a/include/soc/nexell/tieoff.h b/include/soc/nexell/tieoff.h +u32 nx_tieoff_get(u32 tieoff_index); + +#endif /* __SOC_NEXELL_TIEOFF_H__ */ -diff -ENwbur a/include/uapi/drm/nexell_drm.h b/include/uapi/drm/nexell_drm.h ---- a/include/uapi/drm/nexell_drm.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/uapi/drm/nexell_drm.h 2018-05-06 08:49:51.990809523 +0200 +diff --git a/include/uapi/drm/nexell_drm.h b/include/uapi/drm/nexell_drm.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/uapi/drm/nexell_drm.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -259688,9 +261297,11 @@ diff -ENwbur a/include/uapi/drm/nexell_drm.h b/include/uapi/drm/nexell_drm.h + DRM_NX_GEM_GET, struct nx_gem_info) + +#endif -diff -ENwbur a/include/uapi/linux/nx-scaler.h b/include/uapi/linux/nx-scaler.h ---- a/include/uapi/linux/nx-scaler.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/uapi/linux/nx-scaler.h 2018-05-06 08:49:52.014810496 +0200 +diff --git a/include/uapi/linux/nx-scaler.h b/include/uapi/linux/nx-scaler.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/uapi/linux/nx-scaler.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -259746,9 +261357,11 @@ diff -ENwbur a/include/uapi/linux/nx-scaler.h b/include/uapi/linux/nx-scaler.h + IOCTL_SCALER_SET_AND_RUN = _IO(IOC_NX_MAGIC, 1), +}; +#endif -diff -ENwbur a/include/uapi/linux/videodev2_nxp_media.h b/include/uapi/linux/videodev2_nxp_media.h ---- a/include/uapi/linux/videodev2_nxp_media.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/include/uapi/linux/videodev2_nxp_media.h 2018-05-06 08:49:52.022810821 +0200 +diff --git a/include/uapi/linux/videodev2_nxp_media.h b/include/uapi/linux/videodev2_nxp_media.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/uapi/linux/videodev2_nxp_media.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -259830,13 +261443,14 @@ diff -ENwbur a/include/uapi/linux/videodev2_nxp_media.h b/include/uapi/linux/vid +#define V4L2_CID_MPEG_VIDEO_THUMBNAIL_MODE (V4L2_CID_NXP_VPU_BASE + 0xC) + +#endif -diff -ENwbur a/kernel/power/qos.c b/kernel/power/qos.c ---- a/kernel/power/qos.c 2018-05-06 08:47:39.177419154 +0200 -+++ b/kernel/power/qos.c 2018-05-06 08:49:52.058812282 +0200 -@@ -122,12 +122,82 @@ +diff --git a/kernel/power/qos.c b/kernel/power/qos.c +index 111111111111..222222222222 100644 +--- a/kernel/power/qos.c ++++ b/kernel/power/qos.c +@@ -122,12 +122,82 @@ static struct pm_qos_object memory_bandwidth_pm_qos = { }; - - + + +static BLOCKING_NOTIFIER_HEAD(bus_throughput_notifier); +static struct pm_qos_constraints bus_tput_constraints = { + .list = PLIST_HEAD_INIT(bus_tput_constraints.list), @@ -259914,28 +261528,16 @@ diff -ENwbur a/kernel/power/qos.c b/kernel/power/qos.c + &cpu_freq_min_pm_qos, + &cpu_freq_max_pm_qos, }; - + static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, -diff -ENwbur a/Makefile b/Makefile ---- a/Makefile 2018-05-06 08:47:34.973248474 +0200 -+++ b/Makefile 2018-05-06 08:49:47.990647213 +0200 -@@ -311,7 +311,9 @@ - # Default value for CROSS_COMPILE is not to prefix executables - # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile - ARCH ?= $(SUBARCH) -+ARCH = arm64 - CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) -+CROSS_COMPILE = aarch64-linux-gnu- - - # Architecture as present in compile.h - UTS_MACHINE := $(ARCH) -diff -ENwbur a/mm/page_alloc.c b/mm/page_alloc.c ---- a/mm/page_alloc.c 2018-05-06 08:47:39.257422402 +0200 -+++ b/mm/page_alloc.c 2018-05-06 08:49:52.118814717 +0200 -@@ -2447,6 +2447,22 @@ +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 111111111111..222222222222 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -2447,6 +2447,22 @@ void drain_local_pages(struct zone *zone) drain_pages(cpu); } - + +/* another version, as of smp_processor_id() cannot be used in preemptible code + */ +static void drain_local_pages_v2(struct zone *zone) @@ -259955,28 +261557,50 @@ diff -ENwbur a/mm/page_alloc.c b/mm/page_alloc.c static void drain_local_pages_wq(struct work_struct *work) { /* -@@ -7650,6 +7666,7 @@ +@@ -7648,6 +7664,7 @@ done: void free_contig_range(unsigned long pfn, unsigned nr_pages) { unsigned int count = 0; + struct zone *zone = page_zone(pfn_to_page(pfn)); - + for (; nr_pages--; pfn++) { struct page *page = pfn_to_page(pfn); -@@ -7658,6 +7675,7 @@ +@@ -7656,6 +7673,7 @@ void free_contig_range(unsigned long pfn, unsigned nr_pages) __free_page(page); } WARN(count != 0, "%d pages are still in use!\n", count); + drain_local_pages_v2(zone); } #endif - -diff -ENwbur a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c ---- a/sound/soc/codecs/es8316.c 2018-05-06 08:47:39.569435068 +0200 -+++ b/sound/soc/codecs/es8316.c 2018-05-06 08:49:52.446828026 +0200 -@@ -503,7 +503,12 @@ + +diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig +index 111111111111..222222222222 100644 +--- a/sound/soc/Kconfig ++++ b/sound/soc/Kconfig +@@ -71,6 +71,7 @@ source "sound/soc/txx9/Kconfig" + source "sound/soc/ux500/Kconfig" + source "sound/soc/xtensa/Kconfig" + source "sound/soc/zte/Kconfig" ++source "sound/soc/nexell/Kconfig" + + # Supported codecs + source "sound/soc/codecs/Kconfig" +diff --git a/sound/soc/Makefile b/sound/soc/Makefile +index 111111111111..222222222222 100644 +--- a/sound/soc/Makefile ++++ b/sound/soc/Makefile +@@ -52,3 +52,4 @@ obj-$(CONFIG_SND_SOC) += txx9/ + obj-$(CONFIG_SND_SOC) += ux500/ + obj-$(CONFIG_SND_SOC) += xtensa/ + obj-$(CONFIG_SND_SOC) += zte/ ++obj-$(CONFIG_SND_SOC) += nexell/ +diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c +index 111111111111..222222222222 100644 +--- a/sound/soc/codecs/es8316.c ++++ b/sound/soc/codecs/es8316.c +@@ -506,7 +506,12 @@ static int es8316_mute(struct snd_soc_dai *dai, int mute) SNDRV_PCM_FMTBIT_S24_LE) - + static const struct snd_soc_dai_ops es8316_ops = { - .startup = es8316_pcm_startup, + /* XXX: es8316_pcm_startup is invoked when control device is opened; @@ -259988,28 +261612,11 @@ diff -ENwbur a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c .hw_params = es8316_pcm_hw_params, .set_fmt = es8316_set_dai_fmt, .set_sysclk = es8316_set_dai_sysclk, -diff -ENwbur a/sound/soc/Kconfig b/sound/soc/Kconfig ---- a/sound/soc/Kconfig 2018-05-06 08:47:39.553434419 +0200 -+++ b/sound/soc/Kconfig 2018-05-06 08:49:52.430827377 +0200 -@@ -71,6 +71,7 @@ - source "sound/soc/ux500/Kconfig" - source "sound/soc/xtensa/Kconfig" - source "sound/soc/zte/Kconfig" -+source "sound/soc/nexell/Kconfig" - - # Supported codecs - source "sound/soc/codecs/Kconfig" -diff -ENwbur a/sound/soc/Makefile b/sound/soc/Makefile ---- a/sound/soc/Makefile 2018-05-06 08:47:39.553434419 +0200 -+++ b/sound/soc/Makefile 2018-05-06 08:49:52.430827377 +0200 -@@ -52,3 +52,4 @@ - obj-$(CONFIG_SND_SOC) += ux500/ - obj-$(CONFIG_SND_SOC) += xtensa/ - obj-$(CONFIG_SND_SOC) += zte/ -+obj-$(CONFIG_SND_SOC) += nexell/ -diff -ENwbur a/sound/soc/nexell/Kconfig b/sound/soc/nexell/Kconfig ---- a/sound/soc/nexell/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/Kconfig 2018-05-06 08:49:52.502830297 +0200 +diff --git a/sound/soc/nexell/Kconfig b/sound/soc/nexell/Kconfig +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/Kconfig @@ -0,0 +1,56 @@ +# +# Copyright 2016 Nexell. @@ -260067,9 +261674,11 @@ diff -ENwbur a/sound/soc/nexell/Kconfig b/sound/soc/nexell/Kconfig + tristate "ALC5658 I2S audio codec." + depends on SND_NX_I2S + select SND_SOC_RT5659 -diff -ENwbur a/sound/soc/nexell/Makefile b/sound/soc/nexell/Makefile ---- a/sound/soc/nexell/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/Makefile 2018-05-06 08:49:52.502830297 +0200 +diff --git a/sound/soc/nexell/Makefile b/sound/soc/nexell/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/Makefile @@ -0,0 +1,22 @@ +# +# Copyright 2016 Nexell Co. @@ -260093,9 +261702,11 @@ diff -ENwbur a/sound/soc/nexell/Makefile b/sound/soc/nexell/Makefile +nexell-snd-alc5658-objs := nexell-alc5658.o +nexell-snd-null-objs := nexell-null.o +nexell-snd-spdif-transceiver-objs := nexell-spdif-transceiver.o -diff -ENwbur a/sound/soc/nexell/nexell-alc5658.c b/sound/soc/nexell/nexell-alc5658.c ---- a/sound/soc/nexell/nexell-alc5658.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/nexell-alc5658.c 2018-05-06 08:49:52.502830297 +0200 +diff --git a/sound/soc/nexell/nexell-alc5658.c b/sound/soc/nexell/nexell-alc5658.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/nexell-alc5658.c @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2016 YICSYSTEM Co., Ltd. @@ -260530,9 +262141,11 @@ diff -ENwbur a/sound/soc/nexell/nexell-alc5658.c b/sound/soc/nexell/nexell-alc56 +MODULE_AUTHOR("david yeo < yhyeo@yicsystem.com >"); +MODULE_DESCRIPTION("Sound codec-alc5658 driver for Nexell sound"); +MODULE_LICENSE("GPL"); -diff -ENwbur a/sound/soc/nexell/nexell-es8316.c b/sound/soc/nexell/nexell-es8316.c ---- a/sound/soc/nexell/nexell-es8316.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/nexell-es8316.c 2018-05-06 08:49:52.502830297 +0200 +diff --git a/sound/soc/nexell/nexell-es8316.c b/sound/soc/nexell/nexell-es8316.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/nexell-es8316.c @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -260996,9 +262609,11 @@ diff -ENwbur a/sound/soc/nexell/nexell-es8316.c b/sound/soc/nexell/nexell-es8316 +MODULE_AUTHOR("hsjung "); +MODULE_DESCRIPTION("Sound codec-es8316 driver for Nexell sound"); +MODULE_LICENSE("GPL"); -diff -ENwbur a/sound/soc/nexell/nexell-i2s.c b/sound/soc/nexell/nexell-i2s.c ---- a/sound/soc/nexell/nexell-i2s.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/nexell-i2s.c 2018-05-06 08:49:52.502830297 +0200 +diff --git a/sound/soc/nexell/nexell-i2s.c b/sound/soc/nexell/nexell-i2s.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/nexell-i2s.c @@ -0,0 +1,914 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -261914,9 +263529,11 @@ diff -ENwbur a/sound/soc/nexell/nexell-i2s.c b/sound/soc/nexell/nexell-i2s.c +MODULE_AUTHOR("hsjung "); +MODULE_DESCRIPTION("Sound I2S driver for Nexell sound"); +MODULE_LICENSE("GPL"); -diff -ENwbur a/sound/soc/nexell/nexell-i2s.h b/sound/soc/nexell/nexell-i2s.h ---- a/sound/soc/nexell/nexell-i2s.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/nexell-i2s.h 2018-05-06 08:49:52.502830297 +0200 +diff --git a/sound/soc/nexell/nexell-i2s.h b/sound/soc/nexell/nexell-i2s.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/nexell-i2s.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -261949,9 +263566,11 @@ diff -ENwbur a/sound/soc/nexell/nexell-i2s.h b/sound/soc/nexell/nexell-i2s.h + +#endif /* __NX_I2S_H__ */ + -diff -ENwbur a/sound/soc/nexell/nexell-null.c b/sound/soc/nexell/nexell-null.c ---- a/sound/soc/nexell/nexell-null.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/nexell-null.c 2018-05-06 08:49:52.502830297 +0200 +diff --git a/sound/soc/nexell/nexell-null.c b/sound/soc/nexell/nexell-null.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/nexell-null.c @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -262191,9 +263810,11 @@ diff -ENwbur a/sound/soc/nexell/nexell-null.c b/sound/soc/nexell/nexell-null.c +MODULE_AUTHOR("hsjung "); +MODULE_DESCRIPTION("Sound codec-null driver for Nexell Audio"); +MODULE_LICENSE("GPL"); -diff -ENwbur a/sound/soc/nexell/nexell-pcm.c b/sound/soc/nexell/nexell-pcm.c ---- a/sound/soc/nexell/nexell-pcm.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/nexell-pcm.c 2018-05-06 08:49:52.502830297 +0200 +diff --git a/sound/soc/nexell/nexell-pcm.c b/sound/soc/nexell/nexell-pcm.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/nexell-pcm.c @@ -0,0 +1,649 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -262844,9 +264465,11 @@ diff -ENwbur a/sound/soc/nexell/nexell-pcm.c b/sound/soc/nexell/nexell-pcm.c +MODULE_DESCRIPTION("Sound PCM driver for Nexell sound"); +MODULE_LICENSE("GPL"); + -diff -ENwbur a/sound/soc/nexell/nexell-pcm.h b/sound/soc/nexell/nexell-pcm.h ---- a/sound/soc/nexell/nexell-pcm.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/nexell-pcm.h 2018-05-06 08:49:52.502830297 +0200 +diff --git a/sound/soc/nexell/nexell-pcm.h b/sound/soc/nexell/nexell-pcm.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/nexell-pcm.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -262928,43 +264551,11 @@ diff -ENwbur a/sound/soc/nexell/nexell-pcm.h b/sound/soc/nexell/nexell-pcm.h +extern struct snd_soc_platform_driver nx_pcm_platform; + +#endif -diff -ENwbur a/sound/soc/nexell/nexell-spdif.h b/sound/soc/nexell/nexell-spdif.h ---- a/sound/soc/nexell/nexell-spdif.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/nexell-spdif.h 2018-05-06 08:49:52.502830297 +0200 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2016 Nexell Co., Ltd. -+ * Author: Hyunseok, Jung -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef __NX_SPDIF_H__ -+#define __NX_SPDIF_H__ -+ -+#include "nexell-pcm.h" -+ -+#define SND_SOC_SPDIF_TX_FORMATS \ -+ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) -+ -+#define SND_SOC_SPDIF_RATES \ -+ (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) -+ -+#endif /* __NX_SPDIF_H__ */ -diff -ENwbur a/sound/soc/nexell/nexell-spdif-transceiver.c b/sound/soc/nexell/nexell-spdif-transceiver.c ---- a/sound/soc/nexell/nexell-spdif-transceiver.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/nexell-spdif-transceiver.c 2018-05-06 08:49:52.502830297 +0200 +diff --git a/sound/soc/nexell/nexell-spdif-transceiver.c b/sound/soc/nexell/nexell-spdif-transceiver.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/nexell-spdif-transceiver.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -263103,9 +264694,47 @@ diff -ENwbur a/sound/soc/nexell/nexell-spdif-transceiver.c b/sound/soc/nexell/ne +MODULE_AUTHOR("Hyunseok Jung "); +MODULE_DESCRIPTION("Sound SPDIF transceiver driver for Nexell sound"); +MODULE_LICENSE("GPL"); -diff -ENwbur a/sound/soc/nexell/nexell-spdiftx.c b/sound/soc/nexell/nexell-spdiftx.c ---- a/sound/soc/nexell/nexell-spdiftx.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/sound/soc/nexell/nexell-spdiftx.c 2018-05-06 08:49:52.506830461 +0200 +diff --git a/sound/soc/nexell/nexell-spdif.h b/sound/soc/nexell/nexell-spdif.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/nexell-spdif.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (C) 2016 Nexell Co., Ltd. ++ * Author: Hyunseok, Jung ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#ifndef __NX_SPDIF_H__ ++#define __NX_SPDIF_H__ ++ ++#include "nexell-pcm.h" ++ ++#define SND_SOC_SPDIF_TX_FORMATS \ ++ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) ++ ++#define SND_SOC_SPDIF_RATES \ ++ (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) ++ ++#endif /* __NX_SPDIF_H__ */ +diff --git a/sound/soc/nexell/nexell-spdiftx.c b/sound/soc/nexell/nexell-spdiftx.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/sound/soc/nexell/nexell-spdiftx.c @@ -0,0 +1,631 @@ +/* + * Copyright (C) 2016 Nexell Co., Ltd. @@ -263738,3 +265367,6 @@ diff -ENwbur a/sound/soc/nexell/nexell-spdiftx.c b/sound/soc/nexell/nexell-spdif +MODULE_AUTHOR("Hyunseok Jung "); +MODULE_DESCRIPTION("Sound S/PDIF tx driver for Nexell sound"); +MODULE_LICENSE("GPL"); +-- +Armbian + diff --git a/patch/kernel/archive/s5p6818-4.14/set-DMA-coherent-pool-to-2M.patch b/patch/kernel/archive/s5p6818-4.14/set-DMA-coherent-pool-to-2M.patch index 1c4d60250208..22944ccdb1a8 100644 --- a/patch/kernel/archive/s5p6818-4.14/set-DMA-coherent-pool-to-2M.patch +++ b/patch/kernel/archive/s5p6818-4.14/set-DMA-coherent-pool-to-2M.patch @@ -1,13 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Igor Pecovnik +Date: Mon, 21 Aug 2017 08:54:53 +0200 +Subject: [ARCHEOLOGY] Increasing DMA block memory allocation to 2048k on all + relevant kernels. + +> X-Git-Archeology: > recovered message: > https://forum.armbian.com/index.php?/topic/4811-uas-mainline-kernel-coherent-pool-memory-size +> X-Git-Archeology: - Revision 908bb199ec2defd77f7f05d2016980abf100d627: https://github.com/armbian/build/commit/908bb199ec2defd77f7f05d2016980abf100d627 +> X-Git-Archeology: Date: Mon, 21 Aug 2017 08:54:53 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Increasing DMA block memory allocation to 2048k on all relevant kernels. +> X-Git-Archeology: +> X-Git-Archeology: - Revision a3cf7b74858e1f862db8ca238bd44f6406be6662: https://github.com/armbian/build/commit/a3cf7b74858e1f862db8ca238bd44f6406be6662 +> X-Git-Archeology: Date: Mon, 21 Aug 2017 17:52:29 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Revert "Increasing DMA block memory allocation to 2048k on all relevant kernels." +> X-Git-Archeology: +> X-Git-Archeology: - Revision 2be21aad5dc965b3bc67e136a1e1170119d60f74: https://github.com/armbian/build/commit/2be21aad5dc965b3bc67e136a1e1170119d60f74 +> X-Git-Archeology: Date: Mon, 21 Aug 2017 17:52:48 +0200 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Increasing DMA block memory allocation to 2048k on all relevant kernels. https://forum.armbian.com/index.php?/topic/4811-uas-mainline-kernel-coherent-pool-memory-size +> X-Git-Archeology: +> X-Git-Archeology: - Revision b878ee203611c195d7f817966950cec817667250: https://github.com/armbian/build/commit/b878ee203611c195d7f817966950cec817667250 +> X-Git-Archeology: Date: Sun, 17 Sep 2017 16:54:06 +0300 +> X-Git-Archeology: From: zador-blood-stained +> X-Git-Archeology: Subject: Clean up and update sunxi-next patches +> X-Git-Archeology: +> X-Git-Archeology: - Revision 13e94e58f04be27db51d18b7dac1d15a1864b79e: https://github.com/armbian/build/commit/13e94e58f04be27db51d18b7dac1d15a1864b79e +> X-Git-Archeology: Date: Fri, 27 Oct 2017 16:14:21 +0300 +> X-Git-Archeology: From: zador-blood-stained +> X-Git-Archeology: Subject: Remove random executable bits from patch files +> X-Git-Archeology: +> X-Git-Archeology: - Revision a134e34af8522a933c701fdbe1151494e79950dc: https://github.com/armbian/build/commit/a134e34af8522a933c701fdbe1151494e79950dc +> X-Git-Archeology: Date: Wed, 06 Dec 2017 22:27:43 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Added FriendlyARM Nanopi M3 mainline target (NEXT). Based on @rafaello7 work - kudos! Tested both CLI http://sprunge.us/bHRO and desktop image: https://www.armbian.com/nanopi-m3 Changed status from CSC to WIP. +> X-Git-Archeology: +> X-Git-Archeology: - Revision 150ac0c2afa147d9e3b036c8ecd8238fe5648cf3: https://github.com/armbian/build/commit/150ac0c2afa147d9e3b036c8ecd8238fe5648cf3 +> X-Git-Archeology: Date: Tue, 19 Nov 2019 23:25:39 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Remove K<4, change branches, new features (#1586) +> X-Git-Archeology: +> X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153 +> X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704) +> X-Git-Archeology: +--- + arch/arm/mm/dma-mapping.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c -index bd83c53..af7cfe3 +index 111111111111..222222222222 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c -@@ -374,7 +374,7 @@ static void __dma_free_remap(void *cpu_addr, size_t size) +@@ -381,7 +381,7 @@ static void __dma_free_remap(void *cpu_addr, size_t size) VM_ARM_DMA_CONSISTENT | VM_USERMAP); } - + -#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K +#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_2M static struct gen_pool *atomic_pool; - + static size_t atomic_pool_size = DEFAULT_DMA_COHERENT_POOL_SIZE; +-- +Armbian + diff --git a/patch/kernel/archive/s5p6818-4.14/update-nanopi-fire3-support.patch b/patch/kernel/archive/s5p6818-4.14/update-nanopi-fire3-support.patch index 6ad438ae19d3..cdef9bff6466 100644 --- a/patch/kernel/archive/s5p6818-4.14/update-nanopi-fire3-support.patch +++ b/patch/kernel/archive/s5p6818-4.14/update-nanopi-fire3-support.patch @@ -1,5 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: 5kft <38135790+5kft@users.noreply.github.com> +Date: Sun, 15 Jul 2018 12:14:42 +0200 +Subject: [ARCHEOLOGY] Improve support for the NanoPi Fire 3 (add SPU1705, + DVFS, thermal tables, etc.) + +> X-Git-Archeology: > recovered message: > * implemented improved support for the FriendlyArm NanoPi Fire3 +> X-Git-Archeology: > recovered message: > * introduced new WIP board configuration "nanopifire3" +> X-Git-Archeology: > recovered message: > * added and enabled the FA SPU1705 regulator +> X-Git-Archeology: > recovered message: > * enabled CPU-based thermal support +> X-Git-Archeology: > recovered message: > * implemented DT-based DVFS table (400MHz-1.4GHz) +> X-Git-Archeology: > recovered message: > * fixed and updated the thermal table and cooling maps +> X-Git-Archeology: > recovered message: > * added support for the onboard LED +> X-Git-Archeology: > recovered message: > * minor patch cleanup +> X-Git-Archeology: - Revision 946289313838e120bf5a9957d89aca2875ac2436: https://github.com/armbian/build/commit/946289313838e120bf5a9957d89aca2875ac2436 +> X-Git-Archeology: Date: Sun, 15 Jul 2018 12:14:42 +0200 +> X-Git-Archeology: From: 5kft <38135790+5kft@users.noreply.github.com> +> X-Git-Archeology: Subject: Improve support for the NanoPi Fire 3 (add SPU1705, DVFS, thermal tables, etc.) +> X-Git-Archeology: +> X-Git-Archeology: - Revision 1301f9f8c254d8408b9136948c786dffa5007acd: https://github.com/armbian/build/commit/1301f9f8c254d8408b9136948c786dffa5007acd +> X-Git-Archeology: Date: Sun, 18 Nov 2018 16:52:31 +0000 +> X-Git-Archeology: From: 5kft <5kft@users.noreply.github.com> +> X-Git-Archeology: Subject: [s5p6818-next Fire3] implemented support for board power-off via PWRKEY +> X-Git-Archeology: +> X-Git-Archeology: - Revision 150ac0c2afa147d9e3b036c8ecd8238fe5648cf3: https://github.com/armbian/build/commit/150ac0c2afa147d9e3b036c8ecd8238fe5648cf3 +> X-Git-Archeology: Date: Tue, 19 Nov 2019 23:25:39 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Remove K<4, change branches, new features (#1586) +> X-Git-Archeology: +> X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153 +> X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100 +> X-Git-Archeology: From: Igor Pecovnik +> X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704) +> X-Git-Archeology: +--- + arch/arm64/boot/dts/nexell/Makefile | 1 + + arch/arm64/boot/dts/nexell/s5p6818-nanopi-fire3.dts | 837 ++++++++++ + arch/arm64/configs/nanopim3_defconfig | 5 +- + drivers/cpufreq/nexell-cpufreq.c | 32 +- + drivers/regulator/Kconfig | 6 + + drivers/regulator/Makefile | 1 + + drivers/regulator/spu1705.c | 596 +++++++ + include/linux/regulator/spu1705.h | 44 + + 8 files changed, 1509 insertions(+), 13 deletions(-) + diff --git a/arch/arm64/boot/dts/nexell/Makefile b/arch/arm64/boot/dts/nexell/Makefile -index 46364d6a..7f4dcadb 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/nexell/Makefile +++ b/arch/arm64/boot/dts/nexell/Makefile @@ -1,4 +1,5 @@ @@ -10,7 +55,7 @@ index 46364d6a..7f4dcadb 100644 subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/nexell/s5p6818-nanopi-fire3.dts b/arch/arm64/boot/dts/nexell/s5p6818-nanopi-fire3.dts new file mode 100644 -index 00000000..25ac71dd +index 000000000000..111111111111 --- /dev/null +++ b/arch/arm64/boot/dts/nexell/s5p6818-nanopi-fire3.dts @@ -0,0 +1,837 @@ @@ -852,7 +897,7 @@ index 00000000..25ac71dd +}; + diff --git a/arch/arm64/configs/nanopim3_defconfig b/arch/arm64/configs/nanopim3_defconfig -index 662657a2..fba15ac2 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/configs/nanopim3_defconfig +++ b/arch/arm64/configs/nanopim3_defconfig @@ -2032,8 +2032,8 @@ CONFIG_THERMAL_GOV_STEP_WISE=y @@ -875,7 +920,7 @@ index 662657a2..fba15ac2 100644 # CONFIG_REGULATOR_TPS62360 is not set # CONFIG_REGULATOR_TPS65023 is not set diff --git a/drivers/cpufreq/nexell-cpufreq.c b/drivers/cpufreq/nexell-cpufreq.c -index 94a00121..f698a270 100644 +index 111111111111..222222222222 100644 --- a/drivers/cpufreq/nexell-cpufreq.c +++ b/drivers/cpufreq/nexell-cpufreq.c @@ -713,6 +713,7 @@ static void *nxp_cpufreq_make_table(struct platform_device *pdev, @@ -932,7 +977,7 @@ index 94a00121..f698a270 100644 freq_table[id].frequency = CPUFREQ_TABLE_END; *table_size = id; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig -index 32763d82..db3f7cb8 100644 +index 111111111111..222222222222 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -776,6 +776,12 @@ config REGULATOR_STM32_VREFBUF @@ -949,7 +994,7 @@ index 32763d82..db3f7cb8 100644 tristate "TI Adaptive Body Bias on-chip LDO" depends on ARCH_OMAP diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile -index 24b2ff3f..4e6ddfec 100644 +index 111111111111..222222222222 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -96,6 +96,7 @@ obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o @@ -962,7 +1007,7 @@ index 24b2ff3f..4e6ddfec 100644 obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o diff --git a/drivers/regulator/spu1705.c b/drivers/regulator/spu1705.c new file mode 100644 -index 00000000..b021e5d4 +index 000000000000..111111111111 --- /dev/null +++ b/drivers/regulator/spu1705.c @@ -0,0 +1,596 @@ @@ -1564,7 +1609,7 @@ index 00000000..b021e5d4 +MODULE_DESCRIPTION("SPU1705 PMIC driver"); diff --git a/include/linux/regulator/spu1705.h b/include/linux/regulator/spu1705.h new file mode 100644 -index 00000000..03fce65e +index 000000000000..111111111111 --- /dev/null +++ b/include/linux/regulator/spu1705.h @@ -0,0 +1,44 @@ @@ -1612,3 +1657,6 @@ index 00000000..03fce65e +}; + +#endif /* __LINUX_REGULATOR_SPU1705_H */ +-- +Armbian + From 05ffbe7f7bf7e3b76d673b61eee534cbc29b1676 Mon Sep 17 00:00:00 2001 From: Ricardo Pardini Date: Mon, 10 Jun 2024 19:51:08 +0200 Subject: [PATCH 05/53] s5p6818-legacy: drop un-needed symlink to archive/s5p818-4.14 - `common_defaults_for_mainline` already sets KERNELPATCHDIR='archive/s5p6818-4.14' thus this symlink is not necessary - 1 step closer to a clean `patch/kernel` dir, when we could finally get rid of `archive/` --- patch/kernel/s5p6818-legacy | 1 - 1 file changed, 1 deletion(-) delete mode 120000 patch/kernel/s5p6818-legacy diff --git a/patch/kernel/s5p6818-legacy b/patch/kernel/s5p6818-legacy deleted file mode 120000 index 0a045714d457..000000000000 --- a/patch/kernel/s5p6818-legacy +++ /dev/null @@ -1 +0,0 @@ -archive/s5p6818-4.14 \ No newline at end of file From 05dbbd654aa92f4a291806fb2f347df095a00e6f Mon Sep 17 00:00:00 2001 From: Alessandro Lannocca Date: Sun, 9 Jun 2024 11:18:12 +0200 Subject: [PATCH 06/53] rk-35xx-vendor-6.1 minor touches: - move CONFIG_INPUT_RK805_PWRKEY and CONFIG_PINCTRL_RK805 to modules - move CONFIG_BT to module --- config/kernel/linux-rk35xx-vendor.config | 279 ++++++++++++++++++++++- 1 file changed, 267 insertions(+), 12 deletions(-) diff --git a/config/kernel/linux-rk35xx-vendor.config b/config/kernel/linux-rk35xx-vendor.config index f54c6d90ada7..380b537f7ba0 100644 --- a/config/kernel/linux-rk35xx-vendor.config +++ b/config/kernel/linux-rk35xx-vendor.config @@ -189,6 +189,7 @@ CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_PERF=y CONFIG_CGROUP_BPF=y # CONFIG_CGROUP_MISC is not set +# CONFIG_CGROUP_DEBUG is not set CONFIG_SOCK_CGROUP_DATA=y CONFIG_NAMESPACES=y CONFIG_UTS_NS=y @@ -218,9 +219,10 @@ CONFIG_LD_ORPHAN_WARN=y CONFIG_SYSCTL=y CONFIG_HAVE_UID16=y CONFIG_SYSCTL_EXCEPTION_TRACE=y -# CONFIG_EXPERT is not set +CONFIG_EXPERT=y CONFIG_UID16=y CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set CONFIG_SYSFS_SYSCALL=y CONFIG_FHANDLE=y CONFIG_POSIX_TIMERS=y @@ -240,18 +242,22 @@ CONFIG_IO_URING=y CONFIG_ADVISE_SYSCALLS=y CONFIG_MEMBARRIER=y CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y CONFIG_KCMP=y CONFIG_RSEQ=y +# CONFIG_DEBUG_RSEQ is not set # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y CONFIG_GUEST_PERF_EVENTS=y +# CONFIG_PC104 is not set # # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set # end of Kernel Performance Events And Counters CONFIG_SYSTEM_DATA_VERIFICATION=y @@ -504,6 +510,7 @@ CONFIG_DMI=y # CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set # CONFIG_HIBERNATION is not set CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y @@ -515,6 +522,7 @@ CONFIG_PM_DEBUG=y CONFIG_PM_ADVANCED_DEBUG=y # CONFIG_PM_TEST_SUSPEND is not set CONFIG_PM_SLEEP_DEBUG=y +# CONFIG_DPM_WATCHDOG is not set CONFIG_PM_CLK=y CONFIG_PM_GENERIC_DOMAINS=y CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y @@ -729,6 +737,7 @@ CONFIG_MODULE_COMPRESS_NONE=y # CONFIG_MODULE_COMPRESS_ZSTD is not set # CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set CONFIG_MODPROBE_PATH="/sbin/modprobe" +# CONFIG_TRIM_UNUSED_KSYMS is not set CONFIG_MODULES_TREE_LOOKUP=y CONFIG_BLOCK=y CONFIG_BLOCK_LEGACY_AUTOLOAD=y @@ -883,6 +892,7 @@ CONFIG_ZSMALLOC=m # # CONFIG_SLAB is not set CONFIG_SLUB=y +# CONFIG_SLOB is not set CONFIG_SLAB_MERGE_DEFAULT=y # CONFIG_SLAB_FREELIST_RANDOM is not set # CONFIG_SLAB_FREELIST_HARDENED is not set @@ -921,6 +931,7 @@ CONFIG_ARCH_WANTS_THP_SWAP=y # CONFIG_TRANSPARENT_HUGEPAGE is not set CONFIG_CMA=y # CONFIG_CMA_INACTIVE is not set +# CONFIG_CMA_DEBUG is not set CONFIG_CMA_DEBUGFS=y CONFIG_CMA_DEBUGFS_BITMAP_HEX=y CONFIG_CMA_SYSFS=y @@ -931,6 +942,7 @@ CONFIG_GENERIC_EARLY_IOREMAP=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CURRENT_STACK_POINTER=y CONFIG_ARCH_HAS_PTE_DEVMAP=y +CONFIG_ARCH_HAS_ZONE_DMA_SET=y CONFIG_ZONE_DMA=y CONFIG_ZONE_DMA32=y CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y @@ -1444,6 +1456,12 @@ CONFIG_IP_DCCP_CCID3=y CONFIG_IP_DCCP_TFRC_LIB=y # end of DCCP CCIDs Configuration +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set +# end of DCCP Kernel Hacking + CONFIG_IP_SCTP=m # CONFIG_SCTP_DBG_OBJCNT is not set CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y @@ -1661,7 +1679,7 @@ CONFIG_CAN_BCM=m CONFIG_CAN_GW=m # CONFIG_CAN_J1939 is not set # CONFIG_CAN_ISOTP is not set -CONFIG_BT=y +CONFIG_BT=m CONFIG_BT_BREDR=y CONFIG_BT_RFCOMM=m CONFIG_BT_RFCOMM_TTY=y @@ -1676,6 +1694,7 @@ CONFIG_BT_LEDS=y CONFIG_BT_MSFTEXT=y # CONFIG_BT_AOSPEXT is not set CONFIG_BT_DEBUGFS=y +# CONFIG_BT_SELFTEST is not set # # Bluetooth device drivers @@ -1732,6 +1751,7 @@ CONFIG_WEXT_PRIV=y CONFIG_CFG80211=y CONFIG_NL80211_TESTMODE=y # CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y CONFIG_CFG80211_DEFAULT_PS=y @@ -1816,11 +1836,17 @@ CONFIG_PCIE_PME=y CONFIG_PCI_MSI=y CONFIG_PCI_MSI_IRQ_DOMAIN=y CONFIG_PCI_QUIRKS=y +# CONFIG_PCI_DEBUG is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set # CONFIG_PCI_PRI is not set # CONFIG_PCI_PASID is not set CONFIG_PCI_LABEL=y +# CONFIG_PCIE_BUS_TUNE_OFF is not set +CONFIG_PCIE_BUS_DEFAULT=y +# CONFIG_PCIE_BUS_SAFE is not set +# CONFIG_PCIE_BUS_PERFORMANCE is not set +# CONFIG_PCIE_BUS_PEER2PEER is not set CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_HOTPLUG_PCI is not set @@ -1913,6 +1939,9 @@ CONFIG_FW_CACHE=y CONFIG_WANT_DEV_COREDUMP=y CONFIG_ALLOW_DEV_COREDUMP=y CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set # CONFIG_TEST_ASYNC_DRIVER_PROBE is not set CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_CPU_VULNERABILITIES=y @@ -1964,6 +1993,7 @@ CONFIG_ARM_SCMI_POWER_DOMAIN=y # end of ARM System Control and Management Interface Protocol # CONFIG_ARM_SCPI_PROTOCOL is not set +# CONFIG_FIRMWARE_MEMMAP is not set CONFIG_DMIID=y # CONFIG_DMI_SYSFS is not set # CONFIG_FW_CFG_SYSFS is not set @@ -3123,7 +3153,6 @@ CONFIG_RTL8822BU=m CONFIG_RTL8821CU=m CONFIG_88XXAU=m CONFIG_RTL8192EU=m -# CONFIG_RTL8189FS is not set CONFIG_RTL8189ES=m CONFIG_WLAN_VENDOR_ZYDAS=y CONFIG_USB_ZD1201=m @@ -3506,7 +3535,7 @@ CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_PWM_BEEPER is not set # CONFIG_INPUT_PWM_VIBRA is not set -CONFIG_INPUT_RK805_PWRKEY=y +CONFIG_INPUT_RK805_PWRKEY=m # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set # CONFIG_INPUT_DA7280_HAPTICS is not set # CONFIG_INPUT_ADXL34X is not set @@ -3613,6 +3642,7 @@ CONFIG_SERIAL_MCTRL_GPIO=y # CONFIG_HVC_DCC is not set CONFIG_SERIAL_DEV_BUS=y CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +# CONFIG_TTY_PRINTK is not set # CONFIG_VIRTIO_CONSOLE is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_IPMB_DEVICE_INTERFACE is not set @@ -3746,6 +3776,7 @@ CONFIG_I2C_SLAVE_TESTUNIT=m # CONFIG_I3C is not set CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set CONFIG_SPI_MASTER=y CONFIG_SPI_MEM=y @@ -3842,11 +3873,12 @@ CONFIG_PINCTRL=y CONFIG_PINMUX=y CONFIG_PINCONF=y CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set # CONFIG_PINCTRL_CY8C95X0 is not set # CONFIG_PINCTRL_MCP23S08 is not set # CONFIG_PINCTRL_MICROCHIP_SGPIO is not set # CONFIG_PINCTRL_OCELOT is not set -CONFIG_PINCTRL_RK805=y +CONFIG_PINCTRL_RK805=m CONFIG_PINCTRL_RK806=y CONFIG_PINCTRL_ROCKCHIP=y # CONFIG_PINCTRL_SINGLE is not set @@ -3862,6 +3894,8 @@ CONFIG_GPIOLIB=y CONFIG_GPIOLIB_FASTPATH_LIMIT=512 CONFIG_OF_GPIO=y CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y CONFIG_GPIO_CDEV=y CONFIG_GPIO_CDEV_V1=y CONFIG_GPIO_GENERIC=y @@ -4981,8 +5015,6 @@ CONFIG_VIDEOBUF2_DMA_SG=y CONFIG_VIDEOBUF2_DVB=m # end of Media drivers -CONFIG_MEDIA_HIDE_ANCILLARY_SUBDRV=y - # # Media ancillary drivers # @@ -5193,30 +5225,132 @@ CONFIG_VIDEO_SGM3784=m # end of Flash devices # -# audio, video and radio I2C drivers auto-selected by 'Autoselect ancillary drivers' +# Audio decoders, processors and mixers # +# CONFIG_VIDEO_CS3308 is not set +# CONFIG_VIDEO_CS5345 is not set CONFIG_VIDEO_CS53L32A=m CONFIG_VIDEO_MSP3400=m CONFIG_VIDEO_SONY_BTF_MPX=m +# CONFIG_VIDEO_TDA1997X is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_TVAUDIO is not set CONFIG_VIDEO_UDA1342=m +# CONFIG_VIDEO_VP27SMPX is not set +# CONFIG_VIDEO_WM8739 is not set CONFIG_VIDEO_WM8775=m +# end of Audio decoders, processors and mixers + +# +# RDS decoders +# CONFIG_VIDEO_SAA6588=m +# end of RDS decoders + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7183 is not set +# CONFIG_VIDEO_ADV748X is not set +# CONFIG_VIDEO_ADV7604 is not set +# CONFIG_VIDEO_ADV7842 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_EP9461E is not set +# CONFIG_VIDEO_ISL7998X is not set +# CONFIG_VIDEO_IT6616 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_LT6911UXC is not set +# CONFIG_VIDEO_LT6911UXE is not set +# CONFIG_VIDEO_LT7911D is not set +# CONFIG_VIDEO_LT7911UXC is not set +# CONFIG_VIDEO_LT8619C is not set +# CONFIG_VIDEO_MAX9286 is not set +# CONFIG_VIDEO_MAX96712 is not set +# CONFIG_VIDEO_MAX96714 is not set +# CONFIG_VIDEO_MAX96722 is not set +# CONFIG_VIDEO_MAX96756 is not set +# CONFIG_VIDEO_ML86V7667 is not set +# CONFIG_VIDEO_NVP6158 is not set +# CONFIG_VIDEO_NVP6188 is not set +# CONFIG_VIDEO_NVP6324 is not set CONFIG_VIDEO_OTP_EEPROM=m +# CONFIG_VIDEO_SAA7110 is not set CONFIG_VIDEO_SAA711X=m +# CONFIG_VIDEO_TC358743 is not set +# CONFIG_VIDEO_TC35874X is not set +# CONFIG_VIDEO_TECHPOINT is not set +# CONFIG_VIDEO_THCV244 is not set +# CONFIG_VIDEO_TVP514X is not set CONFIG_VIDEO_TVP5150=m +# CONFIG_VIDEO_TVP7002 is not set CONFIG_VIDEO_TW2804=m CONFIG_VIDEO_TW9903=m CONFIG_VIDEO_TW9906=m +# CONFIG_VIDEO_TW9910 is not set +# CONFIG_VIDEO_VPX3220 is not set +# CONFIG_VIDEO_RK628_CSI is not set +# CONFIG_VIDEO_RK628_BT1120 is not set +# CONFIG_VIDEO_DES_MAXIM2C is not set +# CONFIG_VIDEO_DES_MAXIM4C is not set # # Video and audio decoders # +# CONFIG_VIDEO_SAA717X is not set CONFIG_VIDEO_CX25840=m +# CONFIG_VIDEO_IT66353 is not set +# end of Video decoders + +# +# Video encoders +# +# CONFIG_VIDEO_AD9389B is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_ADV7393 is not set +# CONFIG_VIDEO_ADV7511 is not set +# CONFIG_VIDEO_AK881X is not set +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_THS8200 is not set +# end of Video encoders + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set +# end of Video improvement chips + +# +# Audio/Video compression chips +# CONFIG_VIDEO_SAA6752HS=m +# end of Audio/Video compression chips # -# SPI I2C drivers auto-selected by 'Autoselect ancillary drivers' +# SDR tuner chips # +# CONFIG_SDR_MAX2175 is not set +# end of SDR tuner chips + +# +# Miscellaneous helper chips +# +# CONFIG_VIDEO_I2C is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_RK_IRCUT is not set +# CONFIG_VIDEO_ST_MIPID02 is not set +# CONFIG_VIDEO_THS7303 is not set +# end of Miscellaneous helper chips # # Media SPI Adapters @@ -5229,7 +5363,7 @@ CONFIG_VIDEO_GS1662=m CONFIG_MEDIA_TUNER=y # -# Tuner drivers auto-selected by 'Autoselect ancillary drivers' +# Customize TV tuners # CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC0011=m @@ -5237,12 +5371,15 @@ CONFIG_MEDIA_TUNER_FC0012=m CONFIG_MEDIA_TUNER_FC0013=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_IT913X=m +# CONFIG_MEDIA_TUNER_M88RS6000T is not set +# CONFIG_MEDIA_TUNER_MAX2165 is not set CONFIG_MEDIA_TUNER_MC44S803=y CONFIG_MEDIA_TUNER_MSI001=m CONFIG_MEDIA_TUNER_MT2060=m CONFIG_MEDIA_TUNER_MT2063=m CONFIG_MEDIA_TUNER_MT20XX=y CONFIG_MEDIA_TUNER_MT2131=m +# CONFIG_MEDIA_TUNER_MT2266 is not set CONFIG_MEDIA_TUNER_MXL301RF=m CONFIG_MEDIA_TUNER_MXL5005S=m CONFIG_MEDIA_TUNER_MXL5007T=m @@ -5254,6 +5391,7 @@ CONFIG_MEDIA_TUNER_SI2157=m CONFIG_MEDIA_TUNER_SIMPLE=y CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_TDA18218=m +# CONFIG_MEDIA_TUNER_TDA18250 is not set CONFIG_MEDIA_TUNER_TDA18271=y CONFIG_MEDIA_TUNER_TDA827X=y CONFIG_MEDIA_TUNER_TDA8290=y @@ -5264,9 +5402,10 @@ CONFIG_MEDIA_TUNER_TUA9001=m CONFIG_MEDIA_TUNER_XC2028=y CONFIG_MEDIA_TUNER_XC4000=y CONFIG_MEDIA_TUNER_XC5000=y +# end of Customize TV tuners # -# DVB Frontend drivers auto-selected by 'Autoselect ancillary drivers' +# Customise DVB Frontends # # @@ -5274,6 +5413,8 @@ CONFIG_MEDIA_TUNER_XC5000=y # CONFIG_DVB_M88DS3103=m CONFIG_DVB_MXL5XX=m +# CONFIG_DVB_STB0899 is not set +# CONFIG_DVB_STB6100 is not set CONFIG_DVB_STV090x=m CONFIG_DVB_STV0910=m CONFIG_DVB_STV6110x=m @@ -5291,21 +5432,31 @@ CONFIG_DVB_TDA18271C2DD=m # # DVB-S (satellite) frontends # +# CONFIG_DVB_CX24110 is not set CONFIG_DVB_CX24116=m +# CONFIG_DVB_CX24117 is not set CONFIG_DVB_CX24120=m CONFIG_DVB_CX24123=m +# CONFIG_DVB_DS3000 is not set +# CONFIG_DVB_MB86A16 is not set CONFIG_DVB_MT312=m CONFIG_DVB_S5H1420=m +# CONFIG_DVB_SI21XX is not set +# CONFIG_DVB_STB6000 is not set +# CONFIG_DVB_STV0288 is not set CONFIG_DVB_STV0299=m CONFIG_DVB_STV0900=m CONFIG_DVB_STV6110=m CONFIG_DVB_TDA10071=m CONFIG_DVB_TDA10086=m CONFIG_DVB_TDA8083=m +# CONFIG_DVB_TDA8261 is not set CONFIG_DVB_TDA826X=m CONFIG_DVB_TS2020=m +# CONFIG_DVB_TUA6100 is not set CONFIG_DVB_TUNER_CX24113=m CONFIG_DVB_TUNER_ITD1000=m +# CONFIG_DVB_VES1X93 is not set CONFIG_DVB_ZL10036=m CONFIG_DVB_ZL10039=m @@ -5315,25 +5466,37 @@ CONFIG_DVB_ZL10039=m CONFIG_DVB_AF9013=m CONFIG_DVB_AS102_FE=m CONFIG_DVB_CX22700=m +# CONFIG_DVB_CX22702 is not set CONFIG_DVB_CXD2820R=m CONFIG_DVB_CXD2841ER=m +# CONFIG_DVB_DIB3000MB is not set +# CONFIG_DVB_DIB3000MC is not set +# CONFIG_DVB_DIB7000M is not set +# CONFIG_DVB_DIB7000P is not set +# CONFIG_DVB_DIB9000 is not set CONFIG_DVB_DRXD=m CONFIG_DVB_EC100=m +# CONFIG_DVB_L64781 is not set CONFIG_DVB_MT352=m +# CONFIG_DVB_NXT6000 is not set CONFIG_DVB_RTL2830=m CONFIG_DVB_RTL2832=m CONFIG_DVB_RTL2832_SDR=m +# CONFIG_DVB_S5H1432 is not set CONFIG_DVB_SI2168=m +# CONFIG_DVB_SP887X is not set CONFIG_DVB_STV0367=m CONFIG_DVB_TDA10048=m CONFIG_DVB_TDA1004X=m CONFIG_DVB_ZD1301_DEMOD=m CONFIG_DVB_ZL10353=m +# CONFIG_DVB_CXD2880 is not set # # DVB-C (cable) frontends # CONFIG_DVB_STV0297=m +# CONFIG_DVB_TDA10021 is not set CONFIG_DVB_TDA10023=m CONFIG_DVB_VES1820=m @@ -5350,24 +5513,30 @@ CONFIG_DVB_LGDT3306A=m CONFIG_DVB_LGDT330X=m CONFIG_DVB_MXL692=m CONFIG_DVB_NXT200X=m +# CONFIG_DVB_OR51132 is not set +# CONFIG_DVB_OR51211 is not set CONFIG_DVB_S5H1409=m CONFIG_DVB_S5H1411=m # # ISDB-T (terrestrial) frontends # +# CONFIG_DVB_DIB8000 is not set CONFIG_DVB_MB86A20S=m CONFIG_DVB_S921=m # # ISDB-S (satellite) & ISDB-T (terrestrial) frontends # +# CONFIG_DVB_MN88443X is not set CONFIG_DVB_TC90522=m # # Digital terrestrial only tuners/PLL # CONFIG_DVB_PLL=m +# CONFIG_DVB_TUNER_DIB0070 is not set +# CONFIG_DVB_TUNER_DIB0090 is not set # # SEC control devices for DVB-S @@ -5375,13 +5544,21 @@ CONFIG_DVB_PLL=m CONFIG_DVB_A8293=m CONFIG_DVB_AF9033=m CONFIG_DVB_ASCOT2E=m +# CONFIG_DVB_ATBM8830 is not set CONFIG_DVB_HELENE=m CONFIG_DVB_HORUS3A=m CONFIG_DVB_ISL6405=m CONFIG_DVB_ISL6421=m CONFIG_DVB_ISL6423=m +# CONFIG_DVB_IX2505V is not set +# CONFIG_DVB_LGS8GL5 is not set +# CONFIG_DVB_LGS8GXX is not set CONFIG_DVB_LNBH25=m +# CONFIG_DVB_LNBH29 is not set CONFIG_DVB_LNBP21=m +# CONFIG_DVB_LNBP22 is not set +# CONFIG_DVB_M88RS2000 is not set +# CONFIG_DVB_TDA665x is not set CONFIG_DVB_DRX39XYJ=m # @@ -5389,6 +5566,7 @@ CONFIG_DVB_DRX39XYJ=m # CONFIG_DVB_CXD2099=m CONFIG_DVB_SP2=m +# end of Customise DVB Frontends # # Tools to develop new frontends @@ -5406,8 +5584,11 @@ CONFIG_DRM_EDID=y CONFIG_DRM_MIPI_DSI=y # CONFIG_DRM_DEBUG_MM is not set CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set +# CONFIG_DRM_DEBUG_MODESET_LOCK is not set CONFIG_DRM_FBDEV_EMULATION=y CONFIG_DRM_FBDEV_OVERALLOC=100 +# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set CONFIG_DRM_LOAD_EDID_FIRMWARE=y CONFIG_DRM_DP=y CONFIG_DRM_DP_AUX_BUS=m @@ -6566,6 +6747,7 @@ CONFIG_USB_PHY=y # end of USB Physical Layer drivers CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set CONFIG_USB_GADGET_DEBUG_FILES=y # CONFIG_USB_GADGET_DEBUG_FS is not set CONFIG_USB_GADGET_VBUS_DRAW=500 @@ -7967,6 +8149,7 @@ CONFIG_IIO_SYSFS_TRIGGER=y # CONFIG_NTB is not set CONFIG_PWM=y CONFIG_PWM_SYSFS=y +# CONFIG_PWM_DEBUG is not set # CONFIG_PWM_ATMEL_TCB is not set # CONFIG_PWM_CLK is not set # CONFIG_PWM_DWC is not set @@ -7996,6 +8179,7 @@ CONFIG_PARTITION_PERCPU=y CONFIG_ARCH_HAS_RESET_CONTROLLER=y CONFIG_RESET_CONTROLLER=y CONFIG_RESET_SCMI=y +# CONFIG_RESET_SIMPLE is not set # CONFIG_RESET_TI_SYSCON is not set # CONFIG_RESET_TI_TPS380X is not set @@ -8982,25 +9166,35 @@ CONFIG_PRINTK_TIME_FROM_ARM_ARCH_TIMER=y CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 CONFIG_CONSOLE_LOGLEVEL_QUIET=4 CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set CONFIG_DYNAMIC_DEBUG=y CONFIG_DYNAMIC_DEBUG_CORE=y CONFIG_SYMBOLIC_ERRNAME=y CONFIG_DEBUG_BUGVERBOSE=y # end of printk and dmesg options -# CONFIG_DEBUG_KERNEL is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_MISC=y # # Compile-time checks and compiler options # CONFIG_AS_HAS_NON_CONST_LEB128=y +CONFIG_DEBUG_INFO_NONE=y +# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_DEBUG_INFO_DWARF5 is not set CONFIG_FRAME_WARN=2048 # CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set # CONFIG_HEADERS_INSTALL is not set # CONFIG_DEBUG_SECTION_MISMATCH is not set CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set CONFIG_ARCH_WANT_FRAME_POINTERS=y CONFIG_FRAME_POINTER=y +# CONFIG_VMLINUX_MAP is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # end of Compile-time checks and compiler options # @@ -9015,34 +9209,51 @@ CONFIG_DEBUG_FS_ALLOW_ALL=y # CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set # CONFIG_DEBUG_FS_ALLOW_NONE is not set CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y # CONFIG_UBSAN is not set +CONFIG_HAVE_ARCH_KCSAN=y CONFIG_HAVE_KCSAN_COMPILER=y +# CONFIG_KCSAN is not set # end of Generic Kernel Debugging Instruments # # Networking Debugging # +# CONFIG_NET_DEV_REFCNT_TRACKER is not set +# CONFIG_NET_NS_REFCNT_TRACKER is not set +# CONFIG_DEBUG_NET is not set # end of Networking Debugging # # Memory Debugging # # CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set CONFIG_SLUB_DEBUG=y # CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_PAGE_OWNER is not set # CONFIG_PAGE_TABLE_CHECK is not set # CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_PAGE_REF is not set # CONFIG_DEBUG_RODATA_TEST is not set CONFIG_ARCH_HAS_DEBUG_WX=y # CONFIG_DEBUG_WX is not set CONFIG_GENERIC_PTDUMP=y +# CONFIG_PTDUMP_DEBUGFS is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_SHRINKER_DEBUG is not set CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_SCHED_STACK_END_CHECK is not set CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y +# CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_VM_PGTABLE is not set CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +# CONFIG_DEBUG_VIRTUAL is not set CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_HAVE_ARCH_KASAN=y CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y CONFIG_HAVE_ARCH_KASAN_HW_TAGS=y @@ -9055,20 +9266,28 @@ CONFIG_HAVE_ARCH_KFENCE=y # CONFIG_KFENCE is not set # end of Memory Debugging +# CONFIG_DEBUG_SHIRQ is not set + # # Debug Oops, Lockups and Hangs # # CONFIG_PANIC_ON_OOPS is not set CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SOFTLOCKUP_DETECTOR is not set CONFIG_HAVE_HARDLOCKUP_DETECTOR_OTHER_CPU=y +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set # CONFIG_TEST_LOCKUP is not set # end of Debug Oops, Lockups and Hangs # # Scheduler Debugging # +CONFIG_SCHED_DEBUG=y CONFIG_SCHED_INFO=y +# CONFIG_SCHEDSTATS is not set # end of Scheduler Debugging # CONFIG_DEBUG_TIMEKEEPING is not set @@ -9077,28 +9296,57 @@ CONFIG_SCHED_INFO=y # Lock Debugging (spinlocks, mutexes, etc...) # CONFIG_LOCK_DEBUGGING_SUPPORT=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set # CONFIG_WW_MUTEX_SELFTEST is not set +# CONFIG_SCF_TORTURE_TEST is not set +# CONFIG_CSD_LOCK_WAIT_DEBUG is not set # end of Lock Debugging (spinlocks, mutexes, etc...) # CONFIG_DEBUG_IRQFLAGS is not set CONFIG_STACKTRACE=y # CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +# CONFIG_DEBUG_KOBJECT is not set # # Debug kernel data structures # +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PLIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_DEBUG_MAPLE_TREE is not set # end of Debug kernel data structures +# CONFIG_DEBUG_CREDENTIALS is not set + # # RCU Debugging # +# CONFIG_RCU_SCALE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_REF_SCALE_TEST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_BOOTPARAM_RCU_STALL_PANIC is not set CONFIG_BOOTPARAM_RCU_STALL_PANIC_VALUE=0 CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0 +CONFIG_RCU_TRACE=y +# CONFIG_RCU_EQS_DEBUG is not set # end of RCU Debugging +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +# CONFIG_LATENCYTOP is not set CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y @@ -9167,13 +9415,20 @@ CONFIG_STRICT_DEVMEM=y # Kernel Testing and Coverage # # CONFIG_KUNIT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set CONFIG_ARCH_HAS_KCOV=y CONFIG_CC_HAS_SANCOV_TRACE_PC=y CONFIG_RUNTIME_TESTING_MENU=y CONFIG_LKDTM=y # CONFIG_TEST_MIN_HEAP is not set # CONFIG_TEST_DIV64 is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_TEST_REF_TRACKER is not set +# CONFIG_RBTREE_TEST is not set # CONFIG_REED_SOLOMON_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set # CONFIG_ATOMIC64_SELFTEST is not set # CONFIG_ASYNC_RAID6_TEST is not set # CONFIG_TEST_HEXDUMP is not set From d7064703168840f8817df56789b4a455c61019b1 Mon Sep 17 00:00:00 2001 From: Alessandro Lannocca Date: Sun, 9 Jun 2024 11:24:49 +0200 Subject: [PATCH 07/53] linux-rockchip-rk3588-edge.config minor touches: - move CONFIG_INPUT_RK805_PWRKEY and CONFIG_PINCTRL_RK805 to modules - move CONFIG_BT to module --- .../kernel/linux-rockchip-rk3588-edge.config | 217 ++++++++++++++++-- 1 file changed, 204 insertions(+), 13 deletions(-) diff --git a/config/kernel/linux-rockchip-rk3588-edge.config b/config/kernel/linux-rockchip-rk3588-edge.config index 6ffc0b42d281..6e4aac52f13b 100644 --- a/config/kernel/linux-rockchip-rk3588-edge.config +++ b/config/kernel/linux-rockchip-rk3588-edge.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 6.8.9 Kernel Configuration +# Linux/arm64 6.8.12 Kernel Configuration # CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0" CONFIG_CC_IS_GCC=y @@ -196,6 +196,7 @@ CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_PERF=y CONFIG_CGROUP_BPF=y CONFIG_CGROUP_MISC=y +# CONFIG_CGROUP_DEBUG is not set CONFIG_SOCK_CGROUP_DATA=y CONFIG_NAMESPACES=y CONFIG_UTS_NS=y @@ -227,9 +228,10 @@ CONFIG_LD_ORPHAN_WARN_LEVEL="warn" CONFIG_SYSCTL=y CONFIG_HAVE_UID16=y CONFIG_SYSCTL_EXCEPTION_TRACE=y -# CONFIG_EXPERT is not set +CONFIG_EXPERT=y CONFIG_UID16=y CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set CONFIG_SYSFS_SYSCALL=y CONFIG_FHANDLE=y CONFIG_POSIX_TIMERS=y @@ -250,9 +252,12 @@ CONFIG_ADVISE_SYSCALLS=y CONFIG_MEMBARRIER=y CONFIG_KCMP=y CONFIG_RSEQ=y +# CONFIG_DEBUG_RSEQ is not set CONFIG_CACHESTAT_SYSCALL=y +# CONFIG_PC104 is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_SELFTEST is not set +# CONFIG_KALLSYMS_ALL is not set CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y CONFIG_HAVE_PERF_EVENTS=y @@ -262,6 +267,7 @@ CONFIG_GUEST_PERF_EVENTS=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set # end of Kernel Performance Events And Counters CONFIG_SYSTEM_DATA_VERIFICATION=y @@ -545,6 +551,7 @@ CONFIG_DMI=y # CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set CONFIG_HIBERNATE_CALLBACKS=y CONFIG_HIBERNATION=y CONFIG_HIBERNATION_SNAPSHOT_DEV=y @@ -839,6 +846,7 @@ CONFIG_MODULE_COMPRESS_NONE=y # CONFIG_MODULE_COMPRESS_ZSTD is not set # CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set CONFIG_MODPROBE_PATH="/sbin/modprobe" +# CONFIG_TRIM_UNUSED_KSYMS is not set CONFIG_MODULES_TREE_LOOKUP=y CONFIG_BLOCK=y CONFIG_BLOCK_LEGACY_AUTOLOAD=y @@ -968,6 +976,7 @@ CONFIG_ZSMALLOC_CHAIN_SIZE=8 # Slab allocator options # CONFIG_SLUB=y +# CONFIG_SLUB_TINY is not set CONFIG_SLAB_MERGE_DEFAULT=y CONFIG_SLAB_FREELIST_RANDOM=y # CONFIG_SLAB_FREELIST_HARDENED is not set @@ -1008,6 +1017,7 @@ CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y CONFIG_MEMORY_FAILURE=y +# CONFIG_HWPOISON_INJECT is not set CONFIG_ARCH_WANTS_THP_SWAP=y CONFIG_TRANSPARENT_HUGEPAGE=y # CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS is not set @@ -1020,6 +1030,7 @@ CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y CONFIG_USE_PERCPU_NUMA_NODE_ID=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set # CONFIG_CMA_DEBUGFS is not set # CONFIG_CMA_SYSFS is not set CONFIG_CMA_AREAS=7 @@ -1030,6 +1041,7 @@ CONFIG_IDLE_PAGE_TRACKING=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CURRENT_STACK_POINTER=y CONFIG_ARCH_HAS_PTE_DEVMAP=y +CONFIG_ARCH_HAS_ZONE_DMA_SET=y CONFIG_ZONE_DMA=y CONFIG_ZONE_DMA32=y CONFIG_GET_FREE_REGION=y @@ -1564,6 +1576,12 @@ CONFIG_IP_DCCP_CCID3=y CONFIG_IP_DCCP_TFRC_LIB=y # end of DCCP CCIDs Configuration +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set +# end of DCCP Kernel Hacking + CONFIG_IP_SCTP=m CONFIG_SCTP_DBG_OBJCNT=y CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y @@ -1842,6 +1860,7 @@ CONFIG_BT_LEDS=y # CONFIG_BT_MSFTEXT is not set CONFIG_BT_AOSPEXT=y # CONFIG_BT_DEBUGFS is not set +# CONFIG_BT_SELFTEST is not set # # Bluetooth device drivers @@ -1907,6 +1926,7 @@ CONFIG_WEXT_PRIV=y CONFIG_CFG80211=m # CONFIG_NL80211_TESTMODE is not set # CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y CONFIG_CFG80211_DEFAULT_PS=y @@ -2032,6 +2052,7 @@ CONFIG_PCIE_PME=y # CONFIG_PCIE_PTM is not set CONFIG_PCI_MSI=y CONFIG_PCI_QUIRKS=y +# CONFIG_PCI_DEBUG is not set # CONFIG_PCI_REALLOC_ENABLE_AUTO is not set CONFIG_PCI_STUB=y # CONFIG_PCI_PF_STUB is not set @@ -2043,6 +2064,11 @@ CONFIG_PCI_PRI=y CONFIG_PCI_PASID=y CONFIG_PCI_LABEL=y # CONFIG_PCI_DYNAMIC_OF_NODES is not set +# CONFIG_PCIE_BUS_TUNE_OFF is not set +CONFIG_PCIE_BUS_DEFAULT=y +# CONFIG_PCIE_BUS_SAFE is not set +# CONFIG_PCIE_BUS_PERFORMANCE is not set +# CONFIG_PCIE_BUS_PEER2PEER is not set CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 CONFIG_HOTPLUG_PCI=y @@ -2157,6 +2183,9 @@ CONFIG_FW_UPLOAD=y CONFIG_WANT_DEV_COREDUMP=y CONFIG_ALLOW_DEV_COREDUMP=y CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set CONFIG_HMEM_REPORTING=y # CONFIG_TEST_ASYNC_DRIVER_PROBE is not set # CONFIG_DM_KUNIT_TEST is not set @@ -2230,6 +2259,7 @@ CONFIG_ARM_SCMI_POWER_CONTROL=m CONFIG_ARM_SCPI_PROTOCOL=y CONFIG_ARM_SDE_INTERFACE=y +# CONFIG_FIRMWARE_MEMMAP is not set CONFIG_DMIID=y CONFIG_DMI_SYSFS=y CONFIG_ISCSI_IBFT=y @@ -3852,7 +3882,6 @@ CONFIG_WLCORE_SDIO=m # CONFIG_RTL8821CU is not set # CONFIG_88XXAU is not set # CONFIG_RTL8192EU is not set -# CONFIG_RTL8189FS is not set # CONFIG_RTL8189ES is not set CONFIG_WLAN_VENDOR_ZYDAS=y CONFIG_ZD1211RW=m @@ -4310,6 +4339,7 @@ CONFIG_HVC_XEN_FRONTEND=y CONFIG_RPMSG_TTY=m CONFIG_SERIAL_DEV_BUS=y CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +# CONFIG_TTY_PRINTK is not set CONFIG_VIRTIO_CONSOLE=y CONFIG_IPMI_HANDLER=m CONFIG_IPMI_DMI_DECODE=y @@ -4472,6 +4502,7 @@ CONFIG_DW_I3C_MASTER=m CONFIG_SVC_I3C_MASTER=m CONFIG_MIPI_I3C_HCI=m CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set CONFIG_SPI_MASTER=y CONFIG_SPI_MEM=y @@ -4564,6 +4595,7 @@ CONFIG_PINMUX=y CONFIG_GENERIC_PINMUX_FUNCTIONS=y CONFIG_PINCONF=y CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set # CONFIG_PINCTRL_AMD is not set CONFIG_PINCTRL_CY8C95X0=m # CONFIG_PINCTRL_MCP23S08 is not set @@ -4586,6 +4618,8 @@ CONFIG_OF_GPIO=y CONFIG_GPIO_ACPI=y CONFIG_GPIOLIB_IRQCHIP=y CONFIG_OF_GPIO_MM_GPIOCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y CONFIG_GPIO_CDEV=y CONFIG_GPIO_CDEV_V1=y CONFIG_GPIO_GENERIC=y @@ -5852,8 +5886,6 @@ CONFIG_VIDEOBUF2_DMA_SG=m CONFIG_VIDEOBUF2_DVB=m # end of Media drivers -CONFIG_MEDIA_HIDE_ANCILLARY_SUBDRV=y - # # Media ancillary drivers # @@ -5966,39 +5998,108 @@ CONFIG_VIDEO_LM3646=m # end of Flash devices # -# audio, video and radio I2C drivers auto-selected by 'Autoselect ancillary drivers' +# Audio decoders, processors and mixers # CONFIG_VIDEO_CS3308=m CONFIG_VIDEO_CS5345=m CONFIG_VIDEO_CS53L32A=m CONFIG_VIDEO_MSP3400=m CONFIG_VIDEO_SONY_BTF_MPX=m +# CONFIG_VIDEO_TDA1997X is not set CONFIG_VIDEO_TDA7432=m CONFIG_VIDEO_TDA9840=m CONFIG_VIDEO_TEA6415C=m CONFIG_VIDEO_TEA6420=m +# CONFIG_VIDEO_TLV320AIC23B is not set CONFIG_VIDEO_TVAUDIO=m CONFIG_VIDEO_UDA1342=m CONFIG_VIDEO_VP27SMPX=m CONFIG_VIDEO_WM8739=m CONFIG_VIDEO_WM8775=m +# end of Audio decoders, processors and mixers + +# +# RDS decoders +# CONFIG_VIDEO_SAA6588=m +# end of RDS decoders + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7183 is not set +# CONFIG_VIDEO_ADV748X is not set +# CONFIG_VIDEO_ADV7604 is not set +# CONFIG_VIDEO_ADV7842 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_ISL7998X is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_MAX9286 is not set +# CONFIG_VIDEO_ML86V7667 is not set +# CONFIG_VIDEO_SAA7110 is not set CONFIG_VIDEO_SAA711X=m +# CONFIG_VIDEO_TC358743 is not set +# CONFIG_VIDEO_TC358746 is not set +# CONFIG_VIDEO_TVP514X is not set CONFIG_VIDEO_TVP5150=m +# CONFIG_VIDEO_TVP7002 is not set CONFIG_VIDEO_TW2804=m +# CONFIG_VIDEO_TW9900 is not set CONFIG_VIDEO_TW9903=m CONFIG_VIDEO_TW9906=m +# CONFIG_VIDEO_TW9910 is not set +# CONFIG_VIDEO_VPX3220 is not set # # Video and audio decoders # CONFIG_VIDEO_SAA717X=m CONFIG_VIDEO_CX25840=m +# end of Video decoders + +# +# Video encoders +# +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_ADV7393 is not set +# CONFIG_VIDEO_AK881X is not set CONFIG_VIDEO_SAA7127=m +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_THS8200 is not set +# end of Video encoders + +# +# Video improvement chips +# CONFIG_VIDEO_UPD64031A=m CONFIG_VIDEO_UPD64083=m +# end of Video improvement chips + +# +# Audio/Video compression chips +# CONFIG_VIDEO_SAA6752HS=m +# end of Audio/Video compression chips + +# +# SDR tuner chips +# +# CONFIG_SDR_MAX2175 is not set +# end of SDR tuner chips + +# +# Miscellaneous helper chips +# +# CONFIG_VIDEO_I2C is not set CONFIG_VIDEO_M52790=m +# CONFIG_VIDEO_ST_MIPID02 is not set +# CONFIG_VIDEO_THS7303 is not set +# end of Miscellaneous helper chips # # Video serializers and deserializers @@ -6008,10 +6109,6 @@ CONFIG_VIDEO_M52790=m # CONFIG_VIDEO_DS90UB960 is not set # end of Video serializers and deserializers -# -# SPI I2C drivers auto-selected by 'Autoselect ancillary drivers' -# - # # Media SPI Adapters # @@ -6022,7 +6119,7 @@ CONFIG_VIDEO_GS1662=m CONFIG_MEDIA_TUNER=m # -# Tuner drivers auto-selected by 'Autoselect ancillary drivers' +# Customize TV tuners # CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC0011=m @@ -6061,9 +6158,10 @@ CONFIG_MEDIA_TUNER_TUA9001=m CONFIG_MEDIA_TUNER_XC2028=m CONFIG_MEDIA_TUNER_XC4000=m CONFIG_MEDIA_TUNER_XC5000=m +# end of Customize TV tuners # -# DVB Frontend drivers auto-selected by 'Autoselect ancillary drivers' +# Customise DVB Frontends # # @@ -6131,6 +6229,7 @@ CONFIG_DVB_DIB3000MB=m CONFIG_DVB_DIB3000MC=m CONFIG_DVB_DIB7000M=m CONFIG_DVB_DIB7000P=m +# CONFIG_DVB_DIB9000 is not set CONFIG_DVB_DRXD=m CONFIG_DVB_EC100=m CONFIG_DVB_GP8PSK_FE=m @@ -6140,6 +6239,7 @@ CONFIG_DVB_NXT6000=m CONFIG_DVB_RTL2830=m CONFIG_DVB_RTL2832=m CONFIG_DVB_RTL2832_SDR=m +# CONFIG_DVB_S5H1432 is not set CONFIG_DVB_SI2168=m CONFIG_DVB_SP887X=m CONFIG_DVB_STV0367=m @@ -6147,6 +6247,7 @@ CONFIG_DVB_TDA10048=m CONFIG_DVB_TDA1004X=m CONFIG_DVB_ZD1301_DEMOD=m CONFIG_DVB_ZL10353=m +# CONFIG_DVB_CXD2880 is not set # # DVB-C (cable) frontends @@ -6184,6 +6285,7 @@ CONFIG_DVB_S921=m # # ISDB-S (satellite) & ISDB-T (terrestrial) frontends # +# CONFIG_DVB_MN88443X is not set CONFIG_DVB_TC90522=m # @@ -6198,13 +6300,18 @@ CONFIG_DVB_TUNER_DIB0090=m # CONFIG_DVB_A8293=m CONFIG_DVB_AF9033=m +# CONFIG_DVB_ASCOT2E is not set CONFIG_DVB_ATBM8830=m +# CONFIG_DVB_HELENE is not set +# CONFIG_DVB_HORUS3A is not set CONFIG_DVB_ISL6405=m CONFIG_DVB_ISL6421=m CONFIG_DVB_ISL6423=m CONFIG_DVB_IX2505V=m +# CONFIG_DVB_LGS8GL5 is not set CONFIG_DVB_LGS8GXX=m CONFIG_DVB_LNBH25=m +# CONFIG_DVB_LNBH29 is not set CONFIG_DVB_LNBP21=m CONFIG_DVB_LNBP22=m CONFIG_DVB_M88RS2000=m @@ -6216,6 +6323,7 @@ CONFIG_DVB_DRX39XYJ=m # CONFIG_DVB_CXD2099=m CONFIG_DVB_SP2=m +# end of Customise DVB Frontends # # Tools to develop new frontends @@ -6236,8 +6344,11 @@ CONFIG_DRM_MIPI_DSI=y CONFIG_DRM_KUNIT_TEST_HELPERS=m CONFIG_DRM_KUNIT_TEST=m CONFIG_DRM_KMS_HELPER=m +# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set +# CONFIG_DRM_DEBUG_MODESET_LOCK is not set CONFIG_DRM_FBDEV_EMULATION=y CONFIG_DRM_FBDEV_OVERALLOC=100 +# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set CONFIG_DRM_LOAD_EDID_FIRMWARE=y CONFIG_DRM_DP_AUX_BUS=m CONFIG_DRM_DISPLAY_HELPER=m @@ -7030,6 +7141,7 @@ CONFIG_SND_SOC_RT715_SDW=m CONFIG_SND_SOC_RT715_SDCA_SDW=m # CONFIG_SND_SOC_RT9120 is not set # CONFIG_SND_SOC_RTQ9128 is not set +# CONFIG_SND_SOC_SDW_MOCKUP is not set CONFIG_SND_SOC_SGTL5000=m CONFIG_SND_SOC_SIGMADSP=m CONFIG_SND_SOC_SIGMADSP_I2C=m @@ -7578,6 +7690,7 @@ CONFIG_USB_ULPI_VIEWPORT=y # end of USB Physical Layer drivers CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set # CONFIG_USB_GADGET_DEBUG_FS is not set CONFIG_USB_GADGET_VBUS_DRAW=2 @@ -9216,6 +9329,7 @@ CONFIG_MAX31865=m # CONFIG_NTB is not set CONFIG_PWM=y CONFIG_PWM_SYSFS=y +# CONFIG_PWM_DEBUG is not set CONFIG_PWM_ATMEL_TCB=m CONFIG_PWM_CLK=m CONFIG_PWM_CROS_EC=m @@ -9246,6 +9360,7 @@ CONFIG_PARTITION_PERCPU=y CONFIG_ARCH_HAS_RESET_CONTROLLER=y CONFIG_RESET_CONTROLLER=y CONFIG_RESET_SCMI=y +# CONFIG_RESET_SIMPLE is not set # CONFIG_RESET_TI_SYSCON is not set CONFIG_RESET_TI_TPS380X=m @@ -9962,6 +10077,7 @@ CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_ALGAPI2=y CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_SIG=y CONFIG_CRYPTO_SIG2=y CONFIG_CRYPTO_SKCIPHER=y CONFIG_CRYPTO_SKCIPHER2=y @@ -10368,6 +10484,7 @@ CONFIG_CMA_ALIGNMENT=8 # CONFIG_DMA_MAP_BENCHMARK is not set CONFIG_SGL_ALLOC=y CONFIG_CHECK_SIGNATURE=y +# CONFIG_FORCE_NR_CPUS is not set CONFIG_CPU_RMAP=y CONFIG_DQL=y CONFIG_GLOB=y @@ -10429,25 +10546,35 @@ CONFIG_PRINTK_TIME=y CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 CONFIG_CONSOLE_LOGLEVEL_QUIET=4 CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set CONFIG_DYNAMIC_DEBUG=y CONFIG_DYNAMIC_DEBUG_CORE=y CONFIG_SYMBOLIC_ERRNAME=y CONFIG_DEBUG_BUGVERBOSE=y # end of printk and dmesg options -# CONFIG_DEBUG_KERNEL is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_MISC=y # # Compile-time checks and compiler options # CONFIG_AS_HAS_NON_CONST_ULEB128=y +CONFIG_DEBUG_INFO_NONE=y +# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_DEBUG_INFO_DWARF5 is not set CONFIG_FRAME_WARN=2048 # CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set # CONFIG_HEADERS_INSTALL is not set # CONFIG_DEBUG_SECTION_MISMATCH is not set CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set CONFIG_ARCH_WANT_FRAME_POINTERS=y CONFIG_FRAME_POINTER=y +# CONFIG_VMLINUX_MAP is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # end of Compile-time checks and compiler options # @@ -10462,35 +10589,52 @@ CONFIG_DEBUG_FS_ALLOW_ALL=y # CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set # CONFIG_DEBUG_FS_ALLOW_NONE is not set CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y # CONFIG_UBSAN is not set +CONFIG_HAVE_ARCH_KCSAN=y CONFIG_HAVE_KCSAN_COMPILER=y +# CONFIG_KCSAN is not set # end of Generic Kernel Debugging Instruments # # Networking Debugging # +# CONFIG_NET_DEV_REFCNT_TRACKER is not set +# CONFIG_NET_NS_REFCNT_TRACKER is not set +# CONFIG_DEBUG_NET is not set # end of Networking Debugging # # Memory Debugging # # CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set CONFIG_SLUB_DEBUG=y # CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_PAGE_OWNER is not set # CONFIG_PAGE_TABLE_CHECK is not set # CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_PAGE_REF is not set # CONFIG_DEBUG_RODATA_TEST is not set CONFIG_ARCH_HAS_DEBUG_WX=y # CONFIG_DEBUG_WX is not set CONFIG_GENERIC_PTDUMP=y +# CONFIG_PTDUMP_DEBUGFS is not set CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_PER_VMA_LOCK_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set # CONFIG_SHRINKER_DEBUG is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_SCHED_STACK_END_CHECK is not set CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y +# CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_VM_PGTABLE is not set CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +# CONFIG_DEBUG_VIRTUAL is not set CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set CONFIG_HAVE_ARCH_KASAN=y CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y CONFIG_HAVE_ARCH_KASAN_HW_TAGS=y @@ -10503,49 +10647,87 @@ CONFIG_HAVE_ARCH_KFENCE=y # CONFIG_KFENCE is not set # end of Memory Debugging +# CONFIG_DEBUG_SHIRQ is not set + # # Debug Oops, Lockups and Hangs # # CONFIG_PANIC_ON_OOPS is not set CONFIG_PANIC_ON_OOPS_VALUE=0 CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SOFTLOCKUP_DETECTOR is not set CONFIG_HAVE_HARDLOCKUP_DETECTOR_BUDDY=y +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set +# CONFIG_WQ_CPU_INTENSIVE_REPORT is not set CONFIG_TEST_LOCKUP=m # end of Debug Oops, Lockups and Hangs # # Scheduler Debugging # +CONFIG_SCHED_DEBUG=y CONFIG_SCHED_INFO=y +# CONFIG_SCHEDSTATS is not set # end of Scheduler Debugging # CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_DEBUG_PREEMPT is not set # # Lock Debugging (spinlocks, mutexes, etc...) # CONFIG_LOCK_DEBUGGING_SUPPORT=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set # CONFIG_WW_MUTEX_SELFTEST is not set +# CONFIG_SCF_TORTURE_TEST is not set +# CONFIG_CSD_LOCK_WAIT_DEBUG is not set # end of Lock Debugging (spinlocks, mutexes, etc...) # CONFIG_DEBUG_IRQFLAGS is not set CONFIG_STACKTRACE=y # CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +# CONFIG_DEBUG_KOBJECT is not set # # Debug kernel data structures # +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PLIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_DEBUG_CLOSURES is not set +# CONFIG_DEBUG_MAPLE_TREE is not set # end of Debug kernel data structures # # RCU Debugging # +# CONFIG_RCU_SCALE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_REF_SCALE_TEST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=21 CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0 # CONFIG_RCU_CPU_STALL_CPUTIME is not set +CONFIG_RCU_TRACE=y +# CONFIG_RCU_EQS_DEBUG is not set # end of RCU Debugging +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_DEBUG_CGROUP_REF is not set CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y @@ -10618,7 +10800,9 @@ CONFIG_KUNIT=m # CONFIG_KUNIT_EXAMPLE_TEST is not set # CONFIG_KUNIT_ALL_TESTS is not set # CONFIG_KUNIT_DEFAULT_ENABLED is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set CONFIG_FUNCTION_ERROR_INJECTION=y +# CONFIG_FAULT_INJECTION is not set CONFIG_ARCH_HAS_KCOV=y CONFIG_CC_HAS_SANCOV_TRACE_PC=y CONFIG_RUNTIME_TESTING_MENU=y @@ -10630,7 +10814,13 @@ CONFIG_TEST_MIN_HEAP=m # CONFIG_TEST_SORT is not set CONFIG_TEST_DIV64=m # CONFIG_TEST_IOV_ITER is not set +# CONFIG_KPROBES_SANITY_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_TEST_REF_TRACKER is not set +# CONFIG_RBTREE_TEST is not set CONFIG_REED_SOLOMON_TEST=m +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set # CONFIG_ATOMIC64_SELFTEST is not set CONFIG_ASYNC_RAID6_TEST=m # CONFIG_TEST_HEXDUMP is not set @@ -10682,6 +10872,7 @@ CONFIG_MEMCPY_SLOW_KUNIT_TEST=y CONFIG_TEST_MEMCAT_P=m # CONFIG_TEST_MEMINIT is not set # CONFIG_TEST_FREE_PAGES is not set +# CONFIG_TEST_OBJPOOL is not set CONFIG_ARCH_USE_MEMTEST=y CONFIG_MEMTEST=y # end of Kernel Testing and Coverage From ec569900fd3300323e9e6671c710c5f4ff8709dd Mon Sep 17 00:00:00 2001 From: chainsx Date: Mon, 10 Jun 2024 15:15:44 +0800 Subject: [PATCH 08/53] sun55iiw3-syterkit: update kernel config --- .../linux-sun55iw3-syterkit-legacy.config | 66 +------------------ 1 file changed, 2 insertions(+), 64 deletions(-) diff --git a/config/kernel/linux-sun55iw3-syterkit-legacy.config b/config/kernel/linux-sun55iw3-syterkit-legacy.config index 3fd713326f29..2470f3e8e143 100644 --- a/config/kernel/linux-sun55iw3-syterkit-legacy.config +++ b/config/kernel/linux-sun55iw3-syterkit-legacy.config @@ -1689,7 +1689,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # # Avaota SBC Drivers # -CONFIG_AVA_FB_TFT=m +CONFIG_AVA_FB_TFT=y CONFIG_AVA_FB_TFT_ST7789V=m # end of Avaota SBC Drivers # end of Allwinner BSP @@ -3028,7 +3028,6 @@ CONFIG_WLAN_VENDOR_TI=y # CONFIG_RTL8821CU is not set # CONFIG_88XXAU is not set # CONFIG_RTL8192EU is not set -# CONFIG_RTL8189FS is not set # CONFIG_RTL8189ES is not set CONFIG_WLAN_VENDOR_ZYDAS=y # CONFIG_USB_ZD1201 is not set @@ -5691,68 +5690,7 @@ CONFIG_VHOST_CROSS_ENDIAN_LEGACY=y # CONFIG_GREYBUS is not set # CONFIG_COMEDI is not set -CONFIG_STAGING=y -# CONFIG_PRISM2_USB is not set -# CONFIG_RTL8192U is not set -# CONFIG_RTLLIB is not set -# CONFIG_RTL8723BS is not set -# CONFIG_R8712U is not set -# CONFIG_R8188EU is not set -# CONFIG_RTS5208 is not set -# CONFIG_VT6655 is not set -# CONFIG_VT6656 is not set -# CONFIG_FB_SM750 is not set -# CONFIG_STAGING_MEDIA is not set - -# -# Android -# -# end of Android - -# CONFIG_STAGING_BOARD is not set -# CONFIG_LTE_GDM724X is not set -# CONFIG_GS_FPGABOOT is not set -# CONFIG_UNISYSSPAR is not set -# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set -CONFIG_FB_TFT=y -# CONFIG_FB_TFT_AGM1264K_FL is not set -# CONFIG_FB_TFT_BD663474 is not set -# CONFIG_FB_TFT_HX8340BN is not set -# CONFIG_FB_TFT_HX8347D is not set -# CONFIG_FB_TFT_HX8353D is not set -# CONFIG_FB_TFT_HX8357D is not set -# CONFIG_FB_TFT_ILI9163 is not set -# CONFIG_FB_TFT_ILI9320 is not set -# CONFIG_FB_TFT_ILI9325 is not set -# CONFIG_FB_TFT_ILI9340 is not set -# CONFIG_FB_TFT_ILI9341 is not set -# CONFIG_FB_TFT_ILI9481 is not set -# CONFIG_FB_TFT_ILI9486 is not set -# CONFIG_FB_TFT_PCD8544 is not set -# CONFIG_FB_TFT_RA8875 is not set -# CONFIG_FB_TFT_S6D02A1 is not set -# CONFIG_FB_TFT_S6D1121 is not set -# CONFIG_FB_TFT_SEPS525 is not set -# CONFIG_FB_TFT_SH1106 is not set -# CONFIG_FB_TFT_SSD1289 is not set -# CONFIG_FB_TFT_SSD1305 is not set -# CONFIG_FB_TFT_SSD1306 is not set -# CONFIG_FB_TFT_SSD1331 is not set -# CONFIG_FB_TFT_SSD1351 is not set -# CONFIG_FB_TFT_ST7735R is not set -# CONFIG_FB_TFT_ST7789V is not set -# CONFIG_FB_TFT_TINYLCD is not set -# CONFIG_FB_TFT_TLS8204 is not set -# CONFIG_FB_TFT_UC1611 is not set -# CONFIG_FB_TFT_UC1701 is not set -# CONFIG_FB_TFT_UPD161704 is not set -# CONFIG_FB_TFT_WATTEROTT is not set -# CONFIG_KS7010 is not set -# CONFIG_PI433 is not set -# CONFIG_XIL_AXIS_FIFO is not set -# CONFIG_FIELDBUS_DEV is not set -# CONFIG_QLGE is not set -# CONFIG_WFX is not set +# CONFIG_STAGING is not set # CONFIG_GOLDFISH is not set # CONFIG_CHROME_PLATFORMS is not set # CONFIG_MELLANOX_PLATFORM is not set From 8eb8cc530295931f5857aef1ddafbca20afcd61b Mon Sep 17 00:00:00 2001 From: lanmarc77 Date: Tue, 11 Jun 2024 11:50:01 +0200 Subject: [PATCH 09/53] NanoPi Neo3 spidev support (#6689) * added spi device support for Nano Pi Neo3 with different address * adjusted Makefile for compilation for Nano Pi Neo3 spi-spidev --- .../archive/rockchip64-6.6/overlay/Makefile | 1 + .../overlay/rockchip-rk3328-spi-spidev.dts | 33 +++++++++++++++++++ .../archive/rockchip64-6.9/overlay/Makefile | 1 + .../overlay/rockchip-rk3328-spi-spidev.dts | 33 +++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 patch/kernel/archive/rockchip64-6.6/overlay/rockchip-rk3328-spi-spidev.dts create mode 100644 patch/kernel/archive/rockchip64-6.9/overlay/rockchip-rk3328-spi-spidev.dts diff --git a/patch/kernel/archive/rockchip64-6.6/overlay/Makefile b/patch/kernel/archive/rockchip64-6.6/overlay/Makefile index 18a0b45ee43b..413cbef21ce2 100644 --- a/patch/kernel/archive/rockchip64-6.6/overlay/Makefile +++ b/patch/kernel/archive/rockchip64-6.6/overlay/Makefile @@ -21,6 +21,7 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ rockchip-rk3328-i2s1-pcm5102.dtbo \ rockchip-rk3328-opp-1.4ghz.dtbo \ rockchip-rk3328-opp-1.5ghz.dtbo \ + rockchip-rk3328-spi-spidev.dtbo \ rockchip-rk3328-uart1.dtbo \ rockchip-rk3399-dwc3-0-host.dtbo \ rockchip-rk3399-i2c7.dtbo \ diff --git a/patch/kernel/archive/rockchip64-6.6/overlay/rockchip-rk3328-spi-spidev.dts b/patch/kernel/archive/rockchip64-6.6/overlay/rockchip-rk3328-spi-spidev.dts new file mode 100644 index 000000000000..9cc0238296de --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.6/overlay/rockchip-rk3328-spi-spidev.dts @@ -0,0 +1,33 @@ +/dts-v1/; + +/ { + compatible = "rockchip,rk3328"; + + fragment@0 { + target-path = "/aliases"; + + __overlay__ { + status = "okay"; + spi0 = "/spi@ff190000"; + }; + }; + + fragment@1 { + target = <0xffffffff>; + + __overlay__ { + status = "okay"; + + spidev { + compatible = "armbian,spi-dev"; + status = "okay"; + reg = <0x00>; + spi-max-frequency = <0x989680>; + }; + }; + }; + + __fixups__ { + spi0 = "/fragment@1:target:0"; + }; +}; diff --git a/patch/kernel/archive/rockchip64-6.9/overlay/Makefile b/patch/kernel/archive/rockchip64-6.9/overlay/Makefile index 0d2893349f50..be8b1f59e69f 100644 --- a/patch/kernel/archive/rockchip64-6.9/overlay/Makefile +++ b/patch/kernel/archive/rockchip64-6.9/overlay/Makefile @@ -21,6 +21,7 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ rockchip-rk3328-i2s1-pcm5102.dtbo \ rockchip-rk3328-opp-1.4ghz.dtbo \ rockchip-rk3328-opp-1.5ghz.dtbo \ + rockchip-rk3328-spi-spidev.dtbo \ rockchip-rk3328-uart1.dtbo \ rockchip-rk3399-dwc3-0-host.dtbo \ rockchip-rk3399-i2c7.dtbo \ diff --git a/patch/kernel/archive/rockchip64-6.9/overlay/rockchip-rk3328-spi-spidev.dts b/patch/kernel/archive/rockchip64-6.9/overlay/rockchip-rk3328-spi-spidev.dts new file mode 100644 index 000000000000..9cc0238296de --- /dev/null +++ b/patch/kernel/archive/rockchip64-6.9/overlay/rockchip-rk3328-spi-spidev.dts @@ -0,0 +1,33 @@ +/dts-v1/; + +/ { + compatible = "rockchip,rk3328"; + + fragment@0 { + target-path = "/aliases"; + + __overlay__ { + status = "okay"; + spi0 = "/spi@ff190000"; + }; + }; + + fragment@1 { + target = <0xffffffff>; + + __overlay__ { + status = "okay"; + + spidev { + compatible = "armbian,spi-dev"; + status = "okay"; + reg = <0x00>; + spi-max-frequency = <0x989680>; + }; + }; + }; + + __fixups__ { + spi0 = "/fragment@1:target:0"; + }; +}; From 3ef7d57bd6639785b6aa9c561c8b042d808ae042 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Tue, 11 Jun 2024 17:43:17 +0200 Subject: [PATCH 10/53] board: nanopi-r6s: Update DDR and BL31 blobs FriendlyElec ships their devices with the latest blobs. Trying to run an Armbian image on this board with the old blobs might cause issues. --- config/boards/nanopi-r6s.csc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/boards/nanopi-r6s.csc b/config/boards/nanopi-r6s.csc index a711bafc16d4..8823e09c467d 100644 --- a/config/boards/nanopi-r6s.csc +++ b/config/boards/nanopi-r6s.csc @@ -8,11 +8,11 @@ KERNEL_TARGET="legacy,vendor,edge" KERNEL_TEST_TARGET="vendor,edge" FULL_DESKTOP="yes" BOOT_LOGO="desktop" +IMAGE_PARTITION_TABLE="gpt" BOOT_FDT_FILE="rockchip/rk3588s-nanopi-r6s.dtb" BOOT_SCENARIO="spl-blobs" -IMAGE_PARTITION_TABLE="gpt" -DDR_BLOB='rk35/rk3588_ddr_lp4_2112MHz_lp5_2736MHz_v1.11.bin' -BL31_BLOB='rk35/rk3588_bl31_v1.38.elf' +DDR_BLOB='rk35/rk3588_ddr_lp4_2112MHz_lp5_2400MHz_v1.16.bin' +BL31_BLOB='rk35/rk3588_bl31_v1.45.elf' declare -g UEFI_EDK2_BOARD_ID="nanopi-r6s" # This _only_ used for uefi-edk2-rk3588 extension function post_family_tweaks__nanopir6s_naming_audios() { From 38c8bfcbf470eb0291082b3c93539809f997c511 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Tue, 11 Jun 2024 17:43:34 +0200 Subject: [PATCH 11/53] board:nanopi-r6s: Beautify board config --- config/boards/nanopi-r6s.csc | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/config/boards/nanopi-r6s.csc b/config/boards/nanopi-r6s.csc index 8823e09c467d..30098219be20 100644 --- a/config/boards/nanopi-r6s.csc +++ b/config/boards/nanopi-r6s.csc @@ -15,23 +15,22 @@ DDR_BLOB='rk35/rk3588_ddr_lp4_2112MHz_lp5_2400MHz_v1.16.bin' BL31_BLOB='rk35/rk3588_bl31_v1.45.elf' declare -g UEFI_EDK2_BOARD_ID="nanopi-r6s" # This _only_ used for uefi-edk2-rk3588 extension -function post_family_tweaks__nanopir6s_naming_audios() { - display_alert "$BOARD" "Renaming nanopir6s audio" "info" +function post_family_tweaks__nanopir6s_naming_udev_audios() { + display_alert "$BOARD" "Renaming NanoPi R6S HDMI audio" "info" mkdir -p $SDCARD/etc/udev/rules.d/ - echo 'SUBSYSTEM=="sound", ENV{ID_PATH}=="platform-hdmi0-sound", ENV{SOUND_DESCRIPTION}="HDMI0 Audio"' > $SDCARD/etc/udev/rules.d/90-naming-audios.rules - - return 0 + cat <<- EOF > $SDCARD/etc/udev/rules.d/90-naming-audios.rules + SUBSYSTEM=="sound", ENV{ID_PATH}=="platform-hdmi0-sound", ENV{SOUND_DESCRIPTION}="HDMI0 Audio"' + EOF } -function post_family_tweaks__nanopir6s_udev_network_interfaces() { - display_alert "$BOARD" "Renaming interfaces WAN LAN1 LAN2" "info" +function post_family_tweaks__nanopir6s_naming_udev_network_interfaces() { + display_alert "$BOARD" "Renaming NanoPi R6S network interfaces to WAN LAN1 LAN2" "info" mkdir -p $SDCARD/etc/udev/rules.d/ - cat << EOF > "${SDCARD}/etc/udev/rules.d/70-persistent-net.rules" -SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", KERNELS=="fe1c0000.ethernet", NAME:="wan" -SUBSYSTEM=="net", ACTION=="add", DRIVERS=="r8169", KERNELS=="0003:31:00.0", NAME:="lan1" -SUBSYSTEM=="net", ACTION=="add", DRIVERS=="r8169", KERNELS=="0004:41:00.0", NAME:="lan2" -EOF - + cat <<- EOF > "${SDCARD}/etc/udev/rules.d/70-persistent-net.rules" + SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", KERNELS=="fe1c0000.ethernet", NAME:="wan" + SUBSYSTEM=="net", ACTION=="add", DRIVERS=="r8169", KERNELS=="0003:31:00.0", NAME:="lan1" + SUBSYSTEM=="net", ACTION=="add", DRIVERS=="r8169", KERNELS=="0004:41:00.0", NAME:="lan2" + EOF } From 0cae55f37723fa20c453b82d8fb65f7b5ad9f775 Mon Sep 17 00:00:00 2001 From: Igor Pecovnik Date: Tue, 11 Jun 2024 20:02:45 +0200 Subject: [PATCH 12/53] Adjust Rockchip overlay to match changes introduced in 6.9.y --- ...chip-rk3328-spi-spidev.dts => rockchip-rk3328-spi-spidev.dtso} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename patch/kernel/archive/rockchip64-6.9/overlay/{rockchip-rk3328-spi-spidev.dts => rockchip-rk3328-spi-spidev.dtso} (100%) diff --git a/patch/kernel/archive/rockchip64-6.9/overlay/rockchip-rk3328-spi-spidev.dts b/patch/kernel/archive/rockchip64-6.9/overlay/rockchip-rk3328-spi-spidev.dtso similarity index 100% rename from patch/kernel/archive/rockchip64-6.9/overlay/rockchip-rk3328-spi-spidev.dts rename to patch/kernel/archive/rockchip64-6.9/overlay/rockchip-rk3328-spi-spidev.dtso From bfe636fc74ca22395d01e57007628c0c145eb964 Mon Sep 17 00:00:00 2001 From: Viacheslav Bocharov Date: Fri, 7 Jun 2024 15:58:36 +0300 Subject: [PATCH 13/53] families/meson64_common Add jethubj200 support --- config/sources/families/include/meson64_common.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/sources/families/include/meson64_common.inc b/config/sources/families/include/meson64_common.inc index 9928fe8341be..bb6a2c0cfd72 100644 --- a/config/sources/families/include/meson64_common.inc +++ b/config/sources/families/include/meson64_common.inc @@ -287,7 +287,7 @@ family_tweaks_bsp() { EndSection EOF ;; - "odroidn2" | "odroidc4" | "khadas-vim2" | "odroidhc4" | "khadas-vim3" | "khadas-vim3l" | "radxa-zero" | "radxa-zero2" | "bananapi-m2s") + "jethubj200" | "odroidn2" | "odroidc4" | "khadas-vim2" | "odroidhc4" | "khadas-vim3" | "khadas-vim3l" | "radxa-zero" | "radxa-zero2" | "bananapi-m2s") cat <<- EOF > "$destination"/etc/X11/xorg.conf Section "Device" Identifier "DRM Graphics Acclerated" From 946ed480e7e424187788a86e7756563e2c8e7a75 Mon Sep 17 00:00:00 2001 From: Viacheslav Bocharov Date: Fri, 7 Jun 2024 15:59:51 +0300 Subject: [PATCH 14/53] families/jethub add jethubj200 support --- config/sources/families/jethub.conf | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/config/sources/families/jethub.conf b/config/sources/families/jethub.conf index 51d8689a991d..f2e225261d43 100644 --- a/config/sources/families/jethub.conf +++ b/config/sources/families/jethub.conf @@ -27,8 +27,15 @@ if [[ "$BOARD" == "jethubj80" ]]; then elif [[ "$BOARD" == "jethubj100" ]]; then CPUMAX=1416000 OFFSET=126 +elif [[ "$BOARD" == "jethubj200" ]]; then + ASOUND_STATE="${ASOUND_STATE:-"asound.state.meson64"}" + CPUMIN=667000 + CPUMAX=2100000 + BOOTBRANCH="tag:v2024.01" + BOOTPATCHDIR="v2024.01" fi + ######## # @TODO: Put this in the board configs of the respective boards ######## @@ -49,11 +56,22 @@ fi # but having a core extension allows it to be pre-included in the Dockerfile generation and thus in the Docker images. enable_extension "c-plus-plus-compiler" + +function fetch_sources_tools__jethub_amlogic_fip() { + fetch_from_repo "https://github.com/adeepn/amlogic-boot-fip" "amlogic-boot-fip-jethub" "branch:add_jethub_j200" +} + + uboot_custom_postprocess() { if [[ "$BOARD" == "jethubj80" ]]; then uboot_gxl_postprocess_ng "$SRC/cache/sources/amlogic-boot-fip/jethub-j80" elif [[ "$BOARD" == "jethubj100" ]]; then uboot_axg_postprocess_ng "$SRC/cache/sources/amlogic-boot-fip/jethub-j100" + elif [[ "$BOARD" == "jethubj200" ]]; then + uboot_g12_postprocess "$SRC/cache/sources/amlogic-boot-fip-jethub/jethub-j200" g12a + else + display_alert "uboot_custom_postprocess jethub" "Unknown BOARD: $BOARD - not using FIP trees" "err" + exit 1 fi } @@ -155,7 +173,7 @@ buildjethomecmds() { run_host_command_logged env PATH="${toolchain}:${PATH}" "$gpp" $gpp_options "$SRC/packages/bsp/jethub/jethub_get_cmdline_key.cpp" -o "$destination/usr/bin/jethub_get_cmdline_key" || exit_with_error "Unable to compile jethub_get_cmdline_key.cpp" run_host_command_logged env PATH="${toolchain}:${PATH}" "$gpp" $gpp_options "$SRC/packages/bsp/jethub/jethub_get_cmdline_key_cpuid.cpp" -o "$destination/usr/bin/jethub_get_cpuid" || exit_with_error "Unable to compile jethub_get_cmdline_key_cpuid.cpp" - if [[ $BOARD == jethubj80 ]]; then + if [[ "$BOARD" == "jethubj80" ]]; then # Bluetooth run_host_command_logged install -m 755 "$SRC/packages/blobs/bt/hciattach/rtk_hciattach_$ARCH" "$destination/usr/bin/rtk_hciattach" || exit_with_error "Unable to install rtk_hciattach" @@ -170,7 +188,7 @@ buildjethomecmds() { run_host_command_logged env PATH="${toolchain}:${PATH}" "$gpp" $gpp_options "$SRC/packages/bsp/jethub/$BOARD/jethub_get_efuse_key_mac.cpp" -o "$destination/usr/bin/jethub_get_mac" || exit_with_error "Unable to compile jethub_get_efuse_key_mac.cpp" run_host_command_logged env PATH="${toolchain}:${PATH}" "$gpp" $gpp_options "$SRC/packages/bsp/jethub/$BOARD/jethub_get_efuse_key_serial.cpp" -o "$destination/usr/bin/jethub_get_serial" || exit_with_error "Unable to compile jethub_get_efuse_key_serial.cpp" run_host_command_logged env PATH="${toolchain}:${PATH}" "$gpp" $gpp_options "$SRC/packages/bsp/jethub/$BOARD/jethub_get_efuse_key_usid.cpp" -o "$destination/usr/bin/jethub_get_usid" || exit_with_error "Unable to compile jethub_get_efuse_key_usid.cpp" - elif [[ $BOARD == jethubj100 ]]; then + elif [[ "$BOARD" == "jethubj100" ]]; then # Board identifiers run_host_command_logged env PATH="${toolchain}:${PATH}" "$gpp" $gpp_options "$SRC/packages/bsp/jethub/$BOARD/jethub_get_cmdline_key_mac.cpp" -o "$destination/usr/bin/jethub_get_mac" || exit_with_error "Unable to compile jethub_get_cmdline_key_mac.cpp" @@ -182,6 +200,8 @@ buildjethomecmds() { run_host_command_logged ln -s "brcmfmac43455-sdio.txt" "$destination/lib/firmware/brcm/brcmfmac43455-sdio.jethome,jethub-j100.txt" run_host_command_logged ln -s "brcmfmac43456-sdio.bin" "$destination/lib/firmware/brcm/brcmfmac43456-sdio.jethome,jethub-j100.bin" run_host_command_logged ln -s "brcmfmac43456-sdio.txt" "$destination/lib/firmware/brcm/brcmfmac43456-sdio.jethome,jethub-j100.txt" + elif [[ "$BOARD" == "jethubj200" ]]; then + : else exit_with_error "Unexpected board \"$BOARD\"" fi From 9c9bbc62050be828e3900872ca0a55a32f27794c Mon Sep 17 00:00:00 2001 From: Viacheslav Bocharov Date: Fri, 7 Jun 2024 16:02:40 +0300 Subject: [PATCH 15/53] pre add jethubj200 bsp --- .../bsp/jethub/jethubj200/libjethubconfig.sh | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 packages/bsp/jethub/jethubj200/libjethubconfig.sh diff --git a/packages/bsp/jethub/jethubj200/libjethubconfig.sh b/packages/bsp/jethub/jethubj200/libjethubconfig.sh new file mode 100644 index 000000000000..9b6412f205d5 --- /dev/null +++ b/packages/bsp/jethub/jethubj200/libjethubconfig.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# shellcheck disable=SC2034 + +#TODO: empty now + +GPIOCHIPNUMBER=0 + +GPIO_DIRECTION_OUTPUT=0 +GPIO_DIRECTION_INPUT=1 + +GPIO_ACTIVE_LOW=0 +GPIO_ACTIVE_HIGH=1 + +GPIOS=( +) + + +# Set LED states +LEDS=( +) + + + +ADDITIONALFUNC="" From 3dd2e5c3ec076be643b9f2dd28ee923dc14d67de Mon Sep 17 00:00:00 2001 From: Viacheslav Bocharov Date: Fri, 7 Jun 2024 16:16:42 +0300 Subject: [PATCH 16/53] meson64-6.9 kernel: Add jethub j200 --- .../meson-sm1-jethome-jethub-j200-spinor.dts | 11 + ...amlogic-add-binding-for-JetHome-JetH.patch | 28 + ...axg-add-support-for-JetHome-JetHub-D.patch | 682 ++++++++++++++++++ .../archive/meson64-6.9/overlay/Makefile | 3 +- .../meson-sm1-jethome-jethub-j200-spi.dtso | 19 + 5 files changed, 742 insertions(+), 1 deletion(-) create mode 100644 patch/kernel/archive/meson64-6.9/dt/meson-sm1-jethome-jethub-j200-spinor.dts create mode 100644 patch/kernel/archive/meson64-6.9/jethome-0003-dt-bindings-arm-amlogic-add-binding-for-JetHome-JetH.patch create mode 100644 patch/kernel/archive/meson64-6.9/jethome-0004-arm64-dts-meson-axg-add-support-for-JetHome-JetHub-D.patch create mode 100644 patch/kernel/archive/meson64-6.9/overlay/meson-sm1-jethome-jethub-j200-spi.dtso diff --git a/patch/kernel/archive/meson64-6.9/dt/meson-sm1-jethome-jethub-j200-spinor.dts b/patch/kernel/archive/meson64-6.9/dt/meson-sm1-jethome-jethub-j200-spinor.dts new file mode 100644 index 000000000000..a9e4749f8395 --- /dev/null +++ b/patch/kernel/archive/meson64-6.9/dt/meson-sm1-jethome-jethub-j200-spinor.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include "meson-sm1-jethome-jethub-j200.dts" + +/ { + model = "JetHub D2 with SPI NOR flash"; +}; + +#include "meson-g12-enable-spinor.dtsi" diff --git a/patch/kernel/archive/meson64-6.9/jethome-0003-dt-bindings-arm-amlogic-add-binding-for-JetHome-JetH.patch b/patch/kernel/archive/meson64-6.9/jethome-0003-dt-bindings-arm-amlogic-add-binding-for-JetHome-JetH.patch new file mode 100644 index 000000000000..02e73c4f4b52 --- /dev/null +++ b/patch/kernel/archive/meson64-6.9/jethome-0003-dt-bindings-arm-amlogic-add-binding-for-JetHome-JetH.patch @@ -0,0 +1,28 @@ +From e38ecc4ec467c5eb1b7e510877532239a43f7db8 Mon Sep 17 00:00:00 2001 +From: Viacheslav Bocharov +Date: Thu, 6 Jun 2024 14:31:12 +0300 +Subject: [PATCH 1/2] dt-bindings: arm: amlogic: add binding for JetHome JetHub + D2 + +JetHome JetHub D2 is a home automation controller, based on Amlogic S905X3 SoC + +Signed-off-by: Viacheslav Bocharov +--- + Documentation/devicetree/bindings/arm/amlogic.yaml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml +index a374b98080fe..1acfb184aa9e 100644 +--- a/Documentation/devicetree/bindings/arm/amlogic.yaml ++++ b/Documentation/devicetree/bindings/arm/amlogic.yaml +@@ -190,6 +190,7 @@ properties: + - hardkernel,odroid-c4 + - hardkernel,odroid-hc4 + - haochuangyi,h96-max ++ - jethome,jethub-j200 + - khadas,vim3l + - libretech,aml-s905d3-cc + - seirobotics,sei610 +-- +2.45.2 + diff --git a/patch/kernel/archive/meson64-6.9/jethome-0004-arm64-dts-meson-axg-add-support-for-JetHome-JetHub-D.patch b/patch/kernel/archive/meson64-6.9/jethome-0004-arm64-dts-meson-axg-add-support-for-JetHome-JetHub-D.patch new file mode 100644 index 000000000000..c38f3e73a714 --- /dev/null +++ b/patch/kernel/archive/meson64-6.9/jethome-0004-arm64-dts-meson-axg-add-support-for-JetHome-JetHub-D.patch @@ -0,0 +1,682 @@ +From 7ad1d0a9aa045348451287ab7538201233c64a5b Mon Sep 17 00:00:00 2001 +From: Viacheslav Bocharov +Date: Thu, 16 May 2024 15:14:08 +0300 +Subject: [PATCH 2/2] arm64: dts: meson-axg: add support for JetHome JetHub D2 + (j200) + +JetHome Jethub D2 is a home automation controller with the following features: + - DIN Rail Mounting + - Amlogic S905X3 (ARM Cortex-A55) quad-core + - micro-HDMI video out + - 4GB LPDDR4 + - 32GB eMMC flash + - 1 x USB 2.0 + - 1 x 10/100/1000Mbps ethernet + - two module slots for radio/wire interface cards + - 2 x gpio LEDS + - 1 x 1-Wire + - 1 x RS-485 + - 3 x dry contact digital GPIO inputs + - 2 x relay GPIO outputs + - DC 9-36V power source with battery UPS on board option + +Signed-off-by: Viacheslav Bocharov +--- + arch/arm64/boot/dts/amlogic/Makefile | 1 + + .../amlogic/meson-sm1-jethome-jethub-j200.dts | 632 ++++++++++++++++++ + 2 files changed, 633 insertions(+) + create mode 100644 arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts + +diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile +index 0f29517da5ec..d007b59497d4 100644 +--- a/arch/arm64/boot/dts/amlogic/Makefile ++++ b/arch/arm64/boot/dts/amlogic/Makefile +@@ -79,6 +79,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-bananapi-m2-pro.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-bananapi-m5.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-h96-max.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-jethome-jethub-j200.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-khadas-vim3l.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-khadas-vim3l-ts050.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-s905d3-libretech-cc.dtb +diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts +new file mode 100644 +index 000000000000..fcffbd0e24cc +--- /dev/null ++++ b/arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts +@@ -0,0 +1,632 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2024 JetHome ++ * Author: Viacheslav Bocharov ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1.dtsi" ++ ++#include ++#include ++#include ++ ++ ++/ { ++ ++ compatible = "jethome,jethub-j200", "amlogic,sm1"; ++ model = "JetHome JetHub D2"; ++ ++ aliases { ++ serial0 = &uart_AO; ++ ethernet0 = ðmac; ++ rtc0 = &rtc; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x40000000>; ++ }; ++ ++ emmc_pwrseq: emmc-pwrseq { ++ compatible = "mmc-pwrseq-emmc"; ++ reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>; ++ }; ++ ++ tflash_vdd: regulator-tflash_vdd { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "TFLASH_VDD"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ao GPIOAO_3 GPIO_OPEN_DRAIN>; // #TODO: check ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ tf_io: gpio-regulator-tf_io { ++ compatible = "regulator-gpio"; ++ ++ regulator-name = "TF_IO"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_5v>; ++ ++ enable-gpios = <&gpio_ao GPIOE_2 GPIO_OPEN_DRAIN>; ++ enable-active-high; ++ regulator-always-on; ++ ++ gpios = <&gpio_ao GPIOAO_6 GPIO_OPEN_SOURCE>; // #TODO: check ++ gpios-states = <0>; ++ ++ states = <3300000 0>, ++ <1800000 1>; ++ }; ++ ++ flash_1v8: regulator-flash_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "FLASH_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc_3v3>; ++ regulator-always-on; ++ }; ++ ++ main_12v: regulator-main_12v { ++ compatible = "regulator-fixed"; ++ regulator-name = "12V"; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ regulator-always-on; ++ }; ++ ++ vcc_5v: regulator-vcc_5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "5V"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ vin-supply = <&main_12v>; ++ gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>; // #TODO: check ++ enable-active-high; ++ }; ++ ++ vcc_1v8: regulator-vcc_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc_3v3>; ++ regulator-always-on; ++ }; ++ ++ vcc_3v3: regulator-vcc_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vddao_3v3>; ++ regulator-always-on; ++ /* FIXME: actually controlled by VDDCPU_B_EN */ ++ }; ++ ++ vddcpu: regulator-vddcpu { ++ /* ++ * MP8756GD Regulator. ++ */ ++ compatible = "pwm-regulator"; ++ ++ regulator-name = "VDDCPU"; ++ regulator-min-microvolt = <721000>; ++ regulator-max-microvolt = <1022000>; ++ ++ pwm-supply = <&main_12v>; ++ ++ pwms = <&pwm_AO_cd 1 1250 0>; ++ pwm-dutycycle-range = <100 0>; ++ ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ usb_pwr_en: regulator-usb_pwr_en { ++ compatible = "regulator-fixed"; ++ regulator-name = "USB_PWR_EN"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_5v>; ++ ++ /* Connected to the microUSB port power enable */ ++ gpio = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vddao_1v8: regulator-vddao_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDAO_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vddao_3v3>; ++ regulator-always-on; ++ }; ++ ++ vddao_3v3: regulator-vddao_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDAO_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&main_12v>; ++ regulator-always-on; ++ }; ++ ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&hdmi_tx_tmds_out>; ++ }; ++ }; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDM_B Playback", "TDMOUT_B OUT"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ ++ /* 8ch hdmi interface */ ++ dai-link-0 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-1 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++ ++ meson64-reboot { ++ compatible = "meson64,reboot"; ++ sys_reset = <0x84000009>; ++ sys_poweroff = <0x84000008>; ++ ++ sd-vqen = <&gpio GPIOE_2 GPIO_ACTIVE_HIGH>; ++ sd-vqsw = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; ++ sd-vmmc = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-green { ++ color = ; ++ function = LED_FUNCTION_STATUS; ++ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "activity"; ++ panic-indicator; ++ }; ++ ++ led-red { ++ color = ; ++ function = LED_FUNCTION_POWER; ++ gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ }; ++ ++ sound { ++ model = "JETHUB-D2"; ++ }; ++ ++}; ++ ++ ++&arb { ++ status = "okay"; ++}; ++ ++&cec_AO { ++ pinctrl-0 = <&cec_ao_a_h_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ hdmi-phandle = <&hdmi_tx>; ++}; ++ ++&cecb_AO { ++ pinctrl-0 = <&cec_ao_b_h_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ hdmi-phandle = <&hdmi_tx>; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU1_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU2_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU3_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&ext_mdio { ++ external_phy: ethernet-phy@0 { ++ /* Realtek RTL8211F (0x001cc916) */ ++ reg = <0>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = ; ++ }; ++}; ++ ++ðmac { ++ pinctrl-0 = <ð_pins>, <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ phy-mode = "rgmii"; ++ phy-handle = <&external_phy>; ++ amlogic,tx-delay-ns = <2>; ++}; ++ ++&gpio { ++ gpio-line-names = ++ /* GPIOZ */ ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ /* GPIOH */ ++ "", "", "", "", "", ++ "LED_RED", /* GPIOH_5 */ ++ "I2C_SDA_MODULES", /* GPIOH_6 */ ++ "I2C_SCL_MODULES", /* GPIOH_7 */ ++ "", ++ /* BOOT */ ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ /* GPIOC */ ++ "", "", "", "", "", "", "", "", ++ /* GPIOA */ ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", ++ "I2C_SDA_SYSBUS", /* GPIOA_14 */ ++ "I2C_SCL_SYSBUS", /* GPIOA_15 */ ++ /* GPIOX */ ++ "", /* GPIOX_0 */ ++ "", /* GPIOX_1 */ ++ "", /* GPIOX_2 */ ++ "", /* GPIOX_3 */ ++ "", /* GPIOX_4 */ ++ "", /* GPIOX_5 */ ++ "RS485_TX", /* GPIOX_6 */ ++ "RS485_RX", /* GPIOX_7 */ ++ "", /* GPIOX_8 */ ++ "", /* GPIOX_9 */ ++ "", /* GPIOX_10 */ ++ "", /* GPIOX_11 */ ++ "", /* GPIOX_12 */ ++ "", /* GPIOX_13 */ ++ "", /* GPIOX_14 */ ++ "", /* GPIOX_15 */ ++ "", /* GPIOX_16 */ ++ "I2C_SDA_LCDBUS", /* GPIOX_17 */ ++ "I2C_SCL_LCDBUS", /* GPIOX_18 */ ++ ""; /* GPIOX_19 */ ++}; ++ ++&gpio_ao { ++ gpio-line-names = ++ /* GPIOAO */ ++ "", "", "", "", ++ "MCU_RESET", /* GPIOAO_4 */ ++ "POWER_GOOD", /* GPIOAO_5 */ ++ "", ++ "MCU_BOOT", /* GPIOAO_7 */ ++ "MCU_UART_TX", /* GPIOAO_8 */ ++ "MCU_UART_RX", /* GPIOAO_9 */ ++ "BUTTON_USR", /* GPIOAO_10 */ ++ "LED_GREEN", /* GPIOAO_11 */ ++ /* GPIOE */ ++ "", "", ""; ++}; ++ ++&hdmi_tx { ++ status = "okay"; ++ pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>; ++ pinctrl-names = "default"; ++ hdmi-supply = <&vcc_5v>; ++}; ++ ++&hdmi_tx_tmds_port { ++ hdmi_tx_tmds_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ }; ++}; ++ ++&pwm_AO_cd { ++ pinctrl-0 = <&pwm_ao_d_e_pins>; // GPIOE_1 ++ pinctrl-names = "default"; ++ clocks = <&xtal>; ++ clock-names = "clkin1"; ++ status = "okay"; ++}; ++ ++&saradc { ++ status = "okay"; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ status = "okay"; ++ pinctrl-0 = <&sdcard_c_pins>; ++ pinctrl-1 = <&sdcard_clk_gate_c_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ max-frequency = <200000000>; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ disable-wp; ++ ++ cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>; ++ vmmc-supply = <&tflash_vdd>; ++ vqmmc-supply = <&tf_io>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ status = "okay"; ++ pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_8b_pins>, <&emmc_ds_pins>; ++ pinctrl-1 = <&emmc_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ max-frequency = <200000000>; ++ disable-wp; ++ ++ mmc-pwrseq = <&emmc_pwrseq>; ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&flash_1v8>; ++}; ++ ++/* ++&sd_emmc_c { ++ pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_4b_pins>, <&emmc_ds_pins>; ++ bus-width = <4>; ++}; ++ ++&spifc { ++ status = "okay"; ++ pinctrl-0 = <&nor_pins>; ++ pinctrl-names = "default"; ++ ++ flash@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <104000000>; ++ }; ++}; ++*/ ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_AO { ++ status = "okay"; ++ pinctrl-0 = <&uart_ao_a_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&uart_AO_B { ++ status = "okay"; ++ pinctrl-0 = <&uart_ao_b_8_9_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&uart_B { ++ status = "okay"; ++ pinctrl-0 = <&uart_b_pins>; ++ pinctrl-names = "default"; ++}; ++ ++ ++&usb { ++ status = "okay"; ++ vbus-supply = <&usb_pwr_en>; ++}; ++ ++&dwc2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* USB 2.0 hub on otg port */ ++ hub_2_0: hub@1 { ++ compatible = "usb4b4,6504"; /* use 10000us timeout for reset */ ++ reg = <1>; ++ reset-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_LOW>; ++ vdd-supply = <&vcc_5v>; ++ }; ++}; ++ ++&usb2_phy0 { ++ phy-supply = <&vcc_5v>; ++}; ++ ++ ++/* I2C for modules */ ++&i2c1 { ++ status = "okay"; ++ pinctrl-0 = <&i2c1_sda_h6_pins>, <&i2c1_sck_h7_pins>; ++ pinctrl-names = "default"; ++ ++ /* GPIO expander */ ++ u9: gpio@22 { ++ compatible = "nxp,pca9535"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ gpio-line-names = ++ "RELAY_1", "RELAY_2", ++ "", "", ++ "UXM1_RESET", "UXM1_BOOT", ++ "UXM2_RESET", "UXM2_BOOT", ++ "DIN_1", "DIN_2", "DIN_3", ++ "","","","",""; ++ }; ++ ++ /* 1-wire */ ++ w1: onewire@18 { ++ compatible = "maxim,ds2482"; ++ reg = <0x18>; ++ }; ++ ++}; ++ ++ ++/* I2C for lcd/etc */ ++&i2c2 { ++ status = "okay"; ++ pinctrl-0 = <&i2c2_sda_x_pins>, <&i2c2_sck_x_pins>; ++ pinctrl-names = "default"; ++}; ++ ++/* I2C_EE_M3: I2C for CPU board */ ++&i2c3 { ++ status = "okay"; ++ pinctrl-0 = <&i2c3_sda_a_pins>, <&i2c3_sck_a_pins>; ++ pinctrl-names = "default"; ++ ++ /* I2C for rtc */ ++ rtc: rtc@51 { ++ status = "okay"; ++ compatible = "nxp,pcf8563"; ++ reg = <0x51>; ++ wakeup-source; ++ }; ++ ++ /* FRAM on base board */ ++ fram: eeprom@52 { ++ compatible = "atmel,24c64"; ++ reg = <0x52>; ++ pagesize = <0x20>; ++ label = "fram"; ++ address-width = <0x10>; ++ vcc-supply = <&vddao_3v3>; ++ }; ++ ++ /* EEPROM on CPU board */ ++ eepromc: eeprom@54 { ++ compatible = "atmel,24c64"; ++ reg = <0x54>; ++ pagesize = <0x20>; ++ label = "eepromc"; ++ address-width = <0x10>; ++ vcc-supply = <&vddao_3v3>; ++ }; ++ ++ /* EEPROM on base board */ ++ eeprompd: eeprom@56 { ++ compatible = "atmel,24c64"; ++ reg = <0x56>; ++ pagesize = <0x20>; ++ label = "eeprompd"; ++ address-width = <0x10>; ++ vcc-supply = <&vddao_3v3>; ++ }; ++ ++ /* EEPROM on power module */ ++ eeprompm: eeprom@57 { ++ compatible = "atmel,24c64"; ++ reg = <0x57>; ++ pagesize = <0x20>; ++ label = "eeprompm"; ++ address-width = <0x10>; ++ vcc-supply = <&vddao_3v3>; ++ }; ++ ++ /* temperature sensors */ ++ temp1: tmp102@48 { ++ compatible = "ti,tmp102"; ++ reg = <0x48>; ++ }; ++ ++ temp2: tmp102@49 { ++ compatible = "ti,tmp102"; ++ reg = <0x49>; ++ }; ++ ++}; +-- +2.45.2 + diff --git a/patch/kernel/archive/meson64-6.9/overlay/Makefile b/patch/kernel/archive/meson64-6.9/overlay/Makefile index a725d266fcd0..bbd0103cf53a 100644 --- a/patch/kernel/archive/meson64-6.9/overlay/Makefile +++ b/patch/kernel/archive/meson64-6.9/overlay/Makefile @@ -28,7 +28,8 @@ dtbo-$(CONFIG_ARCH_MESON) += \ meson-sm1-bananapi-m5-rtl8822cs.dtbo \ meson-sm1-bananapi-uartA.dtbo \ meson-sm1-bananapi-uartA_cts_rts.dtbo \ - meson-sm1-bananapi-uartAO_B.dtbo + meson-sm1-bananapi-uartAO_B.dtbo \ + meson-sm1-jethome-jethub-j200-spi.dtbo scr-$(CONFIG_ARCH_MESON) += \ meson-fixup.scr diff --git a/patch/kernel/archive/meson64-6.9/overlay/meson-sm1-jethome-jethub-j200-spi.dtso b/patch/kernel/archive/meson64-6.9/overlay/meson-sm1-jethome-jethub-j200-spi.dtso new file mode 100644 index 000000000000..eab65a1570db --- /dev/null +++ b/patch/kernel/archive/meson64-6.9/overlay/meson-sm1-jethome-jethub-j200-spi.dtso @@ -0,0 +1,19 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&sd_emmc_c>; + __overlay__ { + pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_4b_pins>, <&emmc_ds_pins>; + bus-width = <4>; + }; + }; + + fragment@1 { + target = <&spifc>; + __overlay__ { + status = "okay"; + }; + }; +}; From 192e732244e98ab073d5bd124f5069e7793c4afc Mon Sep 17 00:00:00 2001 From: Viacheslav Bocharov Date: Mon, 10 Jun 2024 14:45:45 +0300 Subject: [PATCH 17/53] add jethub j200 config (wip) --- config/boards/jethubj200.wip | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 config/boards/jethubj200.wip diff --git a/config/boards/jethubj200.wip b/config/boards/jethubj200.wip new file mode 100644 index 000000000000..3c2f60a3ade4 --- /dev/null +++ b/config/boards/jethubj200.wip @@ -0,0 +1,20 @@ +# Amlogic S905X3 quad core 4GB RAM SoC eMMC GBE USB2 SPI +BOARD_NAME="JetHub D2 family" +BOARDFAMILY="jethub" +BOARD_MAINTAINER="adeepn" +BOOTCONFIG="jethub_j200_defconfig" +KERNEL_TARGET="current,edge" +MODULES_BLACKLIST="simpledrm" # SimpleDRM conflicts with Panfrost +FULL_DESKTOP="yes" +SERIALCON="ttyAML0" +#BOOT_LOGO="desktop" + +BOOTBRANCH_BOARD="tag:v2024.01" +BOOTPATCHDIR="v2024.01" + +BOOT_FDT_FILE="amlogic/meson-sm1-jethome-jethub-j200.dtb" + +# To enable the SPI NOR the -spi .dtb is required, because eMMC shares a pin with SPI on the D2. To use it: +# fdtfile=amlogic/meson-sm1-jethome-jethub-j200-spinor.dtb # in armbianEnv.txt and reboot, then run armbian-install +# After deploying to SPI-NOR/MTD, return back to the normal DTB, otherwise eMMC speed is impaired. +#UBOOT_TARGET_MAP="u-boot-dtb.img;;u-boot.bin.sd.bin:u-boot.bin u-boot-dtb.img u-boot.bin:u-boot-spi.bin" From 6ee05aa88007ce6cad6ee6373136785cae1f5d18 Mon Sep 17 00:00:00 2001 From: kernelzru <106839081+kernelzru@users.noreply.github.com> Date: Wed, 12 Jun 2024 00:10:51 +0300 Subject: [PATCH 18/53] Add audio support to hdmi output (meson) Add audio support to hdmi output (meson) --- config/kernel/linux-meson-edge.config | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/kernel/linux-meson-edge.config b/config/kernel/linux-meson-edge.config index 91933cad6463..6c3d37098b17 100644 --- a/config/kernel/linux-meson-edge.config +++ b/config/kernel/linux-meson-edge.config @@ -5129,8 +5129,9 @@ CONFIG_SND_MESON_AIU=m # CONFIG_SND_MESON_AXG_SPDIFOUT is not set # CONFIG_SND_MESON_AXG_SPDIFIN is not set # CONFIG_SND_MESON_AXG_PDM is not set +CONFIG_SND_MESON_CARD_UTILS=m CONFIG_SND_MESON_CODEC_GLUE=m -# CONFIG_SND_MESON_GX_SOUND_CARD is not set +CONFIG_SND_MESON_GX_SOUND_CARD=m # CONFIG_SND_MESON_G12A_TOACODEC is not set # CONFIG_SND_MESON_G12A_TOHDMITX is not set # CONFIG_SND_SOC_MESON_T9015 is not set From a2a6ac1d954ed0713e629b6077cfaf96ba0f0423 Mon Sep 17 00:00:00 2001 From: Igor Pecovnik Date: Wed, 12 Jun 2024 15:27:21 +0200 Subject: [PATCH 19/53] Temporally disable broken build configuration --- config/boards/{jethubj200.wip => jethubj200.eos} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename config/boards/{jethubj200.wip => jethubj200.eos} (100%) diff --git a/config/boards/jethubj200.wip b/config/boards/jethubj200.eos similarity index 100% rename from config/boards/jethubj200.wip rename to config/boards/jethubj200.eos From f9940caee41c2f2ac5dd5ccd02f491e1ee94ba7f Mon Sep 17 00:00:00 2001 From: Igor Pecovnik Date: Wed, 12 Jun 2024 15:28:34 +0200 Subject: [PATCH 20/53] Odroid XU4: Remove deprecated patches --- .../odroidxu4-6.6/patch-6.6.30-31.patch | 12777 ---------------- .../odroidxu4-6.6/patch-6.6.31-32.patch | 10264 ------------- 2 files changed, 23041 deletions(-) delete mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.30-31.patch delete mode 100644 patch/kernel/archive/odroidxu4-6.6/patch-6.6.31-32.patch diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.30-31.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.30-31.patch deleted file mode 100644 index 6eb335f8712c..000000000000 --- a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.30-31.patch +++ /dev/null @@ -1,12777 +0,0 @@ -diff --git a/Documentation/devicetree/bindings/iio/health/maxim,max30102.yaml b/Documentation/devicetree/bindings/iio/health/maxim,max30102.yaml -index c13c10c8d65da..eed0df9d3a232 100644 ---- a/Documentation/devicetree/bindings/iio/health/maxim,max30102.yaml -+++ b/Documentation/devicetree/bindings/iio/health/maxim,max30102.yaml -@@ -42,7 +42,7 @@ allOf: - properties: - compatible: - contains: -- const: maxim,max30100 -+ const: maxim,max30102 - then: - properties: - maxim,green-led-current-microamp: false -diff --git a/Documentation/devicetree/bindings/net/mediatek,net.yaml b/Documentation/devicetree/bindings/net/mediatek,net.yaml -index e74502a0afe86..3202dc7967c5b 100644 ---- a/Documentation/devicetree/bindings/net/mediatek,net.yaml -+++ b/Documentation/devicetree/bindings/net/mediatek,net.yaml -@@ -337,8 +337,8 @@ allOf: - minItems: 4 - - clocks: -- minItems: 34 -- maxItems: 34 -+ minItems: 24 -+ maxItems: 24 - - clock-names: - items: -@@ -351,18 +351,6 @@ allOf: - - const: ethwarp_wocpu1 - - const: ethwarp_wocpu0 - - const: esw -- - const: netsys0 -- - const: netsys1 -- - const: sgmii_tx250m -- - const: sgmii_rx250m -- - const: sgmii2_tx250m -- - const: sgmii2_rx250m -- - const: top_usxgmii0_sel -- - const: top_usxgmii1_sel -- - const: top_sgm0_sel -- - const: top_sgm1_sel -- - const: top_xfi_phy0_xtal_sel -- - const: top_xfi_phy1_xtal_sel - - const: top_eth_gmii_sel - - const: top_eth_refck_50m_sel - - const: top_eth_sys_200m_sel -@@ -375,16 +363,10 @@ allOf: - - const: top_netsys_sync_250m_sel - - const: top_netsys_ppefb_250m_sel - - const: top_netsys_warp_sel -- - const: wocpu1 -- - const: wocpu0 - - const: xgp1 - - const: xgp2 - - const: xgp3 - -- mediatek,sgmiisys: -- minItems: 2 -- maxItems: 2 -- - patternProperties: - "^mac@[0-1]$": - type: object -diff --git a/Makefile b/Makefile -index 1c144301b02f6..f66238b5d9315 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,7 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - VERSION = 6 - PATCHLEVEL = 6 --SUBLEVEL = 30 -+SUBLEVEL = 31 - EXTRAVERSION = - NAME = Hurr durr I'ma ninja sloth - -diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S -index a86a1d4f34618..93afd1005b43c 100644 ---- a/arch/arm/kernel/sleep.S -+++ b/arch/arm/kernel/sleep.S -@@ -127,6 +127,10 @@ cpu_resume_after_mmu: - instr_sync - #endif - bl cpu_init @ restore the und/abt/irq banked regs -+#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK) -+ mov r0, sp -+ bl kasan_unpoison_task_stack_below -+#endif - mov r0, #0 @ return zero on success - ldmfd sp!, {r4 - r11, pc} - ENDPROC(cpu_resume_after_mmu) -diff --git a/arch/arm64/boot/dts/qcom/sa8155p-adp.dts b/arch/arm64/boot/dts/qcom/sa8155p-adp.dts -index 5e4287f8c8cd1..b2cf2c988336c 100644 ---- a/arch/arm64/boot/dts/qcom/sa8155p-adp.dts -+++ b/arch/arm64/boot/dts/qcom/sa8155p-adp.dts -@@ -367,6 +367,16 @@ queue0 { - }; - }; - -+&pmm8155au_1_gpios { -+ pmm8155au_1_sdc2_cd: sdc2-cd-default-state { -+ pins = "gpio4"; -+ function = "normal"; -+ input-enable; -+ bias-pull-up; -+ power-source = <0>; -+ }; -+}; -+ - &qupv3_id_1 { - status = "okay"; - }; -@@ -384,10 +394,10 @@ &remoteproc_cdsp { - &sdhc_2 { - status = "okay"; - -- cd-gpios = <&tlmm 4 GPIO_ACTIVE_LOW>; -+ cd-gpios = <&pmm8155au_1_gpios 4 GPIO_ACTIVE_LOW>; - pinctrl-names = "default", "sleep"; -- pinctrl-0 = <&sdc2_on>; -- pinctrl-1 = <&sdc2_off>; -+ pinctrl-0 = <&sdc2_on &pmm8155au_1_sdc2_cd>; -+ pinctrl-1 = <&sdc2_off &pmm8155au_1_sdc2_cd>; - vqmmc-supply = <&vreg_l13c_2p96>; /* IO line power */ - vmmc-supply = <&vreg_l17a_2p96>; /* Card power line */ - bus-width = <4>; -@@ -505,13 +515,6 @@ data-pins { - bias-pull-up; /* pull up */ - drive-strength = <16>; /* 16 MA */ - }; -- -- sd-cd-pins { -- pins = "gpio96"; -- function = "gpio"; -- bias-pull-up; /* pull up */ -- drive-strength = <2>; /* 2 MA */ -- }; - }; - - sdc2_off: sdc2-off-state { -@@ -532,13 +535,6 @@ data-pins { - bias-pull-up; /* pull up */ - drive-strength = <2>; /* 2 MA */ - }; -- -- sd-cd-pins { -- pins = "gpio96"; -- function = "gpio"; -- bias-pull-up; /* pull up */ -- drive-strength = <2>; /* 2 MA */ -- }; - }; - - usb2phy_ac_en1_default: usb2phy-ac-en1-default-state { -diff --git a/arch/arm64/kvm/vgic/vgic-kvm-device.c b/arch/arm64/kvm/vgic/vgic-kvm-device.c -index 212b73a715c1c..2f9e8c611f642 100644 ---- a/arch/arm64/kvm/vgic/vgic-kvm-device.c -+++ b/arch/arm64/kvm/vgic/vgic-kvm-device.c -@@ -337,16 +337,12 @@ int kvm_register_vgic_device(unsigned long type) - int vgic_v2_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr, - struct vgic_reg_attr *reg_attr) - { -- int cpuid; -+ int cpuid = FIELD_GET(KVM_DEV_ARM_VGIC_CPUID_MASK, attr->attr); - -- cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >> -- KVM_DEV_ARM_VGIC_CPUID_SHIFT; -- -- if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) -- return -EINVAL; -- -- reg_attr->vcpu = kvm_get_vcpu(dev->kvm, cpuid); - reg_attr->addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK; -+ reg_attr->vcpu = kvm_get_vcpu_by_id(dev->kvm, cpuid); -+ if (!reg_attr->vcpu) -+ return -EINVAL; - - return 0; - } -diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c -index 29196dce9b91d..166619348b98e 100644 ---- a/arch/arm64/net/bpf_jit_comp.c -+++ b/arch/arm64/net/bpf_jit_comp.c -@@ -1738,15 +1738,15 @@ static void invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_link *l, - - emit_call(enter_prog, ctx); - -+ /* save return value to callee saved register x20 */ -+ emit(A64_MOV(1, A64_R(20), A64_R(0)), ctx); -+ - /* if (__bpf_prog_enter(prog) == 0) - * goto skip_exec_of_prog; - */ - branch = ctx->image + ctx->idx; - emit(A64_NOP, ctx); - -- /* save return value to callee saved register x20 */ -- emit(A64_MOV(1, A64_R(20), A64_R(0)), ctx); -- - emit(A64_ADD_I(1, A64_R(0), A64_SP, args_off), ctx); - if (!p->jited) - emit_addr_mov_i64(A64_R(1), (const u64)p->insnsi, ctx); -diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h -index d14d0e37ad02d..4a2b40ce39e09 100644 ---- a/arch/mips/include/asm/ptrace.h -+++ b/arch/mips/include/asm/ptrace.h -@@ -159,7 +159,7 @@ extern unsigned long exception_ip(struct pt_regs *regs); - #define exception_ip(regs) exception_ip(regs) - #define profile_pc(regs) instruction_pointer(regs) - --extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall); -+extern asmlinkage long syscall_trace_enter(struct pt_regs *regs); - extern asmlinkage void syscall_trace_leave(struct pt_regs *regs); - - extern void die(const char *, struct pt_regs *) __noreturn; -diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c -index d1b11f66f748f..cb1045ebab062 100644 ---- a/arch/mips/kernel/asm-offsets.c -+++ b/arch/mips/kernel/asm-offsets.c -@@ -101,6 +101,7 @@ void output_thread_info_defines(void) - OFFSET(TI_CPU, thread_info, cpu); - OFFSET(TI_PRE_COUNT, thread_info, preempt_count); - OFFSET(TI_REGS, thread_info, regs); -+ OFFSET(TI_SYSCALL, thread_info, syscall); - DEFINE(_THREAD_SIZE, THREAD_SIZE); - DEFINE(_THREAD_MASK, THREAD_MASK); - DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE); -diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c -index 59288c13b581b..61503a36067e9 100644 ---- a/arch/mips/kernel/ptrace.c -+++ b/arch/mips/kernel/ptrace.c -@@ -1317,16 +1317,13 @@ long arch_ptrace(struct task_struct *child, long request, - * Notification of system call entry/exit - * - triggered by current->work.syscall_trace - */ --asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) -+asmlinkage long syscall_trace_enter(struct pt_regs *regs) - { - user_exit(); - -- current_thread_info()->syscall = syscall; -- - if (test_thread_flag(TIF_SYSCALL_TRACE)) { - if (ptrace_report_syscall_entry(regs)) - return -1; -- syscall = current_thread_info()->syscall; - } - - #ifdef CONFIG_SECCOMP -@@ -1335,7 +1332,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) - struct seccomp_data sd; - unsigned long args[6]; - -- sd.nr = syscall; -+ sd.nr = current_thread_info()->syscall; - sd.arch = syscall_get_arch(current); - syscall_get_arguments(current, regs, args); - for (i = 0; i < 6; i++) -@@ -1345,23 +1342,23 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) - ret = __secure_computing(&sd); - if (ret == -1) - return ret; -- syscall = current_thread_info()->syscall; - } - #endif - - if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) - trace_sys_enter(regs, regs->regs[2]); - -- audit_syscall_entry(syscall, regs->regs[4], regs->regs[5], -+ audit_syscall_entry(current_thread_info()->syscall, -+ regs->regs[4], regs->regs[5], - regs->regs[6], regs->regs[7]); - - /* - * Negative syscall numbers are mistaken for rejected syscalls, but - * won't have had the return value set appropriately, so we do so now. - */ -- if (syscall < 0) -+ if (current_thread_info()->syscall < 0) - syscall_set_return_value(current, regs, -ENOSYS, 0); -- return syscall; -+ return current_thread_info()->syscall; - } - - /* -diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S -index 18dc9b3450561..2c604717e6308 100644 ---- a/arch/mips/kernel/scall32-o32.S -+++ b/arch/mips/kernel/scall32-o32.S -@@ -77,6 +77,18 @@ loads_done: - PTR_WD load_a7, bad_stack_a7 - .previous - -+ /* -+ * syscall number is in v0 unless we called syscall(__NR_###) -+ * where the real syscall number is in a0 -+ */ -+ subu t2, v0, __NR_O32_Linux -+ bnez t2, 1f /* __NR_syscall at offset 0 */ -+ LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number -+ b 2f -+1: -+ LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number -+2: -+ - lw t0, TI_FLAGS($28) # syscall tracing enabled? - li t1, _TIF_WORK_SYSCALL_ENTRY - and t0, t1 -@@ -114,16 +126,7 @@ syscall_trace_entry: - SAVE_STATIC - move a0, sp - -- /* -- * syscall number is in v0 unless we called syscall(__NR_###) -- * where the real syscall number is in a0 -- */ -- move a1, v0 -- subu t2, v0, __NR_O32_Linux -- bnez t2, 1f /* __NR_syscall at offset 0 */ -- lw a1, PT_R4(sp) -- --1: jal syscall_trace_enter -+ jal syscall_trace_enter - - bltz v0, 1f # seccomp failed? Skip syscall - -diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S -index 97456b2ca7dc3..97788859238c3 100644 ---- a/arch/mips/kernel/scall64-n32.S -+++ b/arch/mips/kernel/scall64-n32.S -@@ -44,6 +44,8 @@ NESTED(handle_sysn32, PT_SIZE, sp) - - sd a3, PT_R26(sp) # save a3 for syscall restarting - -+ LONG_S v0, TI_SYSCALL($28) # Store syscall number -+ - li t1, _TIF_WORK_SYSCALL_ENTRY - LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? - and t0, t1, t0 -@@ -72,7 +74,6 @@ syscall_common: - n32_syscall_trace_entry: - SAVE_STATIC - move a0, sp -- move a1, v0 - jal syscall_trace_enter - - bltz v0, 1f # seccomp failed? Skip syscall -diff --git a/arch/mips/kernel/scall64-n64.S b/arch/mips/kernel/scall64-n64.S -index e6264aa62e457..be11ea5cc67e0 100644 ---- a/arch/mips/kernel/scall64-n64.S -+++ b/arch/mips/kernel/scall64-n64.S -@@ -46,6 +46,8 @@ NESTED(handle_sys64, PT_SIZE, sp) - - sd a3, PT_R26(sp) # save a3 for syscall restarting - -+ LONG_S v0, TI_SYSCALL($28) # Store syscall number -+ - li t1, _TIF_WORK_SYSCALL_ENTRY - LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? - and t0, t1, t0 -@@ -82,7 +84,6 @@ n64_syscall_exit: - syscall_trace_entry: - SAVE_STATIC - move a0, sp -- move a1, v0 - jal syscall_trace_enter - - bltz v0, 1f # seccomp failed? Skip syscall -diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S -index d3c2616cba226..7a5abb73e5312 100644 ---- a/arch/mips/kernel/scall64-o32.S -+++ b/arch/mips/kernel/scall64-o32.S -@@ -79,6 +79,22 @@ loads_done: - PTR_WD load_a7, bad_stack_a7 - .previous - -+ /* -+ * absolute syscall number is in v0 unless we called syscall(__NR_###) -+ * where the real syscall number is in a0 -+ * note: NR_syscall is the first O32 syscall but the macro is -+ * only defined when compiling with -mabi=32 (CONFIG_32BIT) -+ * therefore __NR_O32_Linux is used (4000) -+ */ -+ -+ subu t2, v0, __NR_O32_Linux -+ bnez t2, 1f /* __NR_syscall at offset 0 */ -+ LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number -+ b 2f -+1: -+ LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number -+2: -+ - li t1, _TIF_WORK_SYSCALL_ENTRY - LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? - and t0, t1, t0 -@@ -113,22 +129,7 @@ trace_a_syscall: - sd a7, PT_R11(sp) # For indirect syscalls - - move a0, sp -- /* -- * absolute syscall number is in v0 unless we called syscall(__NR_###) -- * where the real syscall number is in a0 -- * note: NR_syscall is the first O32 syscall but the macro is -- * only defined when compiling with -mabi=32 (CONFIG_32BIT) -- * therefore __NR_O32_Linux is used (4000) -- */ -- .set push -- .set reorder -- subu t1, v0, __NR_O32_Linux -- move a1, v0 -- bnez t1, 1f /* __NR_syscall at offset 0 */ -- ld a1, PT_R4(sp) /* Arg1 for __NR_syscall case */ -- .set pop -- --1: jal syscall_trace_enter -+ jal syscall_trace_enter - - bltz v0, 1f # seccomp failed? Skip syscall - -diff --git a/arch/powerpc/crypto/chacha-p10-glue.c b/arch/powerpc/crypto/chacha-p10-glue.c -index 74fb86b0d2097..7c728755852e1 100644 ---- a/arch/powerpc/crypto/chacha-p10-glue.c -+++ b/arch/powerpc/crypto/chacha-p10-glue.c -@@ -197,6 +197,9 @@ static struct skcipher_alg algs[] = { - - static int __init chacha_p10_init(void) - { -+ if (!cpu_has_feature(CPU_FTR_ARCH_31)) -+ return 0; -+ - static_branch_enable(&have_p10); - - return crypto_register_skciphers(algs, ARRAY_SIZE(algs)); -@@ -204,10 +207,13 @@ static int __init chacha_p10_init(void) - - static void __exit chacha_p10_exit(void) - { -+ if (!static_branch_likely(&have_p10)) -+ return; -+ - crypto_unregister_skciphers(algs, ARRAY_SIZE(algs)); - } - --module_cpu_feature_match(PPC_MODULE_FEATURE_P10, chacha_p10_init); -+module_init(chacha_p10_init); - module_exit(chacha_p10_exit); - - MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (P10 accelerated)"); -diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h -index 23b77027c9163..7a84069759b03 100644 ---- a/arch/powerpc/include/asm/plpks.h -+++ b/arch/powerpc/include/asm/plpks.h -@@ -44,9 +44,8 @@ - #define PLPKS_MAX_DATA_SIZE 4000 - - // Timeouts for PLPKS operations --#define PLPKS_MAX_TIMEOUT 5000 // msec --#define PLPKS_FLUSH_SLEEP 10 // msec --#define PLPKS_FLUSH_SLEEP_RANGE 400 -+#define PLPKS_MAX_TIMEOUT (5 * USEC_PER_SEC) -+#define PLPKS_FLUSH_SLEEP 10000 // usec - - struct plpks_var { - char *component; -diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c -index e8c4129697b14..b1e6d275cda9e 100644 ---- a/arch/powerpc/platforms/pseries/iommu.c -+++ b/arch/powerpc/platforms/pseries/iommu.c -@@ -786,8 +786,16 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) - * parent bus. During reboot, there will be ibm,dma-window property to - * define DMA window. For kdump, there will at least be default window or DDW - * or both. -+ * There is an exception to the above. In case the PE goes into frozen -+ * state, firmware may not provide ibm,dma-window property at the time -+ * of LPAR boot up. - */ - -+ if (!pdn) { -+ pr_debug(" no ibm,dma-window property !\n"); -+ return; -+ } -+ - ppci = PCI_DN(pdn); - - pr_debug(" parent is %pOF, iommu_table: 0x%p\n", -diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c -index 2d40304eb6c16..ed492d38f6ad6 100644 ---- a/arch/powerpc/platforms/pseries/plpks.c -+++ b/arch/powerpc/platforms/pseries/plpks.c -@@ -415,8 +415,7 @@ static int plpks_confirm_object_flushed(struct label *label, - break; - } - -- usleep_range(PLPKS_FLUSH_SLEEP, -- PLPKS_FLUSH_SLEEP + PLPKS_FLUSH_SLEEP_RANGE); -+ fsleep(PLPKS_FLUSH_SLEEP); - timeout = timeout + PLPKS_FLUSH_SLEEP; - } while (timeout < PLPKS_MAX_TIMEOUT); - -@@ -464,9 +463,10 @@ int plpks_signed_update_var(struct plpks_var *var, u64 flags) - - continuetoken = retbuf[0]; - if (pseries_status_to_err(rc) == -EBUSY) { -- int delay_ms = get_longbusy_msecs(rc); -- mdelay(delay_ms); -- timeout += delay_ms; -+ int delay_us = get_longbusy_msecs(rc) * 1000; -+ -+ fsleep(delay_us); -+ timeout += delay_us; - } - rc = pseries_status_to_err(rc); - } while (rc == -EBUSY && timeout < PLPKS_MAX_TIMEOUT); -diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c -index 8581693e62d39..b3990874e4818 100644 ---- a/arch/riscv/net/bpf_jit_comp64.c -+++ b/arch/riscv/net/bpf_jit_comp64.c -@@ -740,6 +740,9 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of - if (ret) - return ret; - -+ /* store prog start time */ -+ emit_mv(RV_REG_S1, RV_REG_A0, ctx); -+ - /* if (__bpf_prog_enter(prog) == 0) - * goto skip_exec_of_prog; - */ -@@ -747,9 +750,6 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of - /* nop reserved for conditional jump */ - emit(rv_nop(), ctx); - -- /* store prog start time */ -- emit_mv(RV_REG_S1, RV_REG_A0, ctx); -- - /* arg1: &args_off */ - emit_addi(RV_REG_A0, RV_REG_FP, -args_off, ctx); - if (!p->jited) -diff --git a/arch/s390/include/asm/dwarf.h b/arch/s390/include/asm/dwarf.h -index 4f21ae561e4dd..390906b8e386e 100644 ---- a/arch/s390/include/asm/dwarf.h -+++ b/arch/s390/include/asm/dwarf.h -@@ -9,6 +9,7 @@ - #define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset - #define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset - #define CFI_RESTORE .cfi_restore -+#define CFI_REL_OFFSET .cfi_rel_offset - - #ifdef CONFIG_AS_CFI_VAL_OFFSET - #define CFI_VAL_OFFSET .cfi_val_offset -diff --git a/arch/s390/kernel/vdso64/vdso_user_wrapper.S b/arch/s390/kernel/vdso64/vdso_user_wrapper.S -index 57f62596e53b9..85247ef5a41b8 100644 ---- a/arch/s390/kernel/vdso64/vdso_user_wrapper.S -+++ b/arch/s390/kernel/vdso64/vdso_user_wrapper.S -@@ -24,8 +24,10 @@ __kernel_\func: - CFI_DEF_CFA_OFFSET (STACK_FRAME_OVERHEAD + WRAPPER_FRAME_SIZE) - CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD - stg %r14,STACK_FRAME_OVERHEAD(%r15) -+ CFI_REL_OFFSET 14, STACK_FRAME_OVERHEAD - brasl %r14,__s390_vdso_\func - lg %r14,STACK_FRAME_OVERHEAD(%r15) -+ CFI_RESTORE 14 - aghi %r15,WRAPPER_FRAME_SIZE - CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD - CFI_RESTORE 15 -diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c -index d17bb1ef63f41..0da54dc9430a9 100644 ---- a/arch/s390/mm/gmap.c -+++ b/arch/s390/mm/gmap.c -@@ -2659,7 +2659,7 @@ static int __s390_enable_skey_hugetlb(pte_t *pte, unsigned long addr, - return 0; - - start = pmd_val(*pmd) & HPAGE_MASK; -- end = start + HPAGE_SIZE - 1; -+ end = start + HPAGE_SIZE; - __storage_key_init_range(start, end); - set_bit(PG_arch_1, &page->flags); - cond_resched(); -diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c -index 5f64f3d0fafbb..763469e518eec 100644 ---- a/arch/s390/mm/hugetlbpage.c -+++ b/arch/s390/mm/hugetlbpage.c -@@ -139,7 +139,7 @@ static void clear_huge_pte_skeys(struct mm_struct *mm, unsigned long rste) - } - - if (!test_and_set_bit(PG_arch_1, &page->flags)) -- __storage_key_init_range(paddr, paddr + size - 1); -+ __storage_key_init_range(paddr, paddr + size); - } - - void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr, -diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c -index ab88a27ff433f..06d5a7eeee81a 100644 ---- a/arch/x86/kernel/apic/apic.c -+++ b/arch/x86/kernel/apic/apic.c -@@ -1808,7 +1808,7 @@ void x2apic_setup(void) - __x2apic_enable(); - } - --static __init void apic_set_fixmap(void); -+static __init void apic_set_fixmap(bool read_apic); - - static __init void x2apic_disable(void) - { -@@ -1830,7 +1830,12 @@ static __init void x2apic_disable(void) - } - - __x2apic_disable(); -- apic_set_fixmap(); -+ /* -+ * Don't reread the APIC ID as it was already done from -+ * check_x2apic() and the APIC driver still is a x2APIC variant, -+ * which fails to do the read after x2APIC was disabled. -+ */ -+ apic_set_fixmap(false); - } - - static __init void x2apic_enable(void) -@@ -2095,13 +2100,14 @@ void __init init_apic_mappings(void) - } - } - --static __init void apic_set_fixmap(void) -+static __init void apic_set_fixmap(bool read_apic) - { - set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); - apic_mmio_base = APIC_BASE; - apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", - apic_mmio_base, mp_lapic_addr); -- apic_read_boot_cpu_id(false); -+ if (read_apic) -+ apic_read_boot_cpu_id(false); - } - - void __init register_lapic_address(unsigned long address) -@@ -2111,7 +2117,7 @@ void __init register_lapic_address(unsigned long address) - mp_lapic_addr = address; - - if (!x2apic_mode) -- apic_set_fixmap(); -+ apic_set_fixmap(true); - } - - /* -diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h -index d008a153a2b9f..7ed1a2085bd72 100644 ---- a/arch/xtensa/include/asm/processor.h -+++ b/arch/xtensa/include/asm/processor.h -@@ -115,9 +115,9 @@ - #define MAKE_RA_FOR_CALL(ra,ws) (((ra) & 0x3fffffff) | (ws) << 30) - - /* Convert return address to a valid pc -- * Note: We assume that the stack pointer is in the same 1GB ranges as the ra -+ * Note: 'text' is the address within the same 1GB range as the ra - */ --#define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000)) -+#define MAKE_PC_FROM_RA(ra, text) (((ra) & 0x3fffffff) | ((unsigned long)(text) & 0xc0000000)) - - #elif defined(__XTENSA_CALL0_ABI__) - -@@ -127,9 +127,9 @@ - #define MAKE_RA_FOR_CALL(ra, ws) (ra) - - /* Convert return address to a valid pc -- * Note: We assume that the stack pointer is in the same 1GB ranges as the ra -+ * Note: 'text' is not used as 'ra' is always the full address - */ --#define MAKE_PC_FROM_RA(ra, sp) (ra) -+#define MAKE_PC_FROM_RA(ra, text) (ra) - - #else - #error Unsupported Xtensa ABI -diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h -index a270467556dc8..86c70117371bb 100644 ---- a/arch/xtensa/include/asm/ptrace.h -+++ b/arch/xtensa/include/asm/ptrace.h -@@ -87,7 +87,7 @@ struct pt_regs { - # define user_mode(regs) (((regs)->ps & 0x00000020)!=0) - # define instruction_pointer(regs) ((regs)->pc) - # define return_pointer(regs) (MAKE_PC_FROM_RA((regs)->areg[0], \ -- (regs)->areg[1])) -+ (regs)->pc)) - - # ifndef CONFIG_SMP - # define profile_pc(regs) instruction_pointer(regs) -diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c -index a815577d25fd0..7bd66677f7b6d 100644 ---- a/arch/xtensa/kernel/process.c -+++ b/arch/xtensa/kernel/process.c -@@ -47,6 +47,7 @@ - #include - #include - #include -+#include - #include - - extern void ret_from_fork(void); -@@ -380,7 +381,7 @@ unsigned long __get_wchan(struct task_struct *p) - int count = 0; - - sp = p->thread.sp; -- pc = MAKE_PC_FROM_RA(p->thread.ra, p->thread.sp); -+ pc = MAKE_PC_FROM_RA(p->thread.ra, _text); - - do { - if (sp < stack_page + sizeof(struct task_struct) || -@@ -392,7 +393,7 @@ unsigned long __get_wchan(struct task_struct *p) - - /* Stack layout: sp-4: ra, sp-3: sp' */ - -- pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), sp); -+ pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), _text); - sp = SPILL_SLOT(sp, 1); - } while (count++ < 16); - return 0; -diff --git a/arch/xtensa/kernel/stacktrace.c b/arch/xtensa/kernel/stacktrace.c -index 831ffb648bda7..ed324fdf2a2f9 100644 ---- a/arch/xtensa/kernel/stacktrace.c -+++ b/arch/xtensa/kernel/stacktrace.c -@@ -13,6 +13,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -189,7 +190,7 @@ void walk_stackframe(unsigned long *sp, - if (a1 <= (unsigned long)sp) - break; - -- frame.pc = MAKE_PC_FROM_RA(a0, a1); -+ frame.pc = MAKE_PC_FROM_RA(a0, _text); - frame.sp = a1; - - if (fn(&frame, data)) -diff --git a/block/blk-iocost.c b/block/blk-iocost.c -index 7ee8d85c2c68d..0dca77591d66c 100644 ---- a/block/blk-iocost.c -+++ b/block/blk-iocost.c -@@ -1347,7 +1347,7 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now) - { - struct ioc *ioc = iocg->ioc; - struct blkcg_gq *blkg = iocg_to_blkg(iocg); -- u64 tdelta, delay, new_delay; -+ u64 tdelta, delay, new_delay, shift; - s64 vover, vover_pct; - u32 hwa; - -@@ -1362,8 +1362,9 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now) - - /* calculate the current delay in effect - 1/2 every second */ - tdelta = now->now - iocg->delay_at; -- if (iocg->delay) -- delay = iocg->delay >> div64_u64(tdelta, USEC_PER_SEC); -+ shift = div64_u64(tdelta, USEC_PER_SEC); -+ if (iocg->delay && shift < BITS_PER_LONG) -+ delay = iocg->delay >> shift; - else - delay = 0; - -@@ -1438,8 +1439,11 @@ static void iocg_pay_debt(struct ioc_gq *iocg, u64 abs_vpay, - lockdep_assert_held(&iocg->ioc->lock); - lockdep_assert_held(&iocg->waitq.lock); - -- /* make sure that nobody messed with @iocg */ -- WARN_ON_ONCE(list_empty(&iocg->active_list)); -+ /* -+ * make sure that nobody messed with @iocg. Check iocg->pd.online -+ * to avoid warn when removing blkcg or disk. -+ */ -+ WARN_ON_ONCE(list_empty(&iocg->active_list) && iocg->pd.online); - WARN_ON_ONCE(iocg->inuse > 1); - - iocg->abs_vdebt -= min(abs_vpay, iocg->abs_vdebt); -diff --git a/block/ioctl.c b/block/ioctl.c -index d1d8e8391279a..68265f914c27b 100644 ---- a/block/ioctl.c -+++ b/block/ioctl.c -@@ -89,7 +89,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, - unsigned long arg) - { - uint64_t range[2]; -- uint64_t start, len; -+ uint64_t start, len, end; - struct inode *inode = bdev->bd_inode; - int err; - -@@ -110,7 +110,8 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, - if (len & 511) - return -EINVAL; - -- if (start + len > bdev_nr_bytes(bdev)) -+ if (check_add_overflow(start, len, &end) || -+ end > bdev_nr_bytes(bdev)) - return -EINVAL; - - filemap_invalidate_lock(inode->i_mapping); -diff --git a/drivers/ata/sata_gemini.c b/drivers/ata/sata_gemini.c -index 400b22ee99c33..4c270999ba3cc 100644 ---- a/drivers/ata/sata_gemini.c -+++ b/drivers/ata/sata_gemini.c -@@ -200,7 +200,10 @@ int gemini_sata_start_bridge(struct sata_gemini *sg, unsigned int bridge) - pclk = sg->sata0_pclk; - else - pclk = sg->sata1_pclk; -- clk_enable(pclk); -+ ret = clk_enable(pclk); -+ if (ret) -+ return ret; -+ - msleep(10); - - /* Do not keep clocking a bridge that is not online */ -diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c -index ea61577471994..c5b5241891a5a 100644 ---- a/drivers/base/regmap/regmap.c -+++ b/drivers/base/regmap/regmap.c -@@ -2836,6 +2836,43 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) - } - EXPORT_SYMBOL_GPL(regmap_read); - -+/** -+ * regmap_read_bypassed() - Read a value from a single register direct -+ * from the device, bypassing the cache -+ * -+ * @map: Register map to read from -+ * @reg: Register to be read from -+ * @val: Pointer to store read value -+ * -+ * A value of zero will be returned on success, a negative errno will -+ * be returned in error cases. -+ */ -+int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val) -+{ -+ int ret; -+ bool bypass, cache_only; -+ -+ if (!IS_ALIGNED(reg, map->reg_stride)) -+ return -EINVAL; -+ -+ map->lock(map->lock_arg); -+ -+ bypass = map->cache_bypass; -+ cache_only = map->cache_only; -+ map->cache_bypass = true; -+ map->cache_only = false; -+ -+ ret = _regmap_read(map, reg, val); -+ -+ map->cache_bypass = bypass; -+ map->cache_only = cache_only; -+ -+ map->unlock(map->lock_arg); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(regmap_read_bypassed); -+ - /** - * regmap_raw_read() - Read raw data from the device - * -diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c -index 5277090c6d6d7..638074992c829 100644 ---- a/drivers/bluetooth/btqca.c -+++ b/drivers/bluetooth/btqca.c -@@ -99,7 +99,8 @@ static int qca_read_fw_build_info(struct hci_dev *hdev) - { - struct sk_buff *skb; - struct edl_event_hdr *edl; -- char cmd, build_label[QCA_FW_BUILD_VER_LEN]; -+ char *build_label; -+ char cmd; - int build_lbl_len, err = 0; - - bt_dev_dbg(hdev, "QCA read fw build info"); -@@ -114,6 +115,11 @@ static int qca_read_fw_build_info(struct hci_dev *hdev) - return err; - } - -+ if (skb->len < sizeof(*edl)) { -+ err = -EILSEQ; -+ goto out; -+ } -+ - edl = (struct edl_event_hdr *)(skb->data); - if (!edl) { - bt_dev_err(hdev, "QCA read fw build info with no header"); -@@ -129,14 +135,25 @@ static int qca_read_fw_build_info(struct hci_dev *hdev) - goto out; - } - -+ if (skb->len < sizeof(*edl) + 1) { -+ err = -EILSEQ; -+ goto out; -+ } -+ - build_lbl_len = edl->data[0]; -- if (build_lbl_len <= QCA_FW_BUILD_VER_LEN - 1) { -- memcpy(build_label, edl->data + 1, build_lbl_len); -- *(build_label + build_lbl_len) = '\0'; -+ -+ if (skb->len < sizeof(*edl) + 1 + build_lbl_len) { -+ err = -EILSEQ; -+ goto out; - } - -+ build_label = kstrndup(&edl->data[1], build_lbl_len, GFP_KERNEL); -+ if (!build_label) -+ goto out; -+ - hci_set_fw_info(hdev, "%s", build_label); - -+ kfree(build_label); - out: - kfree_skb(skb); - return err; -@@ -205,6 +222,49 @@ static int qca_send_reset(struct hci_dev *hdev) - return 0; - } - -+static int qca_read_fw_board_id(struct hci_dev *hdev, u16 *bid) -+{ -+ u8 cmd; -+ struct sk_buff *skb; -+ struct edl_event_hdr *edl; -+ int err = 0; -+ -+ cmd = EDL_GET_BID_REQ_CMD; -+ skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN, -+ &cmd, 0, HCI_INIT_TIMEOUT); -+ if (IS_ERR(skb)) { -+ err = PTR_ERR(skb); -+ bt_dev_err(hdev, "Reading QCA board ID failed (%d)", err); -+ return err; -+ } -+ -+ edl = skb_pull_data(skb, sizeof(*edl)); -+ if (!edl) { -+ bt_dev_err(hdev, "QCA read board ID with no header"); -+ err = -EILSEQ; -+ goto out; -+ } -+ -+ if (edl->cresp != EDL_CMD_REQ_RES_EVT || -+ edl->rtype != EDL_GET_BID_REQ_CMD) { -+ bt_dev_err(hdev, "QCA Wrong packet: %d %d", edl->cresp, edl->rtype); -+ err = -EIO; -+ goto out; -+ } -+ -+ if (skb->len < 3) { -+ err = -EILSEQ; -+ goto out; -+ } -+ -+ *bid = (edl->data[1] << 8) + edl->data[2]; -+ bt_dev_dbg(hdev, "%s: bid = %x", __func__, *bid); -+ -+out: -+ kfree_skb(skb); -+ return err; -+} -+ - int qca_send_pre_shutdown_cmd(struct hci_dev *hdev) - { - struct sk_buff *skb; -@@ -227,9 +287,10 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev) - } - EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd); - --static void qca_tlv_check_data(struct hci_dev *hdev, -+static int qca_tlv_check_data(struct hci_dev *hdev, - struct qca_fw_config *config, -- u8 *fw_data, enum qca_btsoc_type soc_type) -+ u8 *fw_data, size_t fw_size, -+ enum qca_btsoc_type soc_type) - { - const u8 *data; - u32 type_len; -@@ -239,12 +300,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev, - struct tlv_type_patch *tlv_patch; - struct tlv_type_nvm *tlv_nvm; - uint8_t nvm_baud_rate = config->user_baud_rate; -+ u8 type; - - config->dnld_mode = QCA_SKIP_EVT_NONE; - config->dnld_type = QCA_SKIP_EVT_NONE; - - switch (config->type) { - case ELF_TYPE_PATCH: -+ if (fw_size < 7) -+ return -EINVAL; -+ - config->dnld_mode = QCA_SKIP_EVT_VSE_CC; - config->dnld_type = QCA_SKIP_EVT_VSE_CC; - -@@ -253,6 +318,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev, - bt_dev_dbg(hdev, "File version : 0x%x", fw_data[6]); - break; - case TLV_TYPE_PATCH: -+ if (fw_size < sizeof(struct tlv_type_hdr) + sizeof(struct tlv_type_patch)) -+ return -EINVAL; -+ - tlv = (struct tlv_type_hdr *)fw_data; - type_len = le32_to_cpu(tlv->type_len); - tlv_patch = (struct tlv_type_patch *)tlv->data; -@@ -292,25 +360,64 @@ static void qca_tlv_check_data(struct hci_dev *hdev, - break; - - case TLV_TYPE_NVM: -+ if (fw_size < sizeof(struct tlv_type_hdr)) -+ return -EINVAL; -+ - tlv = (struct tlv_type_hdr *)fw_data; - - type_len = le32_to_cpu(tlv->type_len); -- length = (type_len >> 8) & 0x00ffffff; -+ length = type_len >> 8; -+ type = type_len & 0xff; - -- BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x000000ff); -+ /* Some NVM files have more than one set of tags, only parse -+ * the first set when it has type 2 for now. When there is -+ * more than one set there is an enclosing header of type 4. -+ */ -+ if (type == 4) { -+ if (fw_size < 2 * sizeof(struct tlv_type_hdr)) -+ return -EINVAL; -+ -+ tlv++; -+ -+ type_len = le32_to_cpu(tlv->type_len); -+ length = type_len >> 8; -+ type = type_len & 0xff; -+ } -+ -+ BT_DBG("TLV Type\t\t : 0x%x", type); - BT_DBG("Length\t\t : %d bytes", length); - -+ if (type != 2) -+ break; -+ -+ if (fw_size < length + (tlv->data - fw_data)) -+ return -EINVAL; -+ - idx = 0; - data = tlv->data; -- while (idx < length) { -+ while (idx < length - sizeof(struct tlv_type_nvm)) { - tlv_nvm = (struct tlv_type_nvm *)(data + idx); - - tag_id = le16_to_cpu(tlv_nvm->tag_id); - tag_len = le16_to_cpu(tlv_nvm->tag_len); - -+ if (length < idx + sizeof(struct tlv_type_nvm) + tag_len) -+ return -EINVAL; -+ - /* Update NVM tags as needed */ - switch (tag_id) { -+ case EDL_TAG_ID_BD_ADDR: -+ if (tag_len != sizeof(bdaddr_t)) -+ return -EINVAL; -+ -+ memcpy(&config->bdaddr, tlv_nvm->data, sizeof(bdaddr_t)); -+ -+ break; -+ - case EDL_TAG_ID_HCI: -+ if (tag_len < 3) -+ return -EINVAL; -+ - /* HCI transport layer parameters - * enabling software inband sleep - * onto controller side. -@@ -326,6 +433,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev, - break; - - case EDL_TAG_ID_DEEP_SLEEP: -+ if (tag_len < 1) -+ return -EINVAL; -+ - /* Sleep enable mask - * enabling deep sleep feature on controller. - */ -@@ -334,14 +444,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev, - break; - } - -- idx += (sizeof(u16) + sizeof(u16) + 8 + tag_len); -+ idx += sizeof(struct tlv_type_nvm) + tag_len; - } - break; - - default: - BT_ERR("Unknown TLV type %d", config->type); -- break; -+ return -EINVAL; - } -+ -+ return 0; - } - - static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size, -@@ -491,7 +603,9 @@ static int qca_download_firmware(struct hci_dev *hdev, - memcpy(data, fw->data, size); - release_firmware(fw); - -- qca_tlv_check_data(hdev, config, data, soc_type); -+ ret = qca_tlv_check_data(hdev, config, data, size, soc_type); -+ if (ret) -+ goto out; - - segment = data; - remain = size; -@@ -574,14 +688,64 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr) - } - EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome); - -+static int qca_check_bdaddr(struct hci_dev *hdev, const struct qca_fw_config *config) -+{ -+ struct hci_rp_read_bd_addr *bda; -+ struct sk_buff *skb; -+ int err; -+ -+ if (bacmp(&hdev->public_addr, BDADDR_ANY)) -+ return 0; -+ -+ skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL, -+ HCI_INIT_TIMEOUT); -+ if (IS_ERR(skb)) { -+ err = PTR_ERR(skb); -+ bt_dev_err(hdev, "Failed to read device address (%d)", err); -+ return err; -+ } -+ -+ if (skb->len != sizeof(*bda)) { -+ bt_dev_err(hdev, "Device address length mismatch"); -+ kfree_skb(skb); -+ return -EIO; -+ } -+ -+ bda = (struct hci_rp_read_bd_addr *)skb->data; -+ if (!bacmp(&bda->bdaddr, &config->bdaddr)) -+ set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); -+ -+ kfree_skb(skb); -+ -+ return 0; -+} -+ -+static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size, -+ struct qca_btsoc_version ver, u8 rom_ver, u16 bid) -+{ -+ const char *variant; -+ -+ /* hsp gf chip */ -+ if ((le32_to_cpu(ver.soc_id) & QCA_HSP_GF_SOC_MASK) == QCA_HSP_GF_SOC_ID) -+ variant = "g"; -+ else -+ variant = ""; -+ -+ if (bid == 0x0) -+ snprintf(fwname, max_size, "qca/hpnv%02x%s.bin", rom_ver, variant); -+ else -+ snprintf(fwname, max_size, "qca/hpnv%02x%s.%x", rom_ver, variant, bid); -+} -+ - int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, - enum qca_btsoc_type soc_type, struct qca_btsoc_version ver, - const char *firmware_name) - { -- struct qca_fw_config config; -+ struct qca_fw_config config = {}; - int err; - u8 rom_ver = 0; - u32 soc_ver; -+ u16 boardid = 0; - - bt_dev_dbg(hdev, "QCA setup on UART"); - -@@ -615,6 +779,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, - snprintf(config.fwname, sizeof(config.fwname), - "qca/apbtfw%02x.tlv", rom_ver); - break; -+ case QCA_QCA2066: -+ snprintf(config.fwname, sizeof(config.fwname), -+ "qca/hpbtfw%02x.tlv", rom_ver); -+ break; - case QCA_QCA6390: - snprintf(config.fwname, sizeof(config.fwname), - "qca/htbtfw%02x.tlv", rom_ver); -@@ -649,6 +817,9 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, - /* Give the controller some time to get ready to receive the NVM */ - msleep(10); - -+ if (soc_type == QCA_QCA2066) -+ qca_read_fw_board_id(hdev, &boardid); -+ - /* Download NVM configuration */ - config.type = TLV_TYPE_NVM; - if (firmware_name) { -@@ -671,6 +842,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, - snprintf(config.fwname, sizeof(config.fwname), - "qca/apnv%02x.bin", rom_ver); - break; -+ case QCA_QCA2066: -+ qca_generate_hsp_nvm_name(config.fwname, -+ sizeof(config.fwname), ver, rom_ver, boardid); -+ break; - case QCA_QCA6390: - snprintf(config.fwname, sizeof(config.fwname), - "qca/htnv%02x.bin", rom_ver); -@@ -702,6 +877,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, - - switch (soc_type) { - case QCA_WCN3991: -+ case QCA_QCA2066: - case QCA_QCA6390: - case QCA_WCN6750: - case QCA_WCN6855: -@@ -750,6 +926,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, - break; - } - -+ err = qca_check_bdaddr(hdev, &config); -+ if (err) -+ return err; -+ - bt_dev_info(hdev, "QCA setup on UART is completed"); - - return 0; -diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h -index 03bff5c0059de..215433fd76a10 100644 ---- a/drivers/bluetooth/btqca.h -+++ b/drivers/bluetooth/btqca.h -@@ -12,6 +12,7 @@ - #define EDL_PATCH_VER_REQ_CMD (0x19) - #define EDL_PATCH_TLV_REQ_CMD (0x1E) - #define EDL_GET_BUILD_INFO_CMD (0x20) -+#define EDL_GET_BID_REQ_CMD (0x23) - #define EDL_NVM_ACCESS_SET_REQ_CMD (0x01) - #define EDL_PATCH_CONFIG_CMD (0x28) - #define MAX_SIZE_PER_TLV_SEGMENT (243) -@@ -28,6 +29,7 @@ - #define EDL_PATCH_CONFIG_RES_EVT (0x00) - #define QCA_DISABLE_LOGGING_SUB_OP (0x14) - -+#define EDL_TAG_ID_BD_ADDR 2 - #define EDL_TAG_ID_HCI (17) - #define EDL_TAG_ID_DEEP_SLEEP (27) - -@@ -46,8 +48,8 @@ - #define get_soc_ver(soc_id, rom_ver) \ - ((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver))) - --#define QCA_FW_BUILD_VER_LEN 255 -- -+#define QCA_HSP_GF_SOC_ID 0x1200 -+#define QCA_HSP_GF_SOC_MASK 0x0000ff00 - - enum qca_baudrate { - QCA_BAUDRATE_115200 = 0, -@@ -92,6 +94,7 @@ struct qca_fw_config { - uint8_t user_baud_rate; - enum qca_tlv_dnld_mode dnld_mode; - enum qca_tlv_dnld_mode dnld_type; -+ bdaddr_t bdaddr; - }; - - struct edl_event_hdr { -@@ -146,6 +149,7 @@ enum qca_btsoc_type { - QCA_WCN3990, - QCA_WCN3998, - QCA_WCN3991, -+ QCA_QCA2066, - QCA_QCA6390, - QCA_WCN6750, - QCA_WCN6855, -diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c -index 410f146e3f671..92341a87a5da7 100644 ---- a/drivers/bluetooth/hci_qca.c -+++ b/drivers/bluetooth/hci_qca.c -@@ -1845,6 +1845,10 @@ static int qca_setup(struct hci_uart *hu) - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); - - switch (soc_type) { -+ case QCA_QCA2066: -+ soc_name = "qca2066"; -+ break; -+ - case QCA_WCN3988: - case QCA_WCN3990: - case QCA_WCN3991: -@@ -1886,8 +1890,6 @@ static int qca_setup(struct hci_uart *hu) - case QCA_WCN6750: - case QCA_WCN6855: - case QCA_WCN7850: -- set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); -- - qcadev = serdev_device_get_drvdata(hu->serdev); - if (qcadev->bdaddr_property_broken) - set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks); -@@ -2043,6 +2045,11 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = { - .num_vregs = 4, - }; - -+static const struct qca_device_data qca_soc_data_qca2066 __maybe_unused = { -+ .soc_type = QCA_QCA2066, -+ .num_vregs = 0, -+}; -+ - static const struct qca_device_data qca_soc_data_qca6390 __maybe_unused = { - .soc_type = QCA_QCA6390, - .num_vregs = 0, -@@ -2582,6 +2589,7 @@ static SIMPLE_DEV_PM_OPS(qca_pm_ops, qca_suspend, qca_resume); - - #ifdef CONFIG_OF - static const struct of_device_id qca_bluetooth_of_match[] = { -+ { .compatible = "qcom,qca2066-bt", .data = &qca_soc_data_qca2066}, - { .compatible = "qcom,qca6174-bt" }, - { .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390}, - { .compatible = "qcom,qca9377-bt" }, -@@ -2599,6 +2607,7 @@ MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); - - #ifdef CONFIG_ACPI - static const struct acpi_device_id qca_bluetooth_acpi_match[] = { -+ { "QCOM2066", (kernel_ulong_t)&qca_soc_data_qca2066 }, - { "QCOM6390", (kernel_ulong_t)&qca_soc_data_qca6390 }, - { "DLA16390", (kernel_ulong_t)&qca_soc_data_qca6390 }, - { "DLB16390", (kernel_ulong_t)&qca_soc_data_qca6390 }, -diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c -index 4a67c0d4823cf..f8776065ad1f1 100644 ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -4523,7 +4523,8 @@ void clk_unregister(struct clk *clk) - if (ops == &clk_nodrv_ops) { - pr_err("%s: unregistered clock: %s\n", __func__, - clk->core->name); -- goto unlock; -+ clk_prepare_unlock(); -+ return; - } - /* - * Assign empty clock ops for consumers that might still hold -@@ -4557,11 +4558,10 @@ void clk_unregister(struct clk *clk) - if (clk->core->protect_count) - pr_warn("%s: unregistering protected clock: %s\n", - __func__, clk->core->name); -+ clk_prepare_unlock(); - - kref_put(&clk->core->ref, __clk_release); - free_clk(clk); --unlock: -- clk_prepare_unlock(); - } - EXPORT_SYMBOL_GPL(clk_unregister); - -@@ -4720,13 +4720,11 @@ void __clk_put(struct clk *clk) - if (clk->min_rate > 0 || clk->max_rate < ULONG_MAX) - clk_set_rate_range_nolock(clk, 0, ULONG_MAX); - -- owner = clk->core->owner; -- kref_put(&clk->core->ref, __clk_release); -- - clk_prepare_unlock(); - -+ owner = clk->core->owner; -+ kref_put(&clk->core->ref, __clk_release); - module_put(owner); -- - free_clk(clk); - } - -diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c -index 0191fc0dd7dac..789903a1b3f2b 100644 ---- a/drivers/clk/qcom/clk-smd-rpm.c -+++ b/drivers/clk/qcom/clk-smd-rpm.c -@@ -758,6 +758,7 @@ static struct clk_smd_rpm *msm8976_clks[] = { - - static const struct rpm_smd_clk_desc rpm_clk_msm8976 = { - .clks = msm8976_clks, -+ .num_clks = ARRAY_SIZE(msm8976_clks), - .icc_clks = bimc_pcnoc_snoc_smmnoc_icc_clks, - .num_icc_clks = ARRAY_SIZE(bimc_pcnoc_snoc_smmnoc_icc_clks), - }; -diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c -index 8951ffc14ff52..6a4b2b9ef30a8 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c -+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c -@@ -182,6 +182,8 @@ static struct ccu_nkm pll_mipi_clk = { - &ccu_nkm_ops, - CLK_SET_RATE_UNGATE | CLK_SET_RATE_PARENT), - .features = CCU_FEATURE_CLOSEST_RATE, -+ .min_rate = 500000000, -+ .max_rate = 1400000000, - }, - }; - -diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c -index 42568c6161814..892df807275c8 100644 ---- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c -+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c -@@ -1181,11 +1181,18 @@ static const u32 usb2_clk_regs[] = { - SUN50I_H6_USB3_CLK_REG, - }; - -+static struct ccu_mux_nb sun50i_h6_cpu_nb = { -+ .common = &cpux_clk.common, -+ .cm = &cpux_clk.mux, -+ .delay_us = 1, -+ .bypass_index = 0, /* index of 24 MHz oscillator */ -+}; -+ - static int sun50i_h6_ccu_probe(struct platform_device *pdev) - { - void __iomem *reg; -+ int i, ret; - u32 val; -- int i; - - reg = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(reg)) -@@ -1252,7 +1259,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev) - val |= BIT(24); - writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG); - -- return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc); -+ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc); -+ if (ret) -+ return ret; -+ -+ /* Reparent CPU during PLL CPUX rate changes */ -+ ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, -+ &sun50i_h6_cpu_nb); -+ -+ return 0; - } - - static const struct of_device_id sun50i_h6_ccu_ids[] = { -diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c -index 8babce55302f5..ac0091b4ce242 100644 ---- a/drivers/clk/sunxi-ng/ccu_common.c -+++ b/drivers/clk/sunxi-ng/ccu_common.c -@@ -44,6 +44,16 @@ bool ccu_is_better_rate(struct ccu_common *common, - unsigned long current_rate, - unsigned long best_rate) - { -+ unsigned long min_rate, max_rate; -+ -+ clk_hw_get_rate_range(&common->hw, &min_rate, &max_rate); -+ -+ if (current_rate > max_rate) -+ return false; -+ -+ if (current_rate < min_rate) -+ return false; -+ - if (common->features & CCU_FEATURE_CLOSEST_RATE) - return abs(current_rate - target_rate) < abs(best_rate - target_rate); - -@@ -122,6 +132,7 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, - - for (i = 0; i < desc->hw_clks->num ; i++) { - struct clk_hw *hw = desc->hw_clks->hws[i]; -+ struct ccu_common *common = hw_to_ccu_common(hw); - const char *name; - - if (!hw) -@@ -136,6 +147,14 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, - pr_err("Couldn't register clock %d - %s\n", i, name); - goto err_clk_unreg; - } -+ -+ if (common->max_rate) -+ clk_hw_set_rate_range(hw, common->min_rate, -+ common->max_rate); -+ else -+ WARN(common->min_rate, -+ "No max_rate, ignoring min_rate of clock %d - %s\n", -+ i, name); - } - - ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, -diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h -index 942a72c094374..329734f8cf42b 100644 ---- a/drivers/clk/sunxi-ng/ccu_common.h -+++ b/drivers/clk/sunxi-ng/ccu_common.h -@@ -31,6 +31,9 @@ struct ccu_common { - u16 lock_reg; - u32 prediv; - -+ unsigned long min_rate; -+ unsigned long max_rate; -+ - unsigned long features; - spinlock_t *lock; - struct clk_hw hw; -diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c -index ad7b55dd9596d..26f1dedc92d38 100644 ---- a/drivers/dma/idxd/cdev.c -+++ b/drivers/dma/idxd/cdev.c -@@ -400,6 +400,18 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma) - int rc; - - dev_dbg(&pdev->dev, "%s called\n", __func__); -+ -+ /* -+ * Due to an erratum in some of the devices supported by the driver, -+ * direct user submission to the device can be unsafe. -+ * (See the INTEL-SA-01084 security advisory) -+ * -+ * For the devices that exhibit this behavior, require that the user -+ * has CAP_SYS_RAWIO capabilities. -+ */ -+ if (!idxd->user_submission_safe && !capable(CAP_SYS_RAWIO)) -+ return -EPERM; -+ - rc = check_vma(wq, vma, __func__); - if (rc < 0) - return rc; -@@ -414,6 +426,70 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma) - vma->vm_page_prot); - } - -+static int idxd_submit_user_descriptor(struct idxd_user_context *ctx, -+ struct dsa_hw_desc __user *udesc) -+{ -+ struct idxd_wq *wq = ctx->wq; -+ struct idxd_dev *idxd_dev = &wq->idxd->idxd_dev; -+ const uint64_t comp_addr_align = is_dsa_dev(idxd_dev) ? 0x20 : 0x40; -+ void __iomem *portal = idxd_wq_portal_addr(wq); -+ struct dsa_hw_desc descriptor __aligned(64); -+ int rc; -+ -+ rc = copy_from_user(&descriptor, udesc, sizeof(descriptor)); -+ if (rc) -+ return -EFAULT; -+ -+ /* -+ * DSA devices are capable of indirect ("batch") command submission. -+ * On devices where direct user submissions are not safe, we cannot -+ * allow this since there is no good way for us to verify these -+ * indirect commands. -+ */ -+ if (is_dsa_dev(idxd_dev) && descriptor.opcode == DSA_OPCODE_BATCH && -+ !wq->idxd->user_submission_safe) -+ return -EINVAL; -+ /* -+ * As per the programming specification, the completion address must be -+ * aligned to 32 or 64 bytes. If this is violated the hardware -+ * engine can get very confused (security issue). -+ */ -+ if (!IS_ALIGNED(descriptor.completion_addr, comp_addr_align)) -+ return -EINVAL; -+ -+ if (wq_dedicated(wq)) -+ iosubmit_cmds512(portal, &descriptor, 1); -+ else { -+ descriptor.priv = 0; -+ descriptor.pasid = ctx->pasid; -+ rc = idxd_enqcmds(wq, portal, &descriptor); -+ if (rc < 0) -+ return rc; -+ } -+ -+ return 0; -+} -+ -+static ssize_t idxd_cdev_write(struct file *filp, const char __user *buf, size_t len, -+ loff_t *unused) -+{ -+ struct dsa_hw_desc __user *udesc = (struct dsa_hw_desc __user *)buf; -+ struct idxd_user_context *ctx = filp->private_data; -+ ssize_t written = 0; -+ int i; -+ -+ for (i = 0; i < len/sizeof(struct dsa_hw_desc); i++) { -+ int rc = idxd_submit_user_descriptor(ctx, udesc + i); -+ -+ if (rc) -+ return written ? written : rc; -+ -+ written += sizeof(struct dsa_hw_desc); -+ } -+ -+ return written; -+} -+ - static __poll_t idxd_cdev_poll(struct file *filp, - struct poll_table_struct *wait) - { -@@ -436,6 +512,7 @@ static const struct file_operations idxd_cdev_fops = { - .open = idxd_cdev_open, - .release = idxd_cdev_release, - .mmap = idxd_cdev_mmap, -+ .write = idxd_cdev_write, - .poll = idxd_cdev_poll, - }; - -diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h -index df62dd1291189..bea10c5cdb76b 100644 ---- a/drivers/dma/idxd/idxd.h -+++ b/drivers/dma/idxd/idxd.h -@@ -275,6 +275,7 @@ struct idxd_driver_data { - int evl_cr_off; - int cr_status_off; - int cr_result_off; -+ bool user_submission_safe; - }; - - struct idxd_evl { -@@ -360,6 +361,8 @@ struct idxd_device { - - struct dentry *dbgfs_dir; - struct dentry *dbgfs_evl_file; -+ -+ bool user_submission_safe; - }; - - static inline unsigned int evl_ent_size(struct idxd_device *idxd) -diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c -index 2e323c9b2068d..786afb256b6e0 100644 ---- a/drivers/dma/idxd/init.c -+++ b/drivers/dma/idxd/init.c -@@ -47,6 +47,7 @@ static struct idxd_driver_data idxd_driver_data[] = { - .align = 32, - .dev_type = &dsa_device_type, - .evl_cr_off = offsetof(struct dsa_evl_entry, cr), -+ .user_submission_safe = false, /* See INTEL-SA-01084 security advisory */ - .cr_status_off = offsetof(struct dsa_completion_record, status), - .cr_result_off = offsetof(struct dsa_completion_record, result), - }, -@@ -57,6 +58,7 @@ static struct idxd_driver_data idxd_driver_data[] = { - .align = 64, - .dev_type = &iax_device_type, - .evl_cr_off = offsetof(struct iax_evl_entry, cr), -+ .user_submission_safe = false, /* See INTEL-SA-01084 security advisory */ - .cr_status_off = offsetof(struct iax_completion_record, status), - .cr_result_off = offsetof(struct iax_completion_record, error_code), - }, -@@ -767,6 +769,8 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) - dev_info(&pdev->dev, "Intel(R) Accelerator Device (v%x)\n", - idxd->hw.version); - -+ idxd->user_submission_safe = data->user_submission_safe; -+ - return 0; - - err_dev_register: -diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h -index 7b54a3939ea13..cfbcd1adb1d1c 100644 ---- a/drivers/dma/idxd/registers.h -+++ b/drivers/dma/idxd/registers.h -@@ -6,9 +6,6 @@ - #include - - /* PCI Config */ --#define PCI_DEVICE_ID_INTEL_DSA_SPR0 0x0b25 --#define PCI_DEVICE_ID_INTEL_IAX_SPR0 0x0cfe -- - #define DEVICE_VERSION_1 0x100 - #define DEVICE_VERSION_2 0x200 - -diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c -index 7caba90d85b31..1fd5a93045f79 100644 ---- a/drivers/dma/idxd/sysfs.c -+++ b/drivers/dma/idxd/sysfs.c -@@ -1197,12 +1197,35 @@ static ssize_t wq_enqcmds_retries_store(struct device *dev, struct device_attrib - static struct device_attribute dev_attr_wq_enqcmds_retries = - __ATTR(enqcmds_retries, 0644, wq_enqcmds_retries_show, wq_enqcmds_retries_store); - -+static ssize_t op_cap_show_common(struct device *dev, char *buf, unsigned long *opcap_bmap) -+{ -+ ssize_t pos; -+ int i; -+ -+ pos = 0; -+ for (i = IDXD_MAX_OPCAP_BITS/64 - 1; i >= 0; i--) { -+ unsigned long val = opcap_bmap[i]; -+ -+ /* On systems where direct user submissions are not safe, we need to clear out -+ * the BATCH capability from the capability mask in sysfs since we cannot support -+ * that command on such systems. -+ */ -+ if (i == DSA_OPCODE_BATCH/64 && !confdev_to_idxd(dev)->user_submission_safe) -+ clear_bit(DSA_OPCODE_BATCH % 64, &val); -+ -+ pos += sysfs_emit_at(buf, pos, "%*pb", 64, &val); -+ pos += sysfs_emit_at(buf, pos, "%c", i == 0 ? '\n' : ','); -+ } -+ -+ return pos; -+} -+ - static ssize_t wq_op_config_show(struct device *dev, - struct device_attribute *attr, char *buf) - { - struct idxd_wq *wq = confdev_to_wq(dev); - -- return sysfs_emit(buf, "%*pb\n", IDXD_MAX_OPCAP_BITS, wq->opcap_bmap); -+ return op_cap_show_common(dev, buf, wq->opcap_bmap); - } - - static int idxd_verify_supported_opcap(struct idxd_device *idxd, unsigned long *opmask) -@@ -1421,7 +1444,7 @@ static ssize_t op_cap_show(struct device *dev, - { - struct idxd_device *idxd = confdev_to_idxd(dev); - -- return sysfs_emit(buf, "%*pb\n", IDXD_MAX_OPCAP_BITS, idxd->opcap_bmap); -+ return op_cap_show_common(dev, buf, idxd->opcap_bmap); - } - static DEVICE_ATTR_RO(op_cap); - -diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c -index b0d671db178a8..ea31ac7ac1ca9 100644 ---- a/drivers/firewire/nosy.c -+++ b/drivers/firewire/nosy.c -@@ -148,10 +148,12 @@ packet_buffer_get(struct client *client, char __user *data, size_t user_length) - if (atomic_read(&buffer->size) == 0) - return -ENODEV; - -- /* FIXME: Check length <= user_length. */ -+ length = buffer->head->length; -+ -+ if (length > user_length) -+ return 0; - - end = buffer->data + buffer->capacity; -- length = buffer->head->length; - - if (&buffer->head->data[length] < end) { - if (copy_to_user(data, buffer->head->data, length)) -diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c -index 7bc71f4be64a0..b9ae0340b8a70 100644 ---- a/drivers/firewire/ohci.c -+++ b/drivers/firewire/ohci.c -@@ -1556,6 +1556,8 @@ static int handle_at_packet(struct context *context, - #define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff) - #define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff) - -+static u32 get_cycle_time(struct fw_ohci *ohci); -+ - static void handle_local_rom(struct fw_ohci *ohci, - struct fw_packet *packet, u32 csr) - { -@@ -1580,6 +1582,8 @@ static void handle_local_rom(struct fw_ohci *ohci, - (void *) ohci->config_rom + i, length); - } - -+ // Timestamping on behalf of the hardware. -+ response.timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci)); - fw_core_handle_response(&ohci->card, &response); - } - -@@ -1628,6 +1632,8 @@ static void handle_local_lock(struct fw_ohci *ohci, - fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0); - - out: -+ // Timestamping on behalf of the hardware. -+ response.timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci)); - fw_core_handle_response(&ohci->card, &response); - } - -@@ -1670,8 +1676,6 @@ static void handle_local_request(struct context *ctx, struct fw_packet *packet) - } - } - --static u32 get_cycle_time(struct fw_ohci *ohci); -- - static void at_context_transmit(struct context *ctx, struct fw_packet *packet) - { - unsigned long flags; -@@ -2060,6 +2064,8 @@ static void bus_reset_work(struct work_struct *work) - - ohci->generation = generation; - reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); -+ if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) -+ reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); - - if (ohci->quirks & QUIRK_RESET_PACKET) - ohci->request_generation = generation; -@@ -2125,12 +2131,14 @@ static irqreturn_t irq_handler(int irq, void *data) - return IRQ_NONE; - - /* -- * busReset and postedWriteErr must not be cleared yet -+ * busReset and postedWriteErr events must not be cleared yet - * (OHCI 1.1 clauses 7.2.3.2 and 13.2.8.1) - */ - reg_write(ohci, OHCI1394_IntEventClear, - event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr)); - log_irqs(ohci, event); -+ if (event & OHCI1394_busReset) -+ reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset); - - if (event & OHCI1394_selfIDComplete) - queue_work(selfid_workqueue, &ohci->bus_reset_work); -diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c -index 1ee62cd58582b..25db014494a4d 100644 ---- a/drivers/gpio/gpio-crystalcove.c -+++ b/drivers/gpio/gpio-crystalcove.c -@@ -92,7 +92,7 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type) - case 0x5e: - return GPIOPANELCTL; - default: -- return -EOPNOTSUPP; -+ return -ENOTSUPP; - } - } - -diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c -index 5ef8af8249806..c097e310c9e84 100644 ---- a/drivers/gpio/gpio-lpc32xx.c -+++ b/drivers/gpio/gpio-lpc32xx.c -@@ -529,6 +529,7 @@ static const struct of_device_id lpc32xx_gpio_of_match[] = { - { .compatible = "nxp,lpc3220-gpio", }, - { }, - }; -+MODULE_DEVICE_TABLE(of, lpc32xx_gpio_of_match); - - static struct platform_driver lpc32xx_gpio_driver = { - .driver = { -diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c -index c18b6b47384f1..94ca9d03c0949 100644 ---- a/drivers/gpio/gpio-wcove.c -+++ b/drivers/gpio/gpio-wcove.c -@@ -104,7 +104,7 @@ static inline int to_reg(int gpio, enum ctrl_register type) - unsigned int reg = type == CTRL_IN ? GPIO_IN_CTRL_BASE : GPIO_OUT_CTRL_BASE; - - if (gpio >= WCOVE_GPIO_NUM) -- return -EOPNOTSUPP; -+ return -ENOTSUPP; - - return reg + gpio; - } -diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c -index 84125e55de101..b4b71e68b90de 100644 ---- a/drivers/gpio/gpiolib-cdev.c -+++ b/drivers/gpio/gpiolib-cdev.c -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -21,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -461,6 +463,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) - - /** - * struct line - contains the state of a requested line -+ * @node: to store the object in supinfo_tree if supplemental - * @desc: the GPIO descriptor for this line. - * @req: the corresponding line request - * @irq: the interrupt triggered in response to events on this GPIO -@@ -473,6 +476,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) - * @line_seqno: the seqno for the current edge event in the sequence of - * events for this line. - * @work: the worker that implements software debouncing -+ * @debounce_period_us: the debounce period in microseconds - * @sw_debounced: flag indicating if the software debouncer is active - * @level: the current debounced physical level of the line - * @hdesc: the Hardware Timestamp Engine (HTE) descriptor -@@ -481,6 +485,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) - * @last_seqno: the last sequence number before debounce period expires - */ - struct line { -+ struct rb_node node; - struct gpio_desc *desc; - /* - * -- edge detector specific fields -- -@@ -514,6 +519,15 @@ struct line { - * -- debouncer specific fields -- - */ - struct delayed_work work; -+ /* -+ * debounce_period_us is accessed by debounce_irq_handler() and -+ * process_hw_ts() which are disabled when modified by -+ * debounce_setup(), edge_detector_setup() or edge_detector_stop() -+ * or can live with a stale version when updated by -+ * edge_detector_update(). -+ * The modifying functions are themselves mutually exclusive. -+ */ -+ unsigned int debounce_period_us; - /* - * sw_debounce is accessed by linereq_set_config(), which is the - * only setter, and linereq_get_values(), which can live with a -@@ -546,6 +560,17 @@ struct line { - #endif /* CONFIG_HTE */ - }; - -+/* -+ * a rbtree of the struct lines containing supplemental info. -+ * Used to populate gpio_v2_line_info with cdev specific fields not contained -+ * in the struct gpio_desc. -+ * A line is determined to contain supplemental information by -+ * line_has_supinfo(). -+ */ -+static struct rb_root supinfo_tree = RB_ROOT; -+/* covers supinfo_tree */ -+static DEFINE_SPINLOCK(supinfo_lock); -+ - /** - * struct linereq - contains the state of a userspace line request - * @gdev: the GPIO device the line request pertains to -@@ -559,7 +584,8 @@ struct line { - * this line request. Note that this is not used when @num_lines is 1, as - * the line_seqno is then the same and is cheaper to calculate. - * @config_mutex: mutex for serializing ioctl() calls to ensure consistency -- * of configuration, particularly multi-step accesses to desc flags. -+ * of configuration, particularly multi-step accesses to desc flags and -+ * changes to supinfo status. - * @lines: the lines held by this line request, with @num_lines elements. - */ - struct linereq { -@@ -575,6 +601,103 @@ struct linereq { - struct line lines[]; - }; - -+static void supinfo_insert(struct line *line) -+{ -+ struct rb_node **new = &(supinfo_tree.rb_node), *parent = NULL; -+ struct line *entry; -+ -+ guard(spinlock)(&supinfo_lock); -+ -+ while (*new) { -+ entry = container_of(*new, struct line, node); -+ -+ parent = *new; -+ if (line->desc < entry->desc) { -+ new = &((*new)->rb_left); -+ } else if (line->desc > entry->desc) { -+ new = &((*new)->rb_right); -+ } else { -+ /* this should never happen */ -+ WARN(1, "duplicate line inserted"); -+ return; -+ } -+ } -+ -+ rb_link_node(&line->node, parent, new); -+ rb_insert_color(&line->node, &supinfo_tree); -+} -+ -+static void supinfo_erase(struct line *line) -+{ -+ guard(spinlock)(&supinfo_lock); -+ -+ rb_erase(&line->node, &supinfo_tree); -+} -+ -+static struct line *supinfo_find(struct gpio_desc *desc) -+{ -+ struct rb_node *node = supinfo_tree.rb_node; -+ struct line *line; -+ -+ while (node) { -+ line = container_of(node, struct line, node); -+ if (desc < line->desc) -+ node = node->rb_left; -+ else if (desc > line->desc) -+ node = node->rb_right; -+ else -+ return line; -+ } -+ return NULL; -+} -+ -+static void supinfo_to_lineinfo(struct gpio_desc *desc, -+ struct gpio_v2_line_info *info) -+{ -+ struct gpio_v2_line_attribute *attr; -+ struct line *line; -+ -+ guard(spinlock)(&supinfo_lock); -+ -+ line = supinfo_find(desc); -+ if (!line) -+ return; -+ -+ attr = &info->attrs[info->num_attrs]; -+ attr->id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE; -+ attr->debounce_period_us = READ_ONCE(line->debounce_period_us); -+ info->num_attrs++; -+} -+ -+static inline bool line_has_supinfo(struct line *line) -+{ -+ return READ_ONCE(line->debounce_period_us); -+} -+ -+/* -+ * Checks line_has_supinfo() before and after the change to avoid unnecessary -+ * supinfo_tree access. -+ * Called indirectly by linereq_create() or linereq_set_config() so line -+ * is already protected from concurrent changes. -+ */ -+static void line_set_debounce_period(struct line *line, -+ unsigned int debounce_period_us) -+{ -+ bool was_suppl = line_has_supinfo(line); -+ -+ WRITE_ONCE(line->debounce_period_us, debounce_period_us); -+ -+ /* if supinfo status is unchanged then we're done */ -+ if (line_has_supinfo(line) == was_suppl) -+ return; -+ -+ /* supinfo status has changed, so update the tree */ -+ if (was_suppl) -+ supinfo_erase(line); -+ else -+ supinfo_insert(line); -+} -+ - #define GPIO_V2_LINE_BIAS_FLAGS \ - (GPIO_V2_LINE_FLAG_BIAS_PULL_UP | \ - GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN | \ -@@ -742,7 +865,7 @@ static enum hte_return process_hw_ts(struct hte_ts_data *ts, void *p) - line->total_discard_seq++; - line->last_seqno = ts->seq; - mod_delayed_work(system_wq, &line->work, -- usecs_to_jiffies(READ_ONCE(line->desc->debounce_period_us))); -+ usecs_to_jiffies(READ_ONCE(line->debounce_period_us))); - } else { - if (unlikely(ts->seq < line->line_seqno)) - return HTE_CB_HANDLED; -@@ -883,7 +1006,7 @@ static irqreturn_t debounce_irq_handler(int irq, void *p) - struct line *line = p; - - mod_delayed_work(system_wq, &line->work, -- usecs_to_jiffies(READ_ONCE(line->desc->debounce_period_us))); -+ usecs_to_jiffies(READ_ONCE(line->debounce_period_us))); - - return IRQ_HANDLED; - } -@@ -966,7 +1089,7 @@ static int debounce_setup(struct line *line, unsigned int debounce_period_us) - /* try hardware */ - ret = gpiod_set_debounce(line->desc, debounce_period_us); - if (!ret) { -- WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); -+ line_set_debounce_period(line, debounce_period_us); - return ret; - } - if (ret != -ENOTSUPP) -@@ -1051,8 +1174,7 @@ static void edge_detector_stop(struct line *line) - cancel_delayed_work_sync(&line->work); - WRITE_ONCE(line->sw_debounced, 0); - WRITE_ONCE(line->edflags, 0); -- if (line->desc) -- WRITE_ONCE(line->desc->debounce_period_us, 0); -+ line_set_debounce_period(line, 0); - /* do not change line->level - see comment in debounced_value() */ - } - -@@ -1078,7 +1200,7 @@ static int edge_detector_setup(struct line *line, - ret = debounce_setup(line, debounce_period_us); - if (ret) - return ret; -- WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); -+ line_set_debounce_period(line, debounce_period_us); - } - - /* detection disabled or sw debouncer will provide edge detection */ -@@ -1121,17 +1243,31 @@ static int edge_detector_update(struct line *line, - struct gpio_v2_line_config *lc, - unsigned int line_idx, u64 edflags) - { -+ u64 eflags; -+ int ret; - u64 active_edflags = READ_ONCE(line->edflags); - unsigned int debounce_period_us = - gpio_v2_line_config_debounce_period(lc, line_idx); - - if ((active_edflags == edflags) && -- (READ_ONCE(line->desc->debounce_period_us) == debounce_period_us)) -+ (READ_ONCE(line->debounce_period_us) == debounce_period_us)) - return 0; - - /* sw debounced and still will be...*/ - if (debounce_period_us && READ_ONCE(line->sw_debounced)) { -- WRITE_ONCE(line->desc->debounce_period_us, debounce_period_us); -+ line_set_debounce_period(line, debounce_period_us); -+ /* -+ * ensure event fifo is initialised if edge detection -+ * is now enabled. -+ */ -+ eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS; -+ if (eflags && !kfifo_initialized(&line->req->events)) { -+ ret = kfifo_alloc(&line->req->events, -+ line->req->event_buffer_size, -+ GFP_KERNEL); -+ if (ret) -+ return ret; -+ } - return 0; - } - -@@ -1606,6 +1742,7 @@ static ssize_t linereq_read(struct file *file, char __user *buf, - - static void linereq_free(struct linereq *lr) - { -+ struct line *line; - unsigned int i; - - if (lr->device_unregistered_nb.notifier_call) -@@ -1613,10 +1750,14 @@ static void linereq_free(struct linereq *lr) - &lr->device_unregistered_nb); - - for (i = 0; i < lr->num_lines; i++) { -- if (lr->lines[i].desc) { -- edge_detector_stop(&lr->lines[i]); -- gpiod_free(lr->lines[i].desc); -- } -+ line = &lr->lines[i]; -+ if (!line->desc) -+ continue; -+ -+ edge_detector_stop(line); -+ if (line_has_supinfo(line)) -+ supinfo_erase(line); -+ gpiod_free(line->desc); - } - kfifo_free(&lr->events); - kfree(lr->label); -@@ -2316,8 +2457,6 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, - struct gpio_chip *gc = desc->gdev->chip; - bool ok_for_pinctrl; - unsigned long flags; -- u32 debounce_period_us; -- unsigned int num_attrs = 0; - - memset(info, 0, sizeof(*info)); - info->offset = gpio_chip_hwgpio(desc); -@@ -2384,14 +2523,6 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, - else if (test_bit(FLAG_EVENT_CLOCK_HTE, &desc->flags)) - info->flags |= GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE; - -- debounce_period_us = READ_ONCE(desc->debounce_period_us); -- if (debounce_period_us) { -- info->attrs[num_attrs].id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE; -- info->attrs[num_attrs].debounce_period_us = debounce_period_us; -- num_attrs++; -- } -- info->num_attrs = num_attrs; -- - spin_unlock_irqrestore(&gpio_lock, flags); - } - -@@ -2498,6 +2629,7 @@ static int lineinfo_get(struct gpio_chardev_data *cdev, void __user *ip, - return -EBUSY; - } - gpio_desc_to_lineinfo(desc, &lineinfo); -+ supinfo_to_lineinfo(desc, &lineinfo); - - if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) { - if (watch) -@@ -2596,6 +2728,7 @@ static int lineinfo_changed_notify(struct notifier_block *nb, - chg.event_type = action; - chg.timestamp_ns = ktime_get_ns(); - gpio_desc_to_lineinfo(desc, &chg.info); -+ supinfo_to_lineinfo(desc, &chg.info); - - ret = kfifo_in_spinlocked(&cdev->events, &chg, 1, &cdev->wait.lock); - if (ret) -@@ -2816,11 +2949,11 @@ static int gpio_chrdev_release(struct inode *inode, struct file *file) - struct gpio_chardev_data *cdev = file->private_data; - struct gpio_device *gdev = cdev->gdev; - -- bitmap_free(cdev->watched_lines); - blocking_notifier_chain_unregister(&gdev->device_notifier, - &cdev->device_unregistered_nb); - blocking_notifier_chain_unregister(&gdev->line_state_notifier, - &cdev->lineinfo_changed_nb); -+ bitmap_free(cdev->watched_lines); - gpio_device_put(gdev); - kfree(cdev); - -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c -index 78476bc75b4e1..de9d7f3dc2336 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c -@@ -300,12 +300,15 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) - dma_fence_set_error(finished, -ECANCELED); - - if (finished->error < 0) { -- DRM_INFO("Skip scheduling IBs!\n"); -+ dev_dbg(adev->dev, "Skip scheduling IBs in ring(%s)", -+ ring->name); - } else { - r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, job, - &fence); - if (r) -- DRM_ERROR("Error scheduling IBs (%d)\n", r); -+ dev_err(adev->dev, -+ "Error scheduling IBs (%d) in ring(%s)", r, -+ ring->name); - } - - job->job_run_counter++; -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c -index 361f2cc94e8e5..a348d320575e0 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c -@@ -1249,14 +1249,18 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, - * amdgpu_bo_move_notify - notification about a memory move - * @bo: pointer to a buffer object - * @evict: if this move is evicting the buffer from the graphics address space -+ * @new_mem: new resource for backing the BO - * - * Marks the corresponding &amdgpu_bo buffer object as invalid, also performs - * bookkeeping. - * TTM driver callback which is called when ttm moves a buffer. - */ --void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict) -+void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, -+ bool evict, -+ struct ttm_resource *new_mem) - { - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); -+ struct ttm_resource *old_mem = bo->resource; - struct amdgpu_bo *abo; - - if (!amdgpu_bo_is_amdgpu_bo(bo)) -@@ -1268,12 +1272,12 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict) - amdgpu_bo_kunmap(abo); - - if (abo->tbo.base.dma_buf && !abo->tbo.base.import_attach && -- bo->resource->mem_type != TTM_PL_SYSTEM) -+ old_mem && old_mem->mem_type != TTM_PL_SYSTEM) - dma_buf_move_notify(abo->tbo.base.dma_buf); - -- /* remember the eviction */ -- if (evict) -- atomic64_inc(&adev->num_evictions); -+ /* move_notify is called before move happens */ -+ trace_amdgpu_bo_move(abo, new_mem ? new_mem->mem_type : -1, -+ old_mem ? old_mem->mem_type : -1); - } - - void amdgpu_bo_get_memory(struct amdgpu_bo *bo, -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h -index fa03d9e4874cc..bc42ccbde659a 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h -@@ -328,7 +328,9 @@ int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata, - int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, - size_t buffer_size, uint32_t *metadata_size, - uint64_t *flags); --void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict); -+void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, -+ bool evict, -+ struct ttm_resource *new_mem); - void amdgpu_bo_release_notify(struct ttm_buffer_object *bo); - vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); - void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c -index d1687b5725693..8c3fb1562ffef 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c -@@ -424,7 +424,7 @@ bool amdgpu_res_cpu_visible(struct amdgpu_device *adev, - return false; - - if (res->mem_type == TTM_PL_SYSTEM || res->mem_type == TTM_PL_TT || -- res->mem_type == AMDGPU_PL_PREEMPT) -+ res->mem_type == AMDGPU_PL_PREEMPT || res->mem_type == AMDGPU_PL_DOORBELL) - return true; - - if (res->mem_type != TTM_PL_VRAM) -@@ -432,7 +432,7 @@ bool amdgpu_res_cpu_visible(struct amdgpu_device *adev, - - amdgpu_res_first(res, 0, res->size, &cursor); - while (cursor.remaining) { -- if ((cursor.start + cursor.size) >= adev->gmc.visible_vram_size) -+ if ((cursor.start + cursor.size) > adev->gmc.visible_vram_size) - return false; - amdgpu_res_next(&cursor, cursor.size); - } -@@ -486,14 +486,16 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, - - if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM && - bo->ttm == NULL)) { -+ amdgpu_bo_move_notify(bo, evict, new_mem); - ttm_bo_move_null(bo, new_mem); -- goto out; -+ return 0; - } - if (old_mem->mem_type == TTM_PL_SYSTEM && - (new_mem->mem_type == TTM_PL_TT || - new_mem->mem_type == AMDGPU_PL_PREEMPT)) { -+ amdgpu_bo_move_notify(bo, evict, new_mem); - ttm_bo_move_null(bo, new_mem); -- goto out; -+ return 0; - } - if ((old_mem->mem_type == TTM_PL_TT || - old_mem->mem_type == AMDGPU_PL_PREEMPT) && -@@ -503,9 +505,10 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, - return r; - - amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm); -+ amdgpu_bo_move_notify(bo, evict, new_mem); - ttm_resource_free(bo, &bo->resource); - ttm_bo_assign_mem(bo, new_mem); -- goto out; -+ return 0; - } - - if (old_mem->mem_type == AMDGPU_PL_GDS || -@@ -517,8 +520,9 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, - new_mem->mem_type == AMDGPU_PL_OA || - new_mem->mem_type == AMDGPU_PL_DOORBELL) { - /* Nothing to save here */ -+ amdgpu_bo_move_notify(bo, evict, new_mem); - ttm_bo_move_null(bo, new_mem); -- goto out; -+ return 0; - } - - if (bo->type == ttm_bo_type_device && -@@ -530,22 +534,23 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, - abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; - } - -- if (adev->mman.buffer_funcs_enabled) { -- if (((old_mem->mem_type == TTM_PL_SYSTEM && -- new_mem->mem_type == TTM_PL_VRAM) || -- (old_mem->mem_type == TTM_PL_VRAM && -- new_mem->mem_type == TTM_PL_SYSTEM))) { -- hop->fpfn = 0; -- hop->lpfn = 0; -- hop->mem_type = TTM_PL_TT; -- hop->flags = TTM_PL_FLAG_TEMPORARY; -- return -EMULTIHOP; -- } -+ if (adev->mman.buffer_funcs_enabled && -+ ((old_mem->mem_type == TTM_PL_SYSTEM && -+ new_mem->mem_type == TTM_PL_VRAM) || -+ (old_mem->mem_type == TTM_PL_VRAM && -+ new_mem->mem_type == TTM_PL_SYSTEM))) { -+ hop->fpfn = 0; -+ hop->lpfn = 0; -+ hop->mem_type = TTM_PL_TT; -+ hop->flags = TTM_PL_FLAG_TEMPORARY; -+ return -EMULTIHOP; -+ } - -+ amdgpu_bo_move_notify(bo, evict, new_mem); -+ if (adev->mman.buffer_funcs_enabled) - r = amdgpu_move_blit(bo, evict, new_mem, old_mem); -- } else { -+ else - r = -ENODEV; -- } - - if (r) { - /* Check that all memory is CPU accessible */ -@@ -560,11 +565,10 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, - return r; - } - -- trace_amdgpu_bo_move(abo, new_mem->mem_type, old_mem->mem_type); --out: -- /* update statistics */ -+ /* update statistics after the move */ -+ if (evict) -+ atomic64_inc(&adev->num_evictions); - atomic64_add(bo->base.size, &adev->num_bytes_moved); -- amdgpu_bo_move_notify(bo, evict); - return 0; - } - -@@ -1568,7 +1572,7 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, - static void - amdgpu_bo_delete_mem_notify(struct ttm_buffer_object *bo) - { -- amdgpu_bo_move_notify(bo, false); -+ amdgpu_bo_move_notify(bo, false, NULL); - } - - static struct ttm_device_funcs amdgpu_bo_driver = { -diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c -index d0fc62784e821..0284c9198a04a 100644 ---- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c -+++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c -@@ -61,6 +61,11 @@ void aqua_vanjaram_doorbell_index_init(struct amdgpu_device *adev) - adev->doorbell_index.max_assignment = AMDGPU_DOORBELL_LAYOUT1_MAX_ASSIGNMENT << 1; - } - -+static bool aqua_vanjaram_xcp_vcn_shared(struct amdgpu_device *adev) -+{ -+ return (adev->xcp_mgr->num_xcps > adev->vcn.num_vcn_inst); -+} -+ - static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev, - uint32_t inst_idx, struct amdgpu_ring *ring) - { -@@ -86,7 +91,7 @@ static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev, - case AMDGPU_RING_TYPE_VCN_ENC: - case AMDGPU_RING_TYPE_VCN_JPEG: - ip_blk = AMDGPU_XCP_VCN; -- if (adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE) -+ if (aqua_vanjaram_xcp_vcn_shared(adev)) - inst_mask = 1 << (inst_idx * 2); - break; - default: -@@ -139,10 +144,12 @@ static int aqua_vanjaram_xcp_sched_list_update( - - aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id); - -- /* VCN is shared by two partitions under CPX MODE */ -+ /* VCN may be shared by two partitions under CPX MODE in certain -+ * configs. -+ */ - if ((ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC || -- ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) && -- adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE) -+ ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) && -+ aqua_vanjaram_xcp_vcn_shared(adev)) - aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id + 1); - } - -diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c -index e76e7e7cb554e..4e8d5e6a65e41 100644 ---- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c -+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c -@@ -1613,19 +1613,9 @@ static int sdma_v4_4_2_set_ecc_irq_state(struct amdgpu_device *adev, - u32 sdma_cntl; - - sdma_cntl = RREG32_SDMA(type, regSDMA_CNTL); -- switch (state) { -- case AMDGPU_IRQ_STATE_DISABLE: -- sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL, -- DRAM_ECC_INT_ENABLE, 0); -- WREG32_SDMA(type, regSDMA_CNTL, sdma_cntl); -- break; -- /* sdma ecc interrupt is enabled by default -- * driver doesn't need to do anything to -- * enable the interrupt */ -- case AMDGPU_IRQ_STATE_ENABLE: -- default: -- break; -- } -+ sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL, DRAM_ECC_INT_ENABLE, -+ state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0); -+ WREG32_SDMA(type, regSDMA_CNTL, sdma_cntl); - - return 0; - } -diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c -index c157721214e8d..d33ba4fe9ad5b 100644 ---- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c -+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c -@@ -1138,7 +1138,7 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep, - goto err_unlock; - } - offset = dev->adev->rmmio_remap.bus_addr; -- if (!offset) { -+ if (!offset || (PAGE_SIZE > 4096)) { - err = -ENOMEM; - goto err_unlock; - } -@@ -1516,7 +1516,7 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep, - - /* Find a KFD GPU device that supports the get_dmabuf_info query */ - for (i = 0; kfd_topology_enum_kfd_devices(i, &dev) == 0; i++) -- if (dev) -+ if (dev && !kfd_devcgroup_check_permission(dev)) - break; - if (!dev) - return -EINVAL; -@@ -1538,7 +1538,7 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep, - if (xcp_id >= 0) - args->gpu_id = dmabuf_adev->kfd.dev->nodes[xcp_id]->id; - else -- args->gpu_id = dmabuf_adev->kfd.dev->nodes[0]->id; -+ args->gpu_id = dev->id; - args->flags = flags; - - /* Copy metadata buffer to user mode */ -@@ -2307,7 +2307,7 @@ static int criu_restore_memory_of_gpu(struct kfd_process_device *pdd, - return -EINVAL; - } - offset = pdd->dev->adev->rmmio_remap.bus_addr; -- if (!offset) { -+ if (!offset || (PAGE_SIZE > 4096)) { - pr_err("amdgpu_amdkfd_get_mmio_remap_phys_addr failed\n"); - return -ENOMEM; - } -@@ -3348,6 +3348,9 @@ static int kfd_mmio_mmap(struct kfd_node *dev, struct kfd_process *process, - if (vma->vm_end - vma->vm_start != PAGE_SIZE) - return -EINVAL; - -+ if (PAGE_SIZE > 4096) -+ return -EINVAL; -+ - address = dev->adev->rmmio_remap.bus_addr; - - vm_flags_set(vma, VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_NORESERVE | -diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c -index 93ce181eb3baa..913c70a0ef44f 100644 ---- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c -+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c -@@ -935,7 +935,6 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) - { - struct kfd_node *node; - int i; -- int count; - - if (!kfd->init_complete) - return; -@@ -943,12 +942,10 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) - /* for runtime suspend, skip locking kfd */ - if (!run_pm) { - mutex_lock(&kfd_processes_mutex); -- count = ++kfd_locked; -- mutex_unlock(&kfd_processes_mutex); -- - /* For first KFD device suspend all the KFD processes */ -- if (count == 1) -+ if (++kfd_locked == 1) - kfd_suspend_all_processes(); -+ mutex_unlock(&kfd_processes_mutex); - } - - for (i = 0; i < kfd->num_nodes; i++) { -@@ -959,7 +956,7 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) - - int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) - { -- int ret, count, i; -+ int ret, i; - - if (!kfd->init_complete) - return 0; -@@ -973,12 +970,10 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) - /* for runtime resume, skip unlocking kfd */ - if (!run_pm) { - mutex_lock(&kfd_processes_mutex); -- count = --kfd_locked; -- mutex_unlock(&kfd_processes_mutex); -- -- WARN_ONCE(count < 0, "KFD suspend / resume ref. error"); -- if (count == 0) -+ if (--kfd_locked == 0) - ret = kfd_resume_all_processes(); -+ WARN_ONCE(kfd_locked < 0, "KFD suspend / resume ref. error"); -+ mutex_unlock(&kfd_processes_mutex); - } - - return ret; -diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c -index a7697ec8188e0..f85ca6cb90f56 100644 ---- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c -+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c -@@ -336,7 +336,8 @@ static void event_interrupt_wq_v10(struct kfd_node *dev, - break; - } - kfd_signal_event_interrupt(pasid, context_id0 & 0x7fffff, 23); -- } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE) { -+ } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE && -+ KFD_DBG_EC_TYPE_IS_PACKET(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0))) { - kfd_set_dbg_ev_from_interrupt(dev, pasid, - KFD_DEBUG_DOORBELL_ID(context_id0), - KFD_EC_MASK(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0)), -diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c -index 2a65792fd1162..3ca9c160da7c2 100644 ---- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c -+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c -@@ -325,7 +325,8 @@ static void event_interrupt_wq_v11(struct kfd_node *dev, - /* CP */ - if (source_id == SOC15_INTSRC_CP_END_OF_PIPE) - kfd_signal_event_interrupt(pasid, context_id0, 32); -- else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE) -+ else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE && -+ KFD_DBG_EC_TYPE_IS_PACKET(KFD_CTXID0_CP_BAD_OP_ECODE(context_id0))) - kfd_set_dbg_ev_from_interrupt(dev, pasid, - KFD_CTXID0_DOORBELL_ID(context_id0), - KFD_EC_MASK(KFD_CTXID0_CP_BAD_OP_ECODE(context_id0)), -diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c -index 27cdaea405017..8a6729939ae55 100644 ---- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c -+++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c -@@ -385,7 +385,8 @@ static void event_interrupt_wq_v9(struct kfd_node *dev, - break; - } - kfd_signal_event_interrupt(pasid, sq_int_data, 24); -- } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE) { -+ } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE && -+ KFD_DBG_EC_TYPE_IS_PACKET(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0))) { - kfd_set_dbg_ev_from_interrupt(dev, pasid, - KFD_DEBUG_DOORBELL_ID(context_id0), - KFD_EC_MASK(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0)), -diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -index 3442e08f47876..98dd07e3726af 100644 ---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -@@ -2974,6 +2974,10 @@ static int dm_resume(void *handle) - /* Do mst topology probing after resuming cached state*/ - drm_connector_list_iter_begin(ddev, &iter); - drm_for_each_connector_iter(connector, &iter) { -+ -+ if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) -+ continue; -+ - aconnector = to_amdgpu_dm_connector(connector); - if (aconnector->dc_link->type != dc_connection_mst_branch || - aconnector->mst_root) -@@ -5756,6 +5760,9 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector, - &aconnector->base.probed_modes : - &aconnector->base.modes; - -+ if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_WRITEBACK) -+ return NULL; -+ - if (aconnector->freesync_vid_base.clock != 0) - return &aconnector->freesync_vid_base; - -@@ -8445,6 +8452,9 @@ static void amdgpu_dm_commit_audio(struct drm_device *dev, - continue; - - notify: -+ if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) -+ continue; -+ - aconnector = to_amdgpu_dm_connector(connector); - - mutex_lock(&adev->dm.audio_lock); -diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c -index f4b9d43c5d979..2bc37c5a27605 100644 ---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c -+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c -@@ -1465,7 +1465,9 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -@@ -1566,7 +1568,9 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf, - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -@@ -1651,7 +1655,9 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -@@ -1750,7 +1756,9 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf, - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -@@ -1835,7 +1843,9 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -@@ -1934,7 +1944,9 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf, - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -@@ -2015,7 +2027,9 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -@@ -2111,7 +2125,9 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -@@ -2190,7 +2206,9 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf, - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -@@ -2246,7 +2264,9 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf, - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -@@ -2317,7 +2337,9 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf, - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -@@ -2388,7 +2410,9 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf, - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx->stream && -- pipe_ctx->stream->link == aconnector->dc_link) -+ pipe_ctx->stream->link == aconnector->dc_link && -+ pipe_ctx->stream->sink && -+ pipe_ctx->stream->sink == aconnector->dc_sink) - break; - } - -diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c -index 4c3c4c8de1cfc..93720cf069d7c 100644 ---- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c -+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c -@@ -2961,6 +2961,7 @@ static enum bp_result construct_integrated_info( - result = get_integrated_info_v2_1(bp, info); - break; - case 2: -+ case 3: - result = get_integrated_info_v2_2(bp, info); - break; - default: -diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c -index 5b7ad38f85e08..65e45a0b4ff34 100644 ---- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c -+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c -@@ -395,6 +395,12 @@ void dcn31_hpo_dp_link_enc_set_throttled_vcp_size( - x), - 25)); - -+ // If y rounds up to integer, carry it over to x. -+ if (y >> 25) { -+ x += 1; -+ y = 0; -+ } -+ - switch (stream_encoder_inst) { - case 0: - REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, 0, -diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c -index 1d1917e1b63f4..cd674ef5adb19 100644 ---- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c -+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c -@@ -226,7 +226,7 @@ static int smu_v13_0_4_system_features_control(struct smu_context *smu, bool en) - struct amdgpu_device *adev = smu->adev; - int ret = 0; - -- if (!en && !adev->in_s0ix) { -+ if (!en && adev->in_s4) { - /* Adds a GFX reset as workaround just before sending the - * MP1_UNLOAD message to prevent GC/RLC/PMFW from entering - * an invalid state. -diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c -index c44d5bcf12847..309aad5f0c808 100644 ---- a/drivers/gpu/drm/drm_connector.c -+++ b/drivers/gpu/drm/drm_connector.c -@@ -2925,7 +2925,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, - dev->mode_config.max_width, - dev->mode_config.max_height); - else -- drm_dbg_kms(dev, "User-space requested a forced probe on [CONNECTOR:%d:%s] but is not the DRM master, demoting to read-only probe", -+ drm_dbg_kms(dev, "User-space requested a forced probe on [CONNECTOR:%d:%s] but is not the DRM master, demoting to read-only probe\n", - connector->base.id, connector->name); - } - -diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c -index 3d9c9b4f27f80..8b8d1d806566e 100644 ---- a/drivers/gpu/drm/i915/display/intel_audio.c -+++ b/drivers/gpu/drm/i915/display/intel_audio.c -@@ -75,19 +75,6 @@ struct intel_audio_funcs { - struct intel_crtc_state *crtc_state); - }; - --/* DP N/M table */ --#define LC_810M 810000 --#define LC_540M 540000 --#define LC_270M 270000 --#define LC_162M 162000 -- --struct dp_aud_n_m { -- int sample_rate; -- int clock; -- u16 m; -- u16 n; --}; -- - struct hdmi_aud_ncts { - int sample_rate; - int clock; -@@ -95,60 +82,6 @@ struct hdmi_aud_ncts { - int cts; - }; - --/* Values according to DP 1.4 Table 2-104 */ --static const struct dp_aud_n_m dp_aud_n_m[] = { -- { 32000, LC_162M, 1024, 10125 }, -- { 44100, LC_162M, 784, 5625 }, -- { 48000, LC_162M, 512, 3375 }, -- { 64000, LC_162M, 2048, 10125 }, -- { 88200, LC_162M, 1568, 5625 }, -- { 96000, LC_162M, 1024, 3375 }, -- { 128000, LC_162M, 4096, 10125 }, -- { 176400, LC_162M, 3136, 5625 }, -- { 192000, LC_162M, 2048, 3375 }, -- { 32000, LC_270M, 1024, 16875 }, -- { 44100, LC_270M, 784, 9375 }, -- { 48000, LC_270M, 512, 5625 }, -- { 64000, LC_270M, 2048, 16875 }, -- { 88200, LC_270M, 1568, 9375 }, -- { 96000, LC_270M, 1024, 5625 }, -- { 128000, LC_270M, 4096, 16875 }, -- { 176400, LC_270M, 3136, 9375 }, -- { 192000, LC_270M, 2048, 5625 }, -- { 32000, LC_540M, 1024, 33750 }, -- { 44100, LC_540M, 784, 18750 }, -- { 48000, LC_540M, 512, 11250 }, -- { 64000, LC_540M, 2048, 33750 }, -- { 88200, LC_540M, 1568, 18750 }, -- { 96000, LC_540M, 1024, 11250 }, -- { 128000, LC_540M, 4096, 33750 }, -- { 176400, LC_540M, 3136, 18750 }, -- { 192000, LC_540M, 2048, 11250 }, -- { 32000, LC_810M, 1024, 50625 }, -- { 44100, LC_810M, 784, 28125 }, -- { 48000, LC_810M, 512, 16875 }, -- { 64000, LC_810M, 2048, 50625 }, -- { 88200, LC_810M, 1568, 28125 }, -- { 96000, LC_810M, 1024, 16875 }, -- { 128000, LC_810M, 4096, 50625 }, -- { 176400, LC_810M, 3136, 28125 }, -- { 192000, LC_810M, 2048, 16875 }, --}; -- --static const struct dp_aud_n_m * --audio_config_dp_get_n_m(const struct intel_crtc_state *crtc_state, int rate) --{ -- int i; -- -- for (i = 0; i < ARRAY_SIZE(dp_aud_n_m); i++) { -- if (rate == dp_aud_n_m[i].sample_rate && -- crtc_state->port_clock == dp_aud_n_m[i].clock) -- return &dp_aud_n_m[i]; -- } -- -- return NULL; --} -- - static const struct { - int clock; - u32 config; -@@ -386,47 +319,17 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) - { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); -- struct i915_audio_component *acomp = i915->display.audio.component; - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; -- enum port port = encoder->port; -- const struct dp_aud_n_m *nm; -- int rate; -- u32 tmp; -- -- rate = acomp ? acomp->aud_sample_rate[port] : 0; -- nm = audio_config_dp_get_n_m(crtc_state, rate); -- if (nm) -- drm_dbg_kms(&i915->drm, "using Maud %u, Naud %u\n", nm->m, -- nm->n); -- else -- drm_dbg_kms(&i915->drm, "using automatic Maud, Naud\n"); -- -- tmp = intel_de_read(i915, HSW_AUD_CFG(cpu_transcoder)); -- tmp &= ~AUD_CONFIG_N_VALUE_INDEX; -- tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; -- tmp &= ~AUD_CONFIG_N_PROG_ENABLE; -- tmp |= AUD_CONFIG_N_VALUE_INDEX; - -- if (nm) { -- tmp &= ~AUD_CONFIG_N_MASK; -- tmp |= AUD_CONFIG_N(nm->n); -- tmp |= AUD_CONFIG_N_PROG_ENABLE; -- } -- -- intel_de_write(i915, HSW_AUD_CFG(cpu_transcoder), tmp); -- -- tmp = intel_de_read(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder)); -- tmp &= ~AUD_CONFIG_M_MASK; -- tmp &= ~AUD_M_CTS_M_VALUE_INDEX; -- tmp &= ~AUD_M_CTS_M_PROG_ENABLE; -- -- if (nm) { -- tmp |= nm->m; -- tmp |= AUD_M_CTS_M_VALUE_INDEX; -- tmp |= AUD_M_CTS_M_PROG_ENABLE; -- } -+ /* Enable time stamps. Let HW calculate Maud/Naud values */ -+ intel_de_rmw(i915, HSW_AUD_CFG(cpu_transcoder), -+ AUD_CONFIG_N_VALUE_INDEX | -+ AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK | -+ AUD_CONFIG_UPPER_N_MASK | -+ AUD_CONFIG_LOWER_N_MASK | -+ AUD_CONFIG_N_PROG_ENABLE, -+ AUD_CONFIG_N_VALUE_INDEX); - -- intel_de_write(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp); - } - - static void -diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c -index f282a2d89c78d..27d1c49b46ec4 100644 ---- a/drivers/gpu/drm/i915/display/intel_bios.c -+++ b/drivers/gpu/drm/i915/display/intel_bios.c -@@ -1035,22 +1035,11 @@ parse_lfp_backlight(struct drm_i915_private *i915, - panel->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI; - panel->vbt.backlight.controller = 0; - if (i915->display.vbt.version >= 191) { -- size_t exp_size; -+ const struct lfp_backlight_control_method *method; - -- if (i915->display.vbt.version >= 236) -- exp_size = sizeof(struct bdb_lfp_backlight_data); -- else if (i915->display.vbt.version >= 234) -- exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_234; -- else -- exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_191; -- -- if (get_blocksize(backlight_data) >= exp_size) { -- const struct lfp_backlight_control_method *method; -- -- method = &backlight_data->backlight_control[panel_type]; -- panel->vbt.backlight.type = method->type; -- panel->vbt.backlight.controller = method->controller; -- } -+ method = &backlight_data->backlight_control[panel_type]; -+ panel->vbt.backlight.type = method->type; -+ panel->vbt.backlight.controller = method->controller; - } - - panel->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; -diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h -index a9f44abfc9fc2..b50cd0dcabda9 100644 ---- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h -+++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h -@@ -897,11 +897,6 @@ struct lfp_brightness_level { - u16 reserved; - } __packed; - --#define EXP_BDB_LFP_BL_DATA_SIZE_REV_191 \ -- offsetof(struct bdb_lfp_backlight_data, brightness_level) --#define EXP_BDB_LFP_BL_DATA_SIZE_REV_234 \ -- offsetof(struct bdb_lfp_backlight_data, brightness_precision_bits) -- - struct bdb_lfp_backlight_data { - u8 entry_size; - struct lfp_backlight_data_entry data[16]; -diff --git a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c -index 044219c5960a5..99b71bb7da0a6 100644 ---- a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c -+++ b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c -@@ -8,14 +8,14 @@ - #include "intel_gt_ccs_mode.h" - #include "intel_gt_regs.h" - --void intel_gt_apply_ccs_mode(struct intel_gt *gt) -+unsigned int intel_gt_apply_ccs_mode(struct intel_gt *gt) - { - int cslice; - u32 mode = 0; - int first_ccs = __ffs(CCS_MASK(gt)); - - if (!IS_DG2(gt->i915)) -- return; -+ return 0; - - /* Build the value for the fixed CCS load balancing */ - for (cslice = 0; cslice < I915_MAX_CCS; cslice++) { -@@ -35,5 +35,5 @@ void intel_gt_apply_ccs_mode(struct intel_gt *gt) - XEHP_CCS_MODE_CSLICE_MASK); - } - -- intel_uncore_write(gt->uncore, XEHP_CCS_MODE, mode); -+ return mode; - } -diff --git a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h -index 9e5549caeb269..55547f2ff426a 100644 ---- a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h -+++ b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h -@@ -8,6 +8,6 @@ - - struct intel_gt; - --void intel_gt_apply_ccs_mode(struct intel_gt *gt); -+unsigned int intel_gt_apply_ccs_mode(struct intel_gt *gt); - - #endif /* __INTEL_GT_CCS_MODE_H__ */ -diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c -index be060b32bd9ce..8fbb0686c5348 100644 ---- a/drivers/gpu/drm/i915/gt/intel_workarounds.c -+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c -@@ -2828,6 +2828,7 @@ add_render_compute_tuning_settings(struct intel_gt *gt, - static void ccs_engine_wa_mode(struct intel_engine_cs *engine, struct i915_wa_list *wal) - { - struct intel_gt *gt = engine->gt; -+ u32 mode; - - if (!IS_DG2(gt->i915)) - return; -@@ -2844,7 +2845,8 @@ static void ccs_engine_wa_mode(struct intel_engine_cs *engine, struct i915_wa_li - * After having disabled automatic load balancing we need to - * assign all slices to a single CCS. We will call it CCS mode 1 - */ -- intel_gt_apply_ccs_mode(gt); -+ mode = intel_gt_apply_ccs_mode(gt); -+ wa_masked_en(wal, XEHP_CCS_MODE, mode); - } - - /* -diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c -index 5a9538bc0e26f..5565f7777529f 100644 ---- a/drivers/gpu/drm/meson/meson_dw_hdmi.c -+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c -@@ -106,6 +106,8 @@ - #define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 */ - #define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 */ - #define HHI_HDMI_PHY_CNTL1 0x3a4 /* 0xe9 */ -+#define PHY_CNTL1_INIT 0x03900000 -+#define PHY_INVERT BIT(17) - #define HHI_HDMI_PHY_CNTL2 0x3a8 /* 0xea */ - #define HHI_HDMI_PHY_CNTL3 0x3ac /* 0xeb */ - #define HHI_HDMI_PHY_CNTL4 0x3b0 /* 0xec */ -@@ -130,6 +132,8 @@ struct meson_dw_hdmi_data { - unsigned int addr); - void (*dwc_write)(struct meson_dw_hdmi *dw_hdmi, - unsigned int addr, unsigned int data); -+ u32 cntl0_init; -+ u32 cntl1_init; - }; - - struct meson_dw_hdmi { -@@ -384,26 +388,6 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, - dw_hdmi_bus_fmt_is_420(hdmi)) - mode_is_420 = true; - -- /* Enable clocks */ -- regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100); -- -- /* Bring HDMITX MEM output of power down */ -- regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0); -- -- /* Bring out of reset */ -- dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0); -- -- /* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */ -- dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL, -- 0x3, 0x3); -- -- /* Enable cec_clk and hdcp22_tmdsclk_en */ -- dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL, -- 0x3 << 4, 0x3 << 4); -- -- /* Enable normal output to PHY */ -- dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12)); -- - /* TMDS pattern setup */ - if (mode->clock > 340000 && !mode_is_420) { - dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, -@@ -425,20 +409,6 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, - /* Setup PHY parameters */ - meson_hdmi_phy_setup_mode(dw_hdmi, mode, mode_is_420); - -- /* Setup PHY */ -- regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, -- 0xffff << 16, 0x0390 << 16); -- -- /* BIT_INVERT */ -- if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") || -- dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi") || -- dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-g12a-dw-hdmi")) -- regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, -- BIT(17), 0); -- else -- regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, -- BIT(17), BIT(17)); -- - /* Disable clock, fifo, fifo_wr */ - regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0); - -@@ -492,7 +462,9 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, - - DRM_DEBUG_DRIVER("\n"); - -- regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0); -+ /* Fallback to init mode */ -+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL1, dw_hdmi->data->cntl1_init); -+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, dw_hdmi->data->cntl0_init); - } - - static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi, -@@ -610,11 +582,22 @@ static const struct regmap_config meson_dw_hdmi_regmap_config = { - .fast_io = true, - }; - --static const struct meson_dw_hdmi_data meson_dw_hdmi_gx_data = { -+static const struct meson_dw_hdmi_data meson_dw_hdmi_gxbb_data = { - .top_read = dw_hdmi_top_read, - .top_write = dw_hdmi_top_write, - .dwc_read = dw_hdmi_dwc_read, - .dwc_write = dw_hdmi_dwc_write, -+ .cntl0_init = 0x0, -+ .cntl1_init = PHY_CNTL1_INIT | PHY_INVERT, -+}; -+ -+static const struct meson_dw_hdmi_data meson_dw_hdmi_gxl_data = { -+ .top_read = dw_hdmi_top_read, -+ .top_write = dw_hdmi_top_write, -+ .dwc_read = dw_hdmi_dwc_read, -+ .dwc_write = dw_hdmi_dwc_write, -+ .cntl0_init = 0x0, -+ .cntl1_init = PHY_CNTL1_INIT, - }; - - static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = { -@@ -622,6 +605,8 @@ static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = { - .top_write = dw_hdmi_g12a_top_write, - .dwc_read = dw_hdmi_g12a_dwc_read, - .dwc_write = dw_hdmi_g12a_dwc_write, -+ .cntl0_init = 0x000b4242, /* Bandgap */ -+ .cntl1_init = PHY_CNTL1_INIT, - }; - - static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi) -@@ -656,6 +641,13 @@ static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi) - meson_dw_hdmi->data->top_write(meson_dw_hdmi, - HDMITX_TOP_CLK_CNTL, 0xff); - -+ /* Enable normal output to PHY */ -+ meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12)); -+ -+ /* Setup PHY */ -+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL1, meson_dw_hdmi->data->cntl1_init); -+ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, meson_dw_hdmi->data->cntl0_init); -+ - /* Enable HDMI-TX Interrupt */ - meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, - HDMITX_TOP_INTR_CORE); -@@ -865,11 +857,11 @@ static const struct dev_pm_ops meson_dw_hdmi_pm_ops = { - - static const struct of_device_id meson_dw_hdmi_of_table[] = { - { .compatible = "amlogic,meson-gxbb-dw-hdmi", -- .data = &meson_dw_hdmi_gx_data }, -+ .data = &meson_dw_hdmi_gxbb_data }, - { .compatible = "amlogic,meson-gxl-dw-hdmi", -- .data = &meson_dw_hdmi_gx_data }, -+ .data = &meson_dw_hdmi_gxl_data }, - { .compatible = "amlogic,meson-gxm-dw-hdmi", -- .data = &meson_dw_hdmi_gx_data }, -+ .data = &meson_dw_hdmi_gxl_data }, - { .compatible = "amlogic,meson-g12a-dw-hdmi", - .data = &meson_dw_hdmi_g12a_data }, - { } -diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c -index 6a4980b2d4d4e..bf2ae67b03d94 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_dp.c -+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c -@@ -108,12 +108,15 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, - u8 *dpcd = nv_encoder->dp.dpcd; - int ret = NOUVEAU_DP_NONE, hpd; - -- /* If we've already read the DPCD on an eDP device, we don't need to -- * reread it as it won't change -+ /* eDP ports don't support hotplugging - so there's no point in probing eDP ports unless we -+ * haven't probed them once before. - */ -- if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && -- dpcd[DP_DPCD_REV] != 0) -- return NOUVEAU_DP_SST; -+ if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { -+ if (connector->status == connector_status_connected) -+ return NOUVEAU_DP_SST; -+ else if (connector->status == connector_status_disconnected) -+ return NOUVEAU_DP_NONE; -+ } - - mutex_lock(&nv_encoder->dp.hpd_irq_lock); - if (mstm) { -diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig -index 869e535faefa3..3a2f4a9f1d466 100644 ---- a/drivers/gpu/drm/panel/Kconfig -+++ b/drivers/gpu/drm/panel/Kconfig -@@ -184,7 +184,7 @@ config DRM_PANEL_ILITEK_IL9322 - - config DRM_PANEL_ILITEK_ILI9341 - tristate "Ilitek ILI9341 240x320 QVGA panels" -- depends on OF && SPI -+ depends on SPI - select DRM_KMS_HELPER - select DRM_GEM_DMA_HELPER - depends on BACKLIGHT_CLASS_DEVICE -diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c -index 3574681891e81..b933380b7eb78 100644 ---- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c -+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c -@@ -22,8 +22,9 @@ - #include - #include - #include -+#include - #include --#include -+#include - #include - #include - -@@ -421,7 +422,7 @@ static int ili9341_dpi_prepare(struct drm_panel *panel) - - ili9341_dpi_init(ili); - -- return ret; -+ return 0; - } - - static int ili9341_dpi_enable(struct drm_panel *panel) -@@ -691,7 +692,7 @@ static int ili9341_dpi_probe(struct spi_device *spi, struct gpio_desc *dc, - * Every new incarnation of this display must have a unique - * data entry for the system in this driver. - */ -- ili->conf = of_device_get_match_data(dev); -+ ili->conf = device_get_match_data(dev); - if (!ili->conf) { - dev_err(dev, "missing device configuration\n"); - return -ENODEV; -@@ -714,18 +715,18 @@ static int ili9341_probe(struct spi_device *spi) - - reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(reset)) -- dev_err(dev, "Failed to get gpio 'reset'\n"); -+ return dev_err_probe(dev, PTR_ERR(reset), "Failed to get gpio 'reset'\n"); - - dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW); - if (IS_ERR(dc)) -- dev_err(dev, "Failed to get gpio 'dc'\n"); -+ return dev_err_probe(dev, PTR_ERR(dc), "Failed to get gpio 'dc'\n"); - - if (!strcmp(id->name, "sf-tc240t-9370-t")) - return ili9341_dpi_probe(spi, dc, reset); - else if (!strcmp(id->name, "yx240qv29")) - return ili9341_dbi_probe(spi, dc, reset); - -- return -1; -+ return -ENODEV; - } - - static void ili9341_remove(struct spi_device *spi) -diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c -index 9febc8b73f09e..368d26da0d6a2 100644 ---- a/drivers/gpu/drm/qxl/qxl_release.c -+++ b/drivers/gpu/drm/qxl/qxl_release.c -@@ -58,56 +58,16 @@ static long qxl_fence_wait(struct dma_fence *fence, bool intr, - signed long timeout) - { - struct qxl_device *qdev; -- struct qxl_release *release; -- int count = 0, sc = 0; -- bool have_drawable_releases; - unsigned long cur, end = jiffies + timeout; - - qdev = container_of(fence->lock, struct qxl_device, release_lock); -- release = container_of(fence, struct qxl_release, base); -- have_drawable_releases = release->type == QXL_RELEASE_DRAWABLE; -- --retry: -- sc++; -- -- if (dma_fence_is_signaled(fence)) -- goto signaled; -- -- qxl_io_notify_oom(qdev); -- -- for (count = 0; count < 11; count++) { -- if (!qxl_queue_garbage_collect(qdev, true)) -- break; -- -- if (dma_fence_is_signaled(fence)) -- goto signaled; -- } -- -- if (dma_fence_is_signaled(fence)) -- goto signaled; - -- if (have_drawable_releases || sc < 4) { -- if (sc > 2) -- /* back off */ -- usleep_range(500, 1000); -- -- if (time_after(jiffies, end)) -- return 0; -- -- if (have_drawable_releases && sc > 300) { -- DMA_FENCE_WARN(fence, -- "failed to wait on release %llu after spincount %d\n", -- fence->context & ~0xf0000000, sc); -- goto signaled; -- } -- goto retry; -- } -- /* -- * yeah, original sync_obj_wait gave up after 3 spins when -- * have_drawable_releases is not set. -- */ -+ if (!wait_event_timeout(qdev->release_event, -+ (dma_fence_is_signaled(fence) || -+ (qxl_io_notify_oom(qdev), 0)), -+ timeout)) -+ return 0; - --signaled: - cur = jiffies; - if (time_after(cur, end)) - return 0; -diff --git a/drivers/gpu/drm/radeon/pptable.h b/drivers/gpu/drm/radeon/pptable.h -index 4c2eec49dadc9..844f0490bf31f 100644 ---- a/drivers/gpu/drm/radeon/pptable.h -+++ b/drivers/gpu/drm/radeon/pptable.h -@@ -424,7 +424,7 @@ typedef struct _ATOM_PPLIB_SUMO_CLOCK_INFO{ - typedef struct _ATOM_PPLIB_STATE_V2 - { - //number of valid dpm levels in this state; Driver uses it to calculate the whole -- //size of the state: sizeof(ATOM_PPLIB_STATE_V2) + (ucNumDPMLevels - 1) * sizeof(UCHAR) -+ //size of the state: struct_size(ATOM_PPLIB_STATE_V2, clockInfoIndex, ucNumDPMLevels) - UCHAR ucNumDPMLevels; - - //a index to the array of nonClockInfos -@@ -432,14 +432,14 @@ typedef struct _ATOM_PPLIB_STATE_V2 - /** - * Driver will read the first ucNumDPMLevels in this array - */ -- UCHAR clockInfoIndex[1]; -+ UCHAR clockInfoIndex[] __counted_by(ucNumDPMLevels); - } ATOM_PPLIB_STATE_V2; - - typedef struct _StateArray{ - //how many states we have - UCHAR ucNumEntries; - -- ATOM_PPLIB_STATE_V2 states[1]; -+ ATOM_PPLIB_STATE_V2 states[] __counted_by(ucNumEntries); - }StateArray; - - -@@ -450,7 +450,7 @@ typedef struct _ClockInfoArray{ - //sizeof(ATOM_PPLIB_CLOCK_INFO) - UCHAR ucEntrySize; - -- UCHAR clockInfo[1]; -+ UCHAR clockInfo[] __counted_by(ucNumEntries); - }ClockInfoArray; - - typedef struct _NonClockInfoArray{ -@@ -460,7 +460,7 @@ typedef struct _NonClockInfoArray{ - //sizeof(ATOM_PPLIB_NONCLOCK_INFO) - UCHAR ucEntrySize; - -- ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[1]; -+ ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[] __counted_by(ucNumEntries); - }NonClockInfoArray; - - typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record -diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c -index 43eaffa7faae3..bf9601351fa35 100644 ---- a/drivers/gpu/drm/ttm/ttm_tt.c -+++ b/drivers/gpu/drm/ttm/ttm_tt.c -@@ -92,7 +92,7 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc) - */ - if (bdev->pool.use_dma_alloc && cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) { - page_flags |= TTM_TT_FLAG_DECRYPTED; -- drm_info(ddev, "TT memory decryption enabled."); -+ drm_info_once(ddev, "TT memory decryption enabled."); - } - - bo->ttm = bdev->funcs->ttm_tt_create(bo, page_flags); -diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c -index 4aac88cc5f913..ae796e0c64aa5 100644 ---- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c -+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c -@@ -204,6 +204,7 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv, - VMW_BO_DOMAIN_VRAM, - VMW_BO_DOMAIN_VRAM); - buf->places[0].lpfn = PFN_UP(bo->resource->size); -+ buf->busy_places[0].lpfn = PFN_UP(bo->resource->size); - ret = ttm_bo_validate(bo, &buf->placement, &ctx); - - /* For some reason we didn't end up at the start of vram */ -diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c -index 2a0cda3247031..5efc6a766f64e 100644 ---- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c -+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c -@@ -991,7 +991,7 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv, - } - - event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED; -- event->event.base.length = sizeof(*event); -+ event->event.base.length = sizeof(event->event); - event->event.user_data = user_data; - - ret = drm_event_reserve_init(dev, file_priv, &event->base, &event->event.base); -diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c -index 84d042796d2e6..3937889fa912d 100644 ---- a/drivers/gpu/host1x/bus.c -+++ b/drivers/gpu/host1x/bus.c -@@ -351,11 +351,6 @@ static int host1x_device_uevent(const struct device *dev, - return 0; - } - --static int host1x_dma_configure(struct device *dev) --{ -- return of_dma_configure(dev, dev->of_node, true); --} -- - static const struct dev_pm_ops host1x_device_pm_ops = { - .suspend = pm_generic_suspend, - .resume = pm_generic_resume, -@@ -369,7 +364,6 @@ struct bus_type host1x_bus_type = { - .name = "host1x", - .match = host1x_device_match, - .uevent = host1x_device_uevent, -- .dma_configure = host1x_dma_configure, - .pm = &host1x_device_pm_ops, - }; - -@@ -458,8 +452,6 @@ static int host1x_device_add(struct host1x *host1x, - device->dev.bus = &host1x_bus_type; - device->dev.parent = host1x->dev; - -- of_dma_configure(&device->dev, host1x->dev->of_node, true); -- - device->dev.dma_parms = &device->dma_parms; - dma_set_max_seg_size(&device->dev, UINT_MAX); - -diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c -index 56f7e06c673e4..47e1bd8de9fcf 100644 ---- a/drivers/hv/channel.c -+++ b/drivers/hv/channel.c -@@ -153,7 +153,9 @@ void vmbus_free_ring(struct vmbus_channel *channel) - hv_ringbuffer_cleanup(&channel->inbound); - - if (channel->ringbuffer_page) { -- __free_pages(channel->ringbuffer_page, -+ /* In a CoCo VM leak the memory if it didn't get re-encrypted */ -+ if (!channel->ringbuffer_gpadlhandle.decrypted) -+ __free_pages(channel->ringbuffer_page, - get_order(channel->ringbuffer_pagecount - << PAGE_SHIFT)); - channel->ringbuffer_page = NULL; -@@ -472,9 +474,18 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, - (atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1); - - ret = create_gpadl_header(type, kbuffer, size, send_offset, &msginfo); -- if (ret) -+ if (ret) { -+ gpadl->decrypted = false; - return ret; -+ } - -+ /* -+ * Set the "decrypted" flag to true for the set_memory_decrypted() -+ * success case. In the failure case, the encryption state of the -+ * memory is unknown. Leave "decrypted" as true to ensure the -+ * memory will be leaked instead of going back on the free list. -+ */ -+ gpadl->decrypted = true; - ret = set_memory_decrypted((unsigned long)kbuffer, - PFN_UP(size)); - if (ret) { -@@ -563,9 +574,15 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, - - kfree(msginfo); - -- if (ret) -- set_memory_encrypted((unsigned long)kbuffer, -- PFN_UP(size)); -+ if (ret) { -+ /* -+ * If set_memory_encrypted() fails, the decrypted flag is -+ * left as true so the memory is leaked instead of being -+ * put back on the free list. -+ */ -+ if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size))) -+ gpadl->decrypted = false; -+ } - - return ret; - } -@@ -886,6 +903,8 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, struct vmbus_gpadl *gpad - if (ret) - pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret); - -+ gpadl->decrypted = ret; -+ - return ret; - } - EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); -diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c -index 3cabeeabb1cac..f001ae880e1db 100644 ---- a/drivers/hv/connection.c -+++ b/drivers/hv/connection.c -@@ -237,8 +237,17 @@ int vmbus_connect(void) - vmbus_connection.monitor_pages[0], 1); - ret |= set_memory_decrypted((unsigned long) - vmbus_connection.monitor_pages[1], 1); -- if (ret) -+ if (ret) { -+ /* -+ * If set_memory_decrypted() fails, the encryption state -+ * of the memory is unknown. So leak the memory instead -+ * of risking returning decrypted memory to the free list. -+ * For simplicity, always handle both pages the same. -+ */ -+ vmbus_connection.monitor_pages[0] = NULL; -+ vmbus_connection.monitor_pages[1] = NULL; - goto cleanup; -+ } - - /* - * Set_memory_decrypted() will change the memory contents if -@@ -337,13 +346,19 @@ void vmbus_disconnect(void) - vmbus_connection.int_page = NULL; - } - -- set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1); -- set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[1], 1); -+ if (vmbus_connection.monitor_pages[0]) { -+ if (!set_memory_encrypted( -+ (unsigned long)vmbus_connection.monitor_pages[0], 1)) -+ hv_free_hyperv_page(vmbus_connection.monitor_pages[0]); -+ vmbus_connection.monitor_pages[0] = NULL; -+ } - -- hv_free_hyperv_page(vmbus_connection.monitor_pages[0]); -- hv_free_hyperv_page(vmbus_connection.monitor_pages[1]); -- vmbus_connection.monitor_pages[0] = NULL; -- vmbus_connection.monitor_pages[1] = NULL; -+ if (vmbus_connection.monitor_pages[1]) { -+ if (!set_memory_encrypted( -+ (unsigned long)vmbus_connection.monitor_pages[1], 1)) -+ hv_free_hyperv_page(vmbus_connection.monitor_pages[1]); -+ vmbus_connection.monitor_pages[1] = NULL; -+ } - } - - /* -diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c -index 463ab4296ede5..280b90646a873 100644 ---- a/drivers/hwmon/corsair-cpro.c -+++ b/drivers/hwmon/corsair-cpro.c -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - #include - - #define USB_VENDOR_ID_CORSAIR 0x1b1c -@@ -77,8 +78,11 @@ - struct ccp_device { - struct hid_device *hdev; - struct device *hwmon_dev; -+ /* For reinitializing the completion below */ -+ spinlock_t wait_input_report_lock; - struct completion wait_input_report; - struct mutex mutex; /* whenever buffer is used, lock before send_usb_cmd */ -+ u8 *cmd_buffer; - u8 *buffer; - int target[6]; - DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS); -@@ -111,15 +115,23 @@ static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2, - unsigned long t; - int ret; - -- memset(ccp->buffer, 0x00, OUT_BUFFER_SIZE); -- ccp->buffer[0] = command; -- ccp->buffer[1] = byte1; -- ccp->buffer[2] = byte2; -- ccp->buffer[3] = byte3; -- -+ memset(ccp->cmd_buffer, 0x00, OUT_BUFFER_SIZE); -+ ccp->cmd_buffer[0] = command; -+ ccp->cmd_buffer[1] = byte1; -+ ccp->cmd_buffer[2] = byte2; -+ ccp->cmd_buffer[3] = byte3; -+ -+ /* -+ * Disable raw event parsing for a moment to safely reinitialize the -+ * completion. Reinit is done because hidraw could have triggered -+ * the raw event parsing and marked the ccp->wait_input_report -+ * completion as done. -+ */ -+ spin_lock_bh(&ccp->wait_input_report_lock); - reinit_completion(&ccp->wait_input_report); -+ spin_unlock_bh(&ccp->wait_input_report_lock); - -- ret = hid_hw_output_report(ccp->hdev, ccp->buffer, OUT_BUFFER_SIZE); -+ ret = hid_hw_output_report(ccp->hdev, ccp->cmd_buffer, OUT_BUFFER_SIZE); - if (ret < 0) - return ret; - -@@ -135,11 +147,12 @@ static int ccp_raw_event(struct hid_device *hdev, struct hid_report *report, u8 - struct ccp_device *ccp = hid_get_drvdata(hdev); - - /* only copy buffer when requested */ -- if (completion_done(&ccp->wait_input_report)) -- return 0; -- -- memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size)); -- complete(&ccp->wait_input_report); -+ spin_lock(&ccp->wait_input_report_lock); -+ if (!completion_done(&ccp->wait_input_report)) { -+ memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size)); -+ complete_all(&ccp->wait_input_report); -+ } -+ spin_unlock(&ccp->wait_input_report_lock); - - return 0; - } -@@ -492,7 +505,11 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) - if (!ccp) - return -ENOMEM; - -- ccp->buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL); -+ ccp->cmd_buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL); -+ if (!ccp->cmd_buffer) -+ return -ENOMEM; -+ -+ ccp->buffer = devm_kmalloc(&hdev->dev, IN_BUFFER_SIZE, GFP_KERNEL); - if (!ccp->buffer) - return -ENOMEM; - -@@ -510,7 +527,9 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) - - ccp->hdev = hdev; - hid_set_drvdata(hdev, ccp); -+ - mutex_init(&ccp->mutex); -+ spin_lock_init(&ccp->wait_input_report_lock); - init_completion(&ccp->wait_input_report); - - hid_device_io_start(hdev); -diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c -index 8d9d422450e5c..d817c719b90bd 100644 ---- a/drivers/hwmon/pmbus/ucd9000.c -+++ b/drivers/hwmon/pmbus/ucd9000.c -@@ -80,11 +80,11 @@ struct ucd9000_debugfs_entry { - * It has been observed that the UCD90320 randomly fails register access when - * doing another access right on the back of a register write. To mitigate this - * make sure that there is a minimum delay between a write access and the -- * following access. The 250us is based on experimental data. At a delay of -- * 200us the issue seems to go away. Add a bit of extra margin to allow for -+ * following access. The 500 is based on experimental data. At a delay of -+ * 350us the issue seems to go away. Add a bit of extra margin to allow for - * system to system differences. - */ --#define UCD90320_WAIT_DELAY_US 250 -+#define UCD90320_WAIT_DELAY_US 500 - - static inline void ucd90320_wait(const struct ucd9000_data *data) - { -diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c -index 75d142bc14b4f..b608aa5467175 100644 ---- a/drivers/iio/accel/mxc4005.c -+++ b/drivers/iio/accel/mxc4005.c -@@ -27,9 +27,13 @@ - #define MXC4005_REG_ZOUT_UPPER 0x07 - #define MXC4005_REG_ZOUT_LOWER 0x08 - -+#define MXC4005_REG_INT_MASK0 0x0A -+ - #define MXC4005_REG_INT_MASK1 0x0B - #define MXC4005_REG_INT_MASK1_BIT_DRDYE 0x01 - -+#define MXC4005_REG_INT_CLR0 0x00 -+ - #define MXC4005_REG_INT_CLR1 0x01 - #define MXC4005_REG_INT_CLR1_BIT_DRDYC 0x01 - -@@ -113,7 +117,9 @@ static bool mxc4005_is_readable_reg(struct device *dev, unsigned int reg) - static bool mxc4005_is_writeable_reg(struct device *dev, unsigned int reg) - { - switch (reg) { -+ case MXC4005_REG_INT_CLR0: - case MXC4005_REG_INT_CLR1: -+ case MXC4005_REG_INT_MASK0: - case MXC4005_REG_INT_MASK1: - case MXC4005_REG_CONTROL: - return true; -@@ -330,17 +336,13 @@ static int mxc4005_set_trigger_state(struct iio_trigger *trig, - { - struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); - struct mxc4005_data *data = iio_priv(indio_dev); -+ unsigned int val; - int ret; - - mutex_lock(&data->mutex); -- if (state) { -- ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, -- MXC4005_REG_INT_MASK1_BIT_DRDYE); -- } else { -- ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, -- ~MXC4005_REG_INT_MASK1_BIT_DRDYE); -- } - -+ val = state ? MXC4005_REG_INT_MASK1_BIT_DRDYE : 0; -+ ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, val); - if (ret < 0) { - mutex_unlock(&data->mutex); - dev_err(data->dev, "failed to update reg_int_mask1"); -@@ -382,6 +384,14 @@ static int mxc4005_chip_init(struct mxc4005_data *data) - - dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg); - -+ ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0); -+ if (ret < 0) -+ return dev_err_probe(data->dev, ret, "writing INT_MASK0\n"); -+ -+ ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, 0); -+ if (ret < 0) -+ return dev_err_probe(data->dev, ret, "writing INT_MASK1\n"); -+ - return 0; - } - -diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c -index 6c81dc5bf2c7a..b24e1e27f2da6 100644 ---- a/drivers/iio/imu/adis16475.c -+++ b/drivers/iio/imu/adis16475.c -@@ -1127,6 +1127,7 @@ static int adis16475_config_sync_mode(struct adis16475 *st) - struct device *dev = &st->adis.spi->dev; - const struct adis16475_sync *sync; - u32 sync_mode; -+ u16 val; - - /* default to internal clk */ - st->clk_freq = st->info->int_clk * 1000; -@@ -1188,8 +1189,9 @@ static int adis16475_config_sync_mode(struct adis16475 *st) - * I'm keeping this for simplicity and avoiding extra variables - * in chip_info. - */ -+ val = ADIS16475_SYNC_MODE(sync->sync_mode); - ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL, -- ADIS16475_SYNC_MODE_MASK, sync->sync_mode); -+ ADIS16475_SYNC_MODE_MASK, val); - if (ret) - return ret; - -diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c -index 967de99c1bb97..9de923228a9f4 100644 ---- a/drivers/iio/pressure/bmp280-spi.c -+++ b/drivers/iio/pressure/bmp280-spi.c -@@ -83,7 +83,7 @@ static const struct of_device_id bmp280_of_spi_match[] = { - { .compatible = "bosch,bmp180", .data = &bmp180_chip_info }, - { .compatible = "bosch,bmp181", .data = &bmp180_chip_info }, - { .compatible = "bosch,bmp280", .data = &bmp280_chip_info }, -- { .compatible = "bosch,bme280", .data = &bmp280_chip_info }, -+ { .compatible = "bosch,bme280", .data = &bme280_chip_info }, - { .compatible = "bosch,bmp380", .data = &bmp380_chip_info }, - { .compatible = "bosch,bmp580", .data = &bmp580_chip_info }, - { }, -@@ -95,7 +95,7 @@ static const struct spi_device_id bmp280_spi_id[] = { - { "bmp180", (kernel_ulong_t)&bmp180_chip_info }, - { "bmp181", (kernel_ulong_t)&bmp180_chip_info }, - { "bmp280", (kernel_ulong_t)&bmp280_chip_info }, -- { "bme280", (kernel_ulong_t)&bmp280_chip_info }, -+ { "bme280", (kernel_ulong_t)&bme280_chip_info }, - { "bmp380", (kernel_ulong_t)&bmp380_chip_info }, - { "bmp580", (kernel_ulong_t)&bmp580_chip_info }, - { } -diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c -index ed7d4b02f45a6..11155e0fb8395 100644 ---- a/drivers/infiniband/hw/qib/qib_fs.c -+++ b/drivers/infiniband/hw/qib/qib_fs.c -@@ -439,6 +439,7 @@ static int remove_device_files(struct super_block *sb, - return PTR_ERR(dir); - } - simple_recursive_removal(dir, NULL); -+ dput(dir); - return 0; - } - -diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c -index fab6c347ce578..de698463e94ad 100644 ---- a/drivers/iommu/mtk_iommu.c -+++ b/drivers/iommu/mtk_iommu.c -@@ -1773,6 +1773,7 @@ static const struct of_device_id mtk_iommu_of_ids[] = { - { .compatible = "mediatek,mt8365-m4u", .data = &mt8365_data}, - {} - }; -+MODULE_DEVICE_TABLE(of, mtk_iommu_of_ids); - - static struct platform_driver mtk_iommu_driver = { - .probe = mtk_iommu_probe, -diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c -index 8a0a5e5d049f4..f1754efcfe74e 100644 ---- a/drivers/iommu/mtk_iommu_v1.c -+++ b/drivers/iommu/mtk_iommu_v1.c -@@ -600,6 +600,7 @@ static const struct of_device_id mtk_iommu_v1_of_ids[] = { - { .compatible = "mediatek,mt2701-m4u", }, - {} - }; -+MODULE_DEVICE_TABLE(of, mtk_iommu_v1_of_ids); - - static const struct component_master_ops mtk_iommu_v1_com_ops = { - .bind = mtk_iommu_v1_bind, -diff --git a/drivers/md/md.c b/drivers/md/md.c -index 624259f79337f..e4d3741234d90 100644 ---- a/drivers/md/md.c -+++ b/drivers/md/md.c -@@ -2485,6 +2485,7 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev) - fail: - pr_warn("md: failed to register dev-%s for %s\n", - b, mdname(mddev)); -+ mddev_destroy_serial_pool(mddev, rdev, false); - return err; - } - -diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c -index dbbf7db4ff2f4..c290e849b2ed8 100644 ---- a/drivers/misc/eeprom/at24.c -+++ b/drivers/misc/eeprom/at24.c -@@ -581,6 +581,31 @@ static unsigned int at24_get_offset_adj(u8 flags, unsigned int byte_len) - } - } - -+static void at24_probe_temp_sensor(struct i2c_client *client) -+{ -+ struct at24_data *at24 = i2c_get_clientdata(client); -+ struct i2c_board_info info = { .type = "jc42" }; -+ int ret; -+ u8 val; -+ -+ /* -+ * Byte 2 has value 11 for DDR3, earlier versions don't -+ * support the thermal sensor present flag -+ */ -+ ret = at24_read(at24, 2, &val, 1); -+ if (ret || val != 11) -+ return; -+ -+ /* Byte 32, bit 7 is set if temp sensor is present */ -+ ret = at24_read(at24, 32, &val, 1); -+ if (ret || !(val & BIT(7))) -+ return; -+ -+ info.addr = 0x18 | (client->addr & 7); -+ -+ i2c_new_client_device(client->adapter, &info); -+} -+ - static int at24_probe(struct i2c_client *client) - { - struct regmap_config regmap_config = { }; -@@ -756,15 +781,6 @@ static int at24_probe(struct i2c_client *client) - } - pm_runtime_enable(dev); - -- at24->nvmem = devm_nvmem_register(dev, &nvmem_config); -- if (IS_ERR(at24->nvmem)) { -- pm_runtime_disable(dev); -- if (!pm_runtime_status_suspended(dev)) -- regulator_disable(at24->vcc_reg); -- return dev_err_probe(dev, PTR_ERR(at24->nvmem), -- "failed to register nvmem\n"); -- } -- - /* - * Perform a one-byte test read to verify that the chip is functional, - * unless powering on the device is to be avoided during probe (i.e. -@@ -780,6 +796,19 @@ static int at24_probe(struct i2c_client *client) - } - } - -+ at24->nvmem = devm_nvmem_register(dev, &nvmem_config); -+ if (IS_ERR(at24->nvmem)) { -+ pm_runtime_disable(dev); -+ if (!pm_runtime_status_suspended(dev)) -+ regulator_disable(at24->vcc_reg); -+ return dev_err_probe(dev, PTR_ERR(at24->nvmem), -+ "failed to register nvmem\n"); -+ } -+ -+ /* If this a SPD EEPROM, probe for DDR3 thermal sensor */ -+ if (cdata == &at24_data_spd) -+ at24_probe_temp_sensor(client); -+ - pm_runtime_idle(dev); - - if (writable) -diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h -index 3390ff5111033..d3c03d4edbeff 100644 ---- a/drivers/misc/mei/hw-me-regs.h -+++ b/drivers/misc/mei/hw-me-regs.h -@@ -115,6 +115,8 @@ - #define MEI_DEV_ID_ARL_S 0x7F68 /* Arrow Lake Point S */ - #define MEI_DEV_ID_ARL_H 0x7770 /* Arrow Lake Point H */ - -+#define MEI_DEV_ID_LNL_M 0xA870 /* Lunar Lake Point M */ -+ - /* - * MEI HW Section - */ -diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c -index bd4e3df44865e..3c2c28c8ba30a 100644 ---- a/drivers/misc/mei/pci-me.c -+++ b/drivers/misc/mei/pci-me.c -@@ -122,6 +122,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = { - {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_S, MEI_ME_PCH15_CFG)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_H, MEI_ME_PCH15_CFG)}, - -+ {MEI_PCI_DEVICE(MEI_DEV_ID_LNL_M, MEI_ME_PCH15_CFG)}, -+ - /* required last entry */ - {0, } - }; -diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c -index 9bd661be3ae93..5c32208b17a1d 100644 ---- a/drivers/mtd/mtdcore.c -+++ b/drivers/mtd/mtdcore.c -@@ -552,6 +552,7 @@ static int mtd_nvmem_add(struct mtd_info *mtd) - config.dev = &mtd->dev; - config.name = dev_name(&mtd->dev); - config.owner = THIS_MODULE; -+ config.add_legacy_fixed_of_cells = of_device_is_compatible(node, "nvmem-cells"); - config.reg_read = mtd_nvmem_reg_read; - config.size = mtd->size; - config.word_size = 1; -@@ -898,6 +899,7 @@ static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd, - config.name = compatible; - config.id = NVMEM_DEVID_AUTO; - config.owner = THIS_MODULE; -+ config.add_legacy_fixed_of_cells = !mtd_type_is_nand(mtd); - config.type = NVMEM_TYPE_OTP; - config.root_only = true; - config.ignore_wp = true; -diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c -index 8556502f06721..e5bac87941f61 100644 ---- a/drivers/net/dsa/mv88e6xxx/chip.c -+++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -697,6 +697,18 @@ static void mv88e6352_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, - } - } - -+static void mv88e632x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, -+ struct phylink_config *config) -+{ -+ unsigned long *supported = config->supported_interfaces; -+ -+ /* Translate the default cmode */ -+ mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); -+ -+ config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | -+ MAC_1000FD; -+} -+ - static void mv88e6341_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, - struct phylink_config *config) - { -@@ -4976,7 +4988,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { - .gpio_ops = &mv88e6352_gpio_ops, - .avb_ops = &mv88e6352_avb_ops, - .ptp_ops = &mv88e6352_ptp_ops, -- .phylink_get_caps = mv88e6185_phylink_get_caps, -+ .phylink_get_caps = mv88e632x_phylink_get_caps, - }; - - static const struct mv88e6xxx_ops mv88e6321_ops = { -@@ -5022,7 +5034,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { - .gpio_ops = &mv88e6352_gpio_ops, - .avb_ops = &mv88e6352_avb_ops, - .ptp_ops = &mv88e6352_ptp_ops, -- .phylink_get_caps = mv88e6185_phylink_get_caps, -+ .phylink_get_caps = mv88e632x_phylink_get_caps, - }; - - static const struct mv88e6xxx_ops mv88e6341_ops = { -@@ -5588,7 +5600,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { - .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141, - .family = MV88E6XXX_FAMILY_6341, - .name = "Marvell 88E6141", -- .num_databases = 4096, -+ .num_databases = 256, - .num_macs = 2048, - .num_ports = 6, - .num_internal_phys = 5, -@@ -6047,7 +6059,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { - .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341, - .family = MV88E6XXX_FAMILY_6341, - .name = "Marvell 88E6341", -- .num_databases = 4096, -+ .num_databases = 256, - .num_macs = 2048, - .num_internal_phys = 5, - .num_ports = 6, -diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c -index 89c8ddc6565ae..79d096a371ae7 100644 ---- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c -+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c -@@ -2,7 +2,7 @@ - /* - * Broadcom GENET (Gigabit Ethernet) controller driver - * -- * Copyright (c) 2014-2020 Broadcom -+ * Copyright (c) 2014-2024 Broadcom - */ - - #define pr_fmt(fmt) "bcmgenet: " fmt -@@ -2469,14 +2469,18 @@ static void umac_enable_set(struct bcmgenet_priv *priv, u32 mask, bool enable) - { - u32 reg; - -+ spin_lock_bh(&priv->reg_lock); - reg = bcmgenet_umac_readl(priv, UMAC_CMD); -- if (reg & CMD_SW_RESET) -+ if (reg & CMD_SW_RESET) { -+ spin_unlock_bh(&priv->reg_lock); - return; -+ } - if (enable) - reg |= mask; - else - reg &= ~mask; - bcmgenet_umac_writel(priv, reg, UMAC_CMD); -+ spin_unlock_bh(&priv->reg_lock); - - /* UniMAC stops on a packet boundary, wait for a full-size packet - * to be processed -@@ -2492,8 +2496,10 @@ static void reset_umac(struct bcmgenet_priv *priv) - udelay(10); - - /* issue soft reset and disable MAC while updating its registers */ -+ spin_lock_bh(&priv->reg_lock); - bcmgenet_umac_writel(priv, CMD_SW_RESET, UMAC_CMD); - udelay(2); -+ spin_unlock_bh(&priv->reg_lock); - } - - static void bcmgenet_intr_disable(struct bcmgenet_priv *priv) -@@ -3299,7 +3305,7 @@ static void bcmgenet_get_hw_addr(struct bcmgenet_priv *priv, - } - - /* Returns a reusable dma control register value */ --static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv) -+static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv, bool flush_rx) - { - unsigned int i; - u32 reg; -@@ -3324,6 +3330,14 @@ static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv) - udelay(10); - bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH); - -+ if (flush_rx) { -+ reg = bcmgenet_rbuf_ctrl_get(priv); -+ bcmgenet_rbuf_ctrl_set(priv, reg | BIT(0)); -+ udelay(10); -+ bcmgenet_rbuf_ctrl_set(priv, reg); -+ udelay(10); -+ } -+ - return dma_ctrl; - } - -@@ -3345,7 +3359,9 @@ static void bcmgenet_netif_start(struct net_device *dev) - struct bcmgenet_priv *priv = netdev_priv(dev); - - /* Start the network engine */ -+ netif_addr_lock_bh(dev); - bcmgenet_set_rx_mode(dev); -+ netif_addr_unlock_bh(dev); - bcmgenet_enable_rx_napi(priv); - - umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true); -@@ -3387,8 +3403,8 @@ static int bcmgenet_open(struct net_device *dev) - - bcmgenet_set_hw_addr(priv, dev->dev_addr); - -- /* Disable RX/TX DMA and flush TX queues */ -- dma_ctrl = bcmgenet_dma_disable(priv); -+ /* Disable RX/TX DMA and flush TX and RX queues */ -+ dma_ctrl = bcmgenet_dma_disable(priv, true); - - /* Reinitialize TDMA and RDMA and SW housekeeping */ - ret = bcmgenet_init_dma(priv); -@@ -3606,16 +3622,19 @@ static void bcmgenet_set_rx_mode(struct net_device *dev) - * 3. The number of filters needed exceeds the number filters - * supported by the hardware. - */ -+ spin_lock(&priv->reg_lock); - reg = bcmgenet_umac_readl(priv, UMAC_CMD); - if ((dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) || - (nfilter > MAX_MDF_FILTER)) { - reg |= CMD_PROMISC; - bcmgenet_umac_writel(priv, reg, UMAC_CMD); -+ spin_unlock(&priv->reg_lock); - bcmgenet_umac_writel(priv, 0, UMAC_MDF_CTRL); - return; - } else { - reg &= ~CMD_PROMISC; - bcmgenet_umac_writel(priv, reg, UMAC_CMD); -+ spin_unlock(&priv->reg_lock); - } - - /* update MDF filter */ -@@ -4017,6 +4036,7 @@ static int bcmgenet_probe(struct platform_device *pdev) - goto err; - } - -+ spin_lock_init(&priv->reg_lock); - spin_lock_init(&priv->lock); - - /* Set default pause parameters */ -@@ -4259,7 +4279,7 @@ static int bcmgenet_resume(struct device *d) - bcmgenet_hfb_create_rxnfc_filter(priv, rule); - - /* Disable RX/TX DMA and flush TX queues */ -- dma_ctrl = bcmgenet_dma_disable(priv); -+ dma_ctrl = bcmgenet_dma_disable(priv, false); - - /* Reinitialize TDMA and RDMA and SW housekeeping */ - ret = bcmgenet_init_dma(priv); -diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h -index 1985c0ec4da2a..28e2c94ef835c 100644 ---- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h -+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: GPL-2.0-only */ - /* -- * Copyright (c) 2014-2020 Broadcom -+ * Copyright (c) 2014-2024 Broadcom - */ - - #ifndef __BCMGENET_H__ -@@ -573,6 +573,8 @@ struct bcmgenet_rxnfc_rule { - /* device context */ - struct bcmgenet_priv { - void __iomem *base; -+ /* reg_lock: lock to serialize access to shared registers */ -+ spinlock_t reg_lock; - enum bcmgenet_version version; - struct net_device *dev; - -diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c -index 7a41cad5788f4..1248792d7fd4d 100644 ---- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c -+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c -@@ -2,7 +2,7 @@ - /* - * Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support - * -- * Copyright (c) 2014-2020 Broadcom -+ * Copyright (c) 2014-2024 Broadcom - */ - - #define pr_fmt(fmt) "bcmgenet_wol: " fmt -@@ -151,6 +151,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv, - } - - /* Can't suspend with WoL if MAC is still in reset */ -+ spin_lock_bh(&priv->reg_lock); - reg = bcmgenet_umac_readl(priv, UMAC_CMD); - if (reg & CMD_SW_RESET) - reg &= ~CMD_SW_RESET; -@@ -158,6 +159,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv, - /* disable RX */ - reg &= ~CMD_RX_EN; - bcmgenet_umac_writel(priv, reg, UMAC_CMD); -+ spin_unlock_bh(&priv->reg_lock); - mdelay(10); - - if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) { -@@ -203,6 +205,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv, - } - - /* Enable CRC forward */ -+ spin_lock_bh(&priv->reg_lock); - reg = bcmgenet_umac_readl(priv, UMAC_CMD); - priv->crc_fwd_en = 1; - reg |= CMD_CRC_FWD; -@@ -210,6 +213,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv, - /* Receiver must be enabled for WOL MP detection */ - reg |= CMD_RX_EN; - bcmgenet_umac_writel(priv, reg, UMAC_CMD); -+ spin_unlock_bh(&priv->reg_lock); - - reg = UMAC_IRQ_MPD_R; - if (hfb_enable) -@@ -256,7 +260,9 @@ void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv, - } - - /* Disable CRC Forward */ -+ spin_lock_bh(&priv->reg_lock); - reg = bcmgenet_umac_readl(priv, UMAC_CMD); - reg &= ~CMD_CRC_FWD; - bcmgenet_umac_writel(priv, reg, UMAC_CMD); -+ spin_unlock_bh(&priv->reg_lock); - } -diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c -index 97ea76d443abe..e7c659cd39746 100644 ---- a/drivers/net/ethernet/broadcom/genet/bcmmii.c -+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c -@@ -2,7 +2,7 @@ - /* - * Broadcom GENET MDIO routines - * -- * Copyright (c) 2014-2017 Broadcom -+ * Copyright (c) 2014-2024 Broadcom - */ - - #include -@@ -75,6 +75,7 @@ static void bcmgenet_mac_config(struct net_device *dev) - reg |= RGMII_LINK; - bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL); - -+ spin_lock_bh(&priv->reg_lock); - reg = bcmgenet_umac_readl(priv, UMAC_CMD); - reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) | - CMD_HD_EN | -@@ -87,6 +88,7 @@ static void bcmgenet_mac_config(struct net_device *dev) - reg |= CMD_TX_EN | CMD_RX_EN; - } - bcmgenet_umac_writel(priv, reg, UMAC_CMD); -+ spin_unlock_bh(&priv->reg_lock); - - priv->eee.eee_active = phy_init_eee(phydev, 0) >= 0; - bcmgenet_eee_enable_set(dev, -@@ -274,6 +276,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) - * block for the interface to work, unconditionally clear the - * Out-of-band disable since we do not need it. - */ -+ mutex_lock(&phydev->lock); - reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL); - reg &= ~OOB_DISABLE; - if (priv->ext_phy) { -@@ -285,6 +288,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) - reg |= RGMII_MODE_EN; - } - bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL); -+ mutex_unlock(&phydev->lock); - - if (init) - dev_info(kdev, "configuring instance for %s\n", phy_name); -diff --git a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c -index 7246e13dd559f..97291bfbeea58 100644 ---- a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c -+++ b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c -@@ -312,7 +312,7 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf, - void *kern_buf; - - /* Copy the user space buf */ -- kern_buf = memdup_user(buf, nbytes); -+ kern_buf = memdup_user_nul(buf, nbytes); - if (IS_ERR(kern_buf)) - return PTR_ERR(kern_buf); - -@@ -372,7 +372,7 @@ bnad_debugfs_write_regwr(struct file *file, const char __user *buf, - void *kern_buf; - - /* Copy the user space buf */ -- kern_buf = memdup_user(buf, nbytes); -+ kern_buf = memdup_user_nul(buf, nbytes); - if (IS_ERR(kern_buf)) - return PTR_ERR(kern_buf); - -diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c -index 98dd78551d89a..fff1ce835bc0d 100644 ---- a/drivers/net/ethernet/chelsio/cxgb4/sge.c -+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c -@@ -2684,12 +2684,12 @@ int cxgb4_selftest_lb_pkt(struct net_device *netdev) - lb->loopback = 1; - - q = &adap->sge.ethtxq[pi->first_qset]; -- __netif_tx_lock(q->txq, smp_processor_id()); -+ __netif_tx_lock_bh(q->txq); - - reclaim_completed_tx(adap, &q->q, -1, true); - credits = txq_avail(&q->q) - ndesc; - if (unlikely(credits < 0)) { -- __netif_tx_unlock(q->txq); -+ __netif_tx_unlock_bh(q->txq); - return -ENOMEM; - } - -@@ -2724,7 +2724,7 @@ int cxgb4_selftest_lb_pkt(struct net_device *netdev) - init_completion(&lb->completion); - txq_advance(&q->q, ndesc); - cxgb4_ring_tx_db(adap, &q->q, ndesc); -- __netif_tx_unlock(q->txq); -+ __netif_tx_unlock_bh(q->txq); - - /* wait for the pkt to return */ - ret = wait_for_completion_timeout(&lb->completion, 10 * HZ); -diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h -index aaf1f42624a79..57787c380fa07 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h -+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h -@@ -890,7 +890,7 @@ struct hnae3_handle { - struct hnae3_roce_private_info rinfo; - }; - -- u32 numa_node_mask; /* for multi-chip support */ -+ nodemask_t numa_node_mask; /* for multi-chip support */ - - enum hnae3_port_base_vlan_state port_base_vlan_state; - -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c -index dfd0c5f4cb9f5..14713454e0d82 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c -@@ -1526,6 +1526,9 @@ static int hclge_configure(struct hclge_dev *hdev) - cfg.default_speed, ret); - return ret; - } -+ hdev->hw.mac.req_speed = hdev->hw.mac.speed; -+ hdev->hw.mac.req_autoneg = AUTONEG_ENABLE; -+ hdev->hw.mac.req_duplex = DUPLEX_FULL; - - hclge_parse_link_mode(hdev, cfg.speed_ability); - -@@ -1755,7 +1758,8 @@ static int hclge_vport_setup(struct hclge_vport *vport, u16 num_tqps) - - nic->pdev = hdev->pdev; - nic->ae_algo = &ae_algo; -- nic->numa_node_mask = hdev->numa_node_mask; -+ bitmap_copy(nic->numa_node_mask.bits, hdev->numa_node_mask.bits, -+ MAX_NUMNODES); - nic->kinfo.io_base = hdev->hw.hw.io_base; - - ret = hclge_knic_setup(vport, num_tqps, -@@ -2447,7 +2451,8 @@ static int hclge_init_roce_base_info(struct hclge_vport *vport) - - roce->pdev = nic->pdev; - roce->ae_algo = nic->ae_algo; -- roce->numa_node_mask = nic->numa_node_mask; -+ bitmap_copy(roce->numa_node_mask.bits, nic->numa_node_mask.bits, -+ MAX_NUMNODES); - - return 0; - } -@@ -3331,9 +3336,9 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle, - return ret; - } - -- hdev->hw.mac.autoneg = cmd->base.autoneg; -- hdev->hw.mac.speed = cmd->base.speed; -- hdev->hw.mac.duplex = cmd->base.duplex; -+ hdev->hw.mac.req_autoneg = cmd->base.autoneg; -+ hdev->hw.mac.req_speed = cmd->base.speed; -+ hdev->hw.mac.req_duplex = cmd->base.duplex; - linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising); - - return 0; -@@ -3366,9 +3371,9 @@ static int hclge_tp_port_init(struct hclge_dev *hdev) - if (!hnae3_dev_phy_imp_supported(hdev)) - return 0; - -- cmd.base.autoneg = hdev->hw.mac.autoneg; -- cmd.base.speed = hdev->hw.mac.speed; -- cmd.base.duplex = hdev->hw.mac.duplex; -+ cmd.base.autoneg = hdev->hw.mac.req_autoneg; -+ cmd.base.speed = hdev->hw.mac.req_speed; -+ cmd.base.duplex = hdev->hw.mac.req_duplex; - linkmode_copy(cmd.link_modes.advertising, hdev->hw.mac.advertising); - - return hclge_set_phy_link_ksettings(&hdev->vport->nic, &cmd); -@@ -7940,8 +7945,7 @@ static void hclge_set_timer_task(struct hnae3_handle *handle, bool enable) - /* Set the DOWN flag here to disable link updating */ - set_bit(HCLGE_STATE_DOWN, &hdev->state); - -- /* flush memory to make sure DOWN is seen by service task */ -- smp_mb__before_atomic(); -+ smp_mb__after_atomic(); /* flush memory to make sure DOWN is seen by service task */ - hclge_flush_link_update(hdev); - } - } -@@ -9894,6 +9898,7 @@ static int hclge_set_vlan_protocol_type(struct hclge_dev *hdev) - static int hclge_init_vlan_filter(struct hclge_dev *hdev) - { - struct hclge_vport *vport; -+ bool enable = true; - int ret; - int i; - -@@ -9913,8 +9918,12 @@ static int hclge_init_vlan_filter(struct hclge_dev *hdev) - vport->cur_vlan_fltr_en = true; - } - -+ if (test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, hdev->ae_dev->caps) && -+ !test_bit(HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, hdev->ae_dev->caps)) -+ enable = false; -+ - return hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT, -- HCLGE_FILTER_FE_INGRESS, true, 0); -+ HCLGE_FILTER_FE_INGRESS, enable, 0); - } - - static int hclge_init_vlan_type(struct hclge_dev *hdev) -@@ -11610,16 +11619,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) - if (ret) - goto out; - -- ret = hclge_devlink_init(hdev); -- if (ret) -- goto err_pci_uninit; -- -- devl_lock(hdev->devlink); -- - /* Firmware command queue initialize */ - ret = hclge_comm_cmd_queue_init(hdev->pdev, &hdev->hw.hw); - if (ret) -- goto err_devlink_uninit; -+ goto err_pci_uninit; - - /* Firmware command initialize */ - ret = hclge_comm_cmd_init(hdev->ae_dev, &hdev->hw.hw, &hdev->fw_version, -@@ -11747,7 +11750,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) - - ret = hclge_update_port_info(hdev); - if (ret) -- goto err_mdiobus_unreg; -+ goto err_ptp_uninit; - - INIT_KFIFO(hdev->mac_tnl_log); - -@@ -11787,6 +11790,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) - dev_warn(&pdev->dev, - "failed to wake on lan init, ret = %d\n", ret); - -+ ret = hclge_devlink_init(hdev); -+ if (ret) -+ goto err_ptp_uninit; -+ - hclge_state_init(hdev); - hdev->last_reset_time = jiffies; - -@@ -11794,10 +11801,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) - HCLGE_DRIVER_NAME); - - hclge_task_schedule(hdev, round_jiffies_relative(HZ)); -- -- devl_unlock(hdev->devlink); - return 0; - -+err_ptp_uninit: -+ hclge_ptp_uninit(hdev); - err_mdiobus_unreg: - if (hdev->hw.mac.phydev) - mdiobus_unregister(hdev->hw.mac.mdio_bus); -@@ -11807,9 +11814,6 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) - pci_free_irq_vectors(pdev); - err_cmd_uninit: - hclge_comm_cmd_uninit(hdev->ae_dev, &hdev->hw.hw); --err_devlink_uninit: -- devl_unlock(hdev->devlink); -- hclge_devlink_uninit(hdev); - err_pci_uninit: - pcim_iounmap(pdev, hdev->hw.hw.io_base); - pci_release_regions(pdev); -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h -index 7bc2049b723da..76a5edfe7d2e5 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h -@@ -263,11 +263,14 @@ struct hclge_mac { - u8 media_type; /* port media type, e.g. fibre/copper/backplane */ - u8 mac_addr[ETH_ALEN]; - u8 autoneg; -+ u8 req_autoneg; - u8 duplex; -+ u8 req_duplex; - u8 support_autoneg; - u8 speed_type; /* 0: sfp speed, 1: active speed */ - u8 lane_num; - u32 speed; -+ u32 req_speed; - u32 max_speed; - u32 speed_ability; /* speed ability supported by current media */ - u32 module_type; /* sub media type, e.g. kr/cr/sr/lr */ -@@ -875,7 +878,7 @@ struct hclge_dev { - - u16 fdir_pf_filter_count; /* Num of guaranteed filters for this PF */ - u16 num_alloc_vport; /* Num vports this driver supports */ -- u32 numa_node_mask; -+ nodemask_t numa_node_mask; - u16 rx_buf_len; - u16 num_tx_desc; /* desc num of per tx queue */ - u16 num_rx_desc; /* desc num of per rx queue */ -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c -index 04ff9bf121853..877feee53804f 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c -@@ -1077,12 +1077,13 @@ static void hclge_mbx_request_handling(struct hclge_mbx_ops_param *param) - - hdev = param->vport->back; - cmd_func = hclge_mbx_ops_list[param->req->msg.code]; -- if (cmd_func) -- ret = cmd_func(param); -- else -+ if (!cmd_func) { - dev_err(&hdev->pdev->dev, - "un-supported mailbox message, code = %u\n", - param->req->msg.code); -+ return; -+ } -+ ret = cmd_func(param); - - /* PF driver should not reply IMP */ - if (hnae3_get_bit(param->req->mbx_need_resp, HCLGE_MBX_NEED_RESP_B) && -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c -index 0aa9beefd1c7e..43ee20eb03d1f 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c -@@ -412,7 +412,8 @@ static int hclgevf_set_handle_info(struct hclgevf_dev *hdev) - - nic->ae_algo = &ae_algovf; - nic->pdev = hdev->pdev; -- nic->numa_node_mask = hdev->numa_node_mask; -+ bitmap_copy(nic->numa_node_mask.bits, hdev->numa_node_mask.bits, -+ MAX_NUMNODES); - nic->flags |= HNAE3_SUPPORT_VF; - nic->kinfo.io_base = hdev->hw.hw.io_base; - -@@ -2082,8 +2083,8 @@ static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev) - - roce->pdev = nic->pdev; - roce->ae_algo = nic->ae_algo; -- roce->numa_node_mask = nic->numa_node_mask; -- -+ bitmap_copy(roce->numa_node_mask.bits, nic->numa_node_mask.bits, -+ MAX_NUMNODES); - return 0; - } - -@@ -2180,8 +2181,7 @@ static void hclgevf_set_timer_task(struct hnae3_handle *handle, bool enable) - } else { - set_bit(HCLGEVF_STATE_DOWN, &hdev->state); - -- /* flush memory to make sure DOWN is seen by service task */ -- smp_mb__before_atomic(); -+ smp_mb__after_atomic(); /* flush memory to make sure DOWN is seen by service task */ - hclgevf_flush_link_update(hdev); - } - } -@@ -2845,10 +2845,6 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) - if (ret) - return ret; - -- ret = hclgevf_devlink_init(hdev); -- if (ret) -- goto err_devlink_init; -- - ret = hclge_comm_cmd_queue_init(hdev->pdev, &hdev->hw.hw); - if (ret) - goto err_cmd_queue_init; -@@ -2941,6 +2937,10 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) - - hclgevf_init_rxd_adv_layout(hdev); - -+ ret = hclgevf_devlink_init(hdev); -+ if (ret) -+ goto err_config; -+ - set_bit(HCLGEVF_STATE_SERVICE_INITED, &hdev->state); - - hdev->last_reset_time = jiffies; -@@ -2960,8 +2960,6 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) - err_cmd_init: - hclge_comm_cmd_uninit(hdev->ae_dev, &hdev->hw.hw); - err_cmd_queue_init: -- hclgevf_devlink_uninit(hdev); --err_devlink_init: - hclgevf_pci_uninit(hdev); - clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state); - return ret; -diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h -index a73f2bf3a56a6..cccef32284616 100644 ---- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h -+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h -@@ -236,7 +236,7 @@ struct hclgevf_dev { - u16 rss_size_max; /* HW defined max RSS task queue */ - - u16 num_alloc_vport; /* num vports this driver supports */ -- u32 numa_node_mask; -+ nodemask_t numa_node_mask; - u16 rx_buf_len; - u16 num_tx_desc; /* desc num of per tx queue */ - u16 num_rx_desc; /* desc num of per rx queue */ -diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c -index 395746bcf8f7c..8bf44103fb910 100644 ---- a/drivers/net/ethernet/intel/e1000e/phy.c -+++ b/drivers/net/ethernet/intel/e1000e/phy.c -@@ -157,7 +157,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { -- usleep_range(50, 60); -+ udelay(50); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; -@@ -181,7 +181,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) - * reading duplicate data in the next MDIC transaction. - */ - if (hw->mac.type == e1000_pch2lan) -- usleep_range(100, 150); -+ udelay(100); - - if (success) { - *data = (u16)mdic; -@@ -237,7 +237,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { -- usleep_range(50, 60); -+ udelay(50); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; -@@ -261,7 +261,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) - * reading duplicate data in the next MDIC transaction. - */ - if (hw->mac.type == e1000_pch2lan) -- usleep_range(100, 150); -+ udelay(100); - - if (success) - return 0; -diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c -index d30e84803481d..feca86e429df2 100644 ---- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c -+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c -@@ -999,12 +999,10 @@ static ssize_t rvu_dbg_qsize_write(struct file *filp, - u16 pcifunc; - int ret, lf; - -- cmd_buf = memdup_user(buffer, count + 1); -+ cmd_buf = memdup_user_nul(buffer, count); - if (IS_ERR(cmd_buf)) - return -ENOMEM; - -- cmd_buf[count] = '\0'; -- - cmd_buf_tmp = strchr(cmd_buf, '\n'); - if (cmd_buf_tmp) { - *cmd_buf_tmp = '\0'; -diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c -index d4cdf3d4f5525..502518cdb4618 100644 ---- a/drivers/net/ethernet/micrel/ks8851_common.c -+++ b/drivers/net/ethernet/micrel/ks8851_common.c -@@ -234,12 +234,13 @@ static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt) - /** - * ks8851_rx_pkts - receive packets from the host - * @ks: The device information. -+ * @rxq: Queue of packets received in this function. - * - * This is called from the IRQ work queue when the system detects that there - * are packets in the receive queue. Find out how many packets there are and - * read them from the FIFO. - */ --static void ks8851_rx_pkts(struct ks8851_net *ks) -+static void ks8851_rx_pkts(struct ks8851_net *ks, struct sk_buff_head *rxq) - { - struct sk_buff *skb; - unsigned rxfc; -@@ -299,7 +300,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) - ks8851_dbg_dumpkkt(ks, rxpkt); - - skb->protocol = eth_type_trans(skb, ks->netdev); -- __netif_rx(skb); -+ __skb_queue_tail(rxq, skb); - - ks->netdev->stats.rx_packets++; - ks->netdev->stats.rx_bytes += rxlen; -@@ -326,11 +327,11 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) - static irqreturn_t ks8851_irq(int irq, void *_ks) - { - struct ks8851_net *ks = _ks; -+ struct sk_buff_head rxq; - unsigned handled = 0; - unsigned long flags; - unsigned int status; -- -- local_bh_disable(); -+ struct sk_buff *skb; - - ks8851_lock(ks, &flags); - -@@ -384,7 +385,8 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) - * from the device so do not bother masking just the RX - * from the device. */ - -- ks8851_rx_pkts(ks); -+ __skb_queue_head_init(&rxq); -+ ks8851_rx_pkts(ks, &rxq); - } - - /* if something stopped the rx process, probably due to wanting -@@ -408,7 +410,9 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) - if (status & IRQ_LCI) - mii_check_link(&ks->mii); - -- local_bh_enable(); -+ if (status & IRQ_RXI) -+ while ((skb = __skb_dequeue(&rxq))) -+ netif_rx(skb); - - return IRQ_HANDLED; - } -diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c -index a5ac21a0ee33f..cb6b33a228ea2 100644 ---- a/drivers/net/ethernet/qlogic/qede/qede_filter.c -+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c -@@ -1868,8 +1868,8 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto, - struct flow_cls_offload *f) - { - struct qede_arfs_fltr_node *n; -- int min_hlen, rc = -EINVAL; - struct qede_arfs_tuple t; -+ int min_hlen, rc; - - __qede_lock(edev); - -@@ -1879,7 +1879,8 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto, - } - - /* parse flower attribute and prepare filter */ -- if (qede_parse_flow_attr(edev, proto, f->rule, &t)) -+ rc = qede_parse_flow_attr(edev, proto, f->rule, &t); -+ if (rc) - goto unlock; - - /* Validate profile mode and number of filters */ -@@ -1888,11 +1889,13 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto, - DP_NOTICE(edev, - "Filter configuration invalidated, filter mode=0x%x, configured mode=0x%x, filter count=0x%x\n", - t.mode, edev->arfs->mode, edev->arfs->filter_count); -+ rc = -EINVAL; - goto unlock; - } - - /* parse tc actions and get the vf_id */ -- if (qede_parse_actions(edev, &f->rule->action, f->common.extack)) -+ rc = qede_parse_actions(edev, &f->rule->action, f->common.extack); -+ if (rc) - goto unlock; - - if (qede_flow_find_fltr(edev, &t)) { -@@ -1998,10 +2001,9 @@ static int qede_flow_spec_to_rule(struct qede_dev *edev, - if (IS_ERR(flow)) - return PTR_ERR(flow); - -- if (qede_parse_flow_attr(edev, proto, flow->rule, t)) { -- err = -EINVAL; -+ err = qede_parse_flow_attr(edev, proto, flow->rule, t); -+ if (err) - goto err_out; -- } - - /* Make sure location is valid and filter isn't already set */ - err = qede_flow_spec_validate(edev, &flow->rule->action, t, -diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c -index 4f9658a741024..b2f27e505f76c 100644 ---- a/drivers/net/hyperv/netvsc.c -+++ b/drivers/net/hyperv/netvsc.c -@@ -154,8 +154,11 @@ static void free_netvsc_device(struct rcu_head *head) - int i; - - kfree(nvdev->extension); -- vfree(nvdev->recv_buf); -- vfree(nvdev->send_buf); -+ -+ if (!nvdev->recv_buf_gpadl_handle.decrypted) -+ vfree(nvdev->recv_buf); -+ if (!nvdev->send_buf_gpadl_handle.decrypted) -+ vfree(nvdev->send_buf); - bitmap_free(nvdev->send_section_map); - - for (i = 0; i < VRSS_CHANNEL_MAX; i++) { -diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c -index e2e181378f412..edc34402e787f 100644 ---- a/drivers/net/usb/qmi_wwan.c -+++ b/drivers/net/usb/qmi_wwan.c -@@ -1431,6 +1431,7 @@ static const struct usb_device_id products[] = { - {QMI_FIXED_INTF(0x2692, 0x9025, 4)}, /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */ - {QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */ - {QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */ -+ {QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */ - - /* 4. Gobi 1000 devices */ - {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ -diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c -index ecdf0276004f9..f98069920e27f 100644 ---- a/drivers/net/vxlan/vxlan_core.c -+++ b/drivers/net/vxlan/vxlan_core.c -@@ -1674,6 +1674,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb) - bool raw_proto = false; - void *oiph; - __be32 vni = 0; -+ int nh; - - /* Need UDP and VXLAN header to be present */ - if (!pskb_may_pull(skb, VXLAN_HLEN)) -@@ -1762,12 +1763,28 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb) - skb->pkt_type = PACKET_HOST; - } - -- oiph = skb_network_header(skb); -+ /* Save offset of outer header relative to skb->head, -+ * because we are going to reset the network header to the inner header -+ * and might change skb->head. -+ */ -+ nh = skb_network_header(skb) - skb->head; -+ - skb_reset_network_header(skb); - -+ if (!pskb_inet_may_pull(skb)) { -+ DEV_STATS_INC(vxlan->dev, rx_length_errors); -+ DEV_STATS_INC(vxlan->dev, rx_errors); -+ vxlan_vnifilter_count(vxlan, vni, vninode, -+ VXLAN_VNI_STATS_RX_ERRORS, 0); -+ goto drop; -+ } -+ -+ /* Get the outer header. */ -+ oiph = skb->head + nh; -+ - if (!vxlan_ecn_decapsulate(vs, oiph, skb)) { -- ++vxlan->dev->stats.rx_frame_errors; -- ++vxlan->dev->stats.rx_errors; -+ DEV_STATS_INC(vxlan->dev, rx_frame_errors); -+ DEV_STATS_INC(vxlan->dev, rx_errors); - vxlan_vnifilter_count(vxlan, vni, vninode, - VXLAN_VNI_STATS_RX_ERRORS, 0); - goto drop; -@@ -1837,7 +1854,9 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) - goto out; - - if (!pskb_may_pull(skb, arp_hdr_len(dev))) { -- dev->stats.tx_dropped++; -+ dev_core_stats_tx_dropped_inc(dev); -+ vxlan_vnifilter_count(vxlan, vni, NULL, -+ VXLAN_VNI_STATS_TX_DROPS, 0); - goto out; - } - parp = arp_hdr(skb); -@@ -1893,7 +1912,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) - reply->pkt_type = PACKET_HOST; - - if (netif_rx(reply) == NET_RX_DROP) { -- dev->stats.rx_dropped++; -+ dev_core_stats_rx_dropped_inc(dev); - vxlan_vnifilter_count(vxlan, vni, NULL, - VXLAN_VNI_STATS_RX_DROPS, 0); - } -@@ -2052,7 +2071,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) - goto out; - - if (netif_rx(reply) == NET_RX_DROP) { -- dev->stats.rx_dropped++; -+ dev_core_stats_rx_dropped_inc(dev); - vxlan_vnifilter_count(vxlan, vni, NULL, - VXLAN_VNI_STATS_RX_DROPS, 0); - } -@@ -2371,7 +2390,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, - len); - } else { - drop: -- dev->stats.rx_dropped++; -+ dev_core_stats_rx_dropped_inc(dev); - vxlan_vnifilter_count(dst_vxlan, vni, NULL, - VXLAN_VNI_STATS_RX_DROPS, 0); - } -@@ -2403,7 +2422,7 @@ static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev, - daddr->sa.sa_family, dst_port, - vxlan->cfg.flags); - if (!dst_vxlan) { -- dev->stats.tx_errors++; -+ DEV_STATS_INC(dev, tx_errors); - vxlan_vnifilter_count(vxlan, vni, NULL, - VXLAN_VNI_STATS_TX_ERRORS, 0); - kfree_skb(skb); -@@ -2664,7 +2683,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, - return; - - drop: -- dev->stats.tx_dropped++; -+ dev_core_stats_tx_dropped_inc(dev); - vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_DROPS, 0); - dev_kfree_skb(skb); - return; -@@ -2672,11 +2691,11 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, - tx_error: - rcu_read_unlock(); - if (err == -ELOOP) -- dev->stats.collisions++; -+ DEV_STATS_INC(dev, collisions); - else if (err == -ENETUNREACH) -- dev->stats.tx_carrier_errors++; -+ DEV_STATS_INC(dev, tx_carrier_errors); - dst_release(ndst); -- dev->stats.tx_errors++; -+ DEV_STATS_INC(dev, tx_errors); - vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_ERRORS, 0); - kfree_skb(skb); - } -@@ -2709,7 +2728,7 @@ static void vxlan_xmit_nh(struct sk_buff *skb, struct net_device *dev, - return; - - drop: -- dev->stats.tx_dropped++; -+ dev_core_stats_tx_dropped_inc(dev); - vxlan_vnifilter_count(netdev_priv(dev), vni, NULL, - VXLAN_VNI_STATS_TX_DROPS, 0); - dev_kfree_skb(skb); -@@ -2747,7 +2766,7 @@ static netdev_tx_t vxlan_xmit_nhid(struct sk_buff *skb, struct net_device *dev, - return NETDEV_TX_OK; - - drop: -- dev->stats.tx_dropped++; -+ dev_core_stats_tx_dropped_inc(dev); - vxlan_vnifilter_count(netdev_priv(dev), vni, NULL, - VXLAN_VNI_STATS_TX_DROPS, 0); - dev_kfree_skb(skb); -@@ -2844,7 +2863,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) - !is_multicast_ether_addr(eth->h_dest)) - vxlan_fdb_miss(vxlan, eth->h_dest); - -- dev->stats.tx_dropped++; -+ dev_core_stats_tx_dropped_inc(dev); - vxlan_vnifilter_count(vxlan, vni, NULL, - VXLAN_VNI_STATS_TX_DROPS, 0); - kfree_skb(skb); -diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c -index 1ccbe8c1eeb42..278454c116fee 100644 ---- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c -+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c -@@ -853,10 +853,15 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - - int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, u8 sta_id) - { -- int ret = iwl_mvm_mld_rm_sta_from_fw(mvm, sta_id); -+ int ret; - - lockdep_assert_held(&mvm->mutex); - -+ if (WARN_ON(sta_id == IWL_MVM_INVALID_STA)) -+ return 0; -+ -+ ret = iwl_mvm_mld_rm_sta_from_fw(mvm, sta_id); -+ - RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL); - RCU_INIT_POINTER(mvm->fw_id_to_link_sta[sta_id], NULL); - return ret; -diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c -index ca74b1b63cac1..0efa304904bd3 100644 ---- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c -+++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c -@@ -1588,9 +1588,9 @@ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn, - return; - - tfd_num = iwl_txq_get_cmd_index(txq, ssn); -- read_ptr = iwl_txq_get_cmd_index(txq, txq->read_ptr); - - spin_lock_bh(&txq->lock); -+ read_ptr = iwl_txq_get_cmd_index(txq, txq->read_ptr); - - if (!test_bit(txq_id, trans->txqs.queue_used)) { - IWL_DEBUG_TX_QUEUES(trans, "Q %d inactive - ignoring idx %d\n", -diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c -index 012c8b3f5f9c9..2db71e222fa7d 100644 ---- a/drivers/nvme/host/core.c -+++ b/drivers/nvme/host/core.c -@@ -3540,7 +3540,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info) - "Found shared namespace %d, but multipathing not supported.\n", - info->nsid); - dev_warn_once(ctrl->device, -- "Support for shared namespaces without CONFIG_NVME_MULTIPATH is deprecated and will be removed in Linux 6.0\n."); -+ "Support for shared namespaces without CONFIG_NVME_MULTIPATH is deprecated and will be removed in Linux 6.0.\n"); - } - } - -diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h -index ba62d42d2a8b7..176e372a5a796 100644 ---- a/drivers/nvme/host/nvme.h -+++ b/drivers/nvme/host/nvme.h -@@ -161,6 +161,11 @@ enum nvme_quirks { - * Disables simple suspend/resume path. - */ - NVME_QUIRK_FORCE_NO_SIMPLE_SUSPEND = (1 << 20), -+ -+ /* -+ * MSI (but not MSI-X) interrupts are broken and never fire. -+ */ -+ NVME_QUIRK_BROKEN_MSI = (1 << 21), - }; - - /* -diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c -index b985142fb84b9..e47172bd84efe 100644 ---- a/drivers/nvme/host/pci.c -+++ b/drivers/nvme/host/pci.c -@@ -2216,6 +2216,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues) - .priv = dev, - }; - unsigned int irq_queues, poll_queues; -+ unsigned int flags = PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY; - - /* - * Poll queues don't need interrupts, but we need at least one I/O queue -@@ -2239,8 +2240,10 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues) - irq_queues = 1; - if (!(dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR)) - irq_queues += (nr_io_queues - poll_queues); -- return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues, -- PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd); -+ if (dev->ctrl.quirks & NVME_QUIRK_BROKEN_MSI) -+ flags &= ~PCI_IRQ_MSI; -+ return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues, flags, -+ &affd); - } - - static unsigned int nvme_max_io_queues(struct nvme_dev *dev) -@@ -2469,6 +2472,7 @@ static int nvme_pci_enable(struct nvme_dev *dev) - { - int result = -ENOMEM; - struct pci_dev *pdev = to_pci_dev(dev->dev); -+ unsigned int flags = PCI_IRQ_ALL_TYPES; - - if (pci_enable_device_mem(pdev)) - return result; -@@ -2485,7 +2489,9 @@ static int nvme_pci_enable(struct nvme_dev *dev) - * interrupts. Pre-enable a single MSIX or MSI vec for setup. We'll - * adjust this later. - */ -- result = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); -+ if (dev->ctrl.quirks & NVME_QUIRK_BROKEN_MSI) -+ flags &= ~PCI_IRQ_MSI; -+ result = pci_alloc_irq_vectors(pdev, 1, 1, flags); - if (result < 0) - goto disable; - -@@ -3382,6 +3388,8 @@ static const struct pci_device_id nvme_id_table[] = { - .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY | - NVME_QUIRK_DISABLE_WRITE_ZEROES| - NVME_QUIRK_IGNORE_DEV_SUBNQN, }, -+ { PCI_DEVICE(0x15b7, 0x5008), /* Sandisk SN530 */ -+ .driver_data = NVME_QUIRK_BROKEN_MSI }, - { PCI_DEVICE(0x1987, 0x5012), /* Phison E12 */ - .driver_data = NVME_QUIRK_BOGUS_NID, }, - { PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */ -diff --git a/drivers/nvmem/apple-efuses.c b/drivers/nvmem/apple-efuses.c -index 9b7c871021043..d3d49d22338b3 100644 ---- a/drivers/nvmem/apple-efuses.c -+++ b/drivers/nvmem/apple-efuses.c -@@ -36,6 +36,7 @@ static int apple_efuses_probe(struct platform_device *pdev) - struct resource *res; - struct nvmem_config config = { - .dev = &pdev->dev, -+ .add_legacy_fixed_of_cells = true, - .read_only = true, - .reg_read = apple_efuses_read, - .stride = sizeof(u32), -diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c -index 5b3955ad40534..e26f79a132bb5 100644 ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -1003,9 +1003,11 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) - if (rval) - goto err_remove_cells; - -- rval = nvmem_add_cells_from_legacy_of(nvmem); -- if (rval) -- goto err_remove_cells; -+ if (config->add_legacy_fixed_of_cells) { -+ rval = nvmem_add_cells_from_legacy_of(nvmem); -+ if (rval) -+ goto err_remove_cells; -+ } - - rval = nvmem_add_cells_from_fixed_layout(nvmem); - if (rval) -diff --git a/drivers/nvmem/imx-ocotp-scu.c b/drivers/nvmem/imx-ocotp-scu.c -index c38d9c1c3f486..517d83e11af2c 100644 ---- a/drivers/nvmem/imx-ocotp-scu.c -+++ b/drivers/nvmem/imx-ocotp-scu.c -@@ -220,6 +220,7 @@ static int imx_scu_ocotp_write(void *context, unsigned int offset, - - static struct nvmem_config imx_scu_ocotp_nvmem_config = { - .name = "imx-scu-ocotp", -+ .add_legacy_fixed_of_cells = true, - .read_only = false, - .word_size = 4, - .stride = 1, -diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c -index e8b6f194925df..f1e202efaa497 100644 ---- a/drivers/nvmem/imx-ocotp.c -+++ b/drivers/nvmem/imx-ocotp.c -@@ -615,6 +615,7 @@ static int imx_ocotp_probe(struct platform_device *pdev) - return PTR_ERR(priv->clk); - - priv->params = of_device_get_match_data(&pdev->dev); -+ imx_ocotp_nvmem_config.add_legacy_fixed_of_cells = true; - imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; - imx_ocotp_nvmem_config.dev = dev; - imx_ocotp_nvmem_config.priv = priv; -diff --git a/drivers/nvmem/meson-efuse.c b/drivers/nvmem/meson-efuse.c -index ba2714bef8d0e..33678d0af2c24 100644 ---- a/drivers/nvmem/meson-efuse.c -+++ b/drivers/nvmem/meson-efuse.c -@@ -74,6 +74,7 @@ static int meson_efuse_probe(struct platform_device *pdev) - - econfig->dev = dev; - econfig->name = dev_name(dev); -+ econfig->add_legacy_fixed_of_cells = true; - econfig->stride = 1; - econfig->word_size = 1; - econfig->reg_read = meson_efuse_read; -diff --git a/drivers/nvmem/meson-mx-efuse.c b/drivers/nvmem/meson-mx-efuse.c -index d6d7aeda31f92..3ff04d5ca8f85 100644 ---- a/drivers/nvmem/meson-mx-efuse.c -+++ b/drivers/nvmem/meson-mx-efuse.c -@@ -210,6 +210,7 @@ static int meson_mx_efuse_probe(struct platform_device *pdev) - efuse->config.owner = THIS_MODULE; - efuse->config.dev = &pdev->dev; - efuse->config.priv = efuse; -+ efuse->config.add_legacy_fixed_of_cells = true; - efuse->config.stride = drvdata->word_size; - efuse->config.word_size = drvdata->word_size; - efuse->config.size = SZ_512; -diff --git a/drivers/nvmem/microchip-otpc.c b/drivers/nvmem/microchip-otpc.c -index 436e0dc4f3375..7cf81738a3e0a 100644 ---- a/drivers/nvmem/microchip-otpc.c -+++ b/drivers/nvmem/microchip-otpc.c -@@ -261,6 +261,7 @@ static int mchp_otpc_probe(struct platform_device *pdev) - return ret; - - mchp_nvmem_config.dev = otpc->dev; -+ mchp_nvmem_config.add_legacy_fixed_of_cells = true; - mchp_nvmem_config.size = size; - mchp_nvmem_config.priv = otpc; - nvmem = devm_nvmem_register(&pdev->dev, &mchp_nvmem_config); -diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c -index b36cd0dcc8c7f..87c94686cfd21 100644 ---- a/drivers/nvmem/mtk-efuse.c -+++ b/drivers/nvmem/mtk-efuse.c -@@ -83,6 +83,7 @@ static int mtk_efuse_probe(struct platform_device *pdev) - return PTR_ERR(priv->base); - - pdata = device_get_match_data(dev); -+ econfig.add_legacy_fixed_of_cells = true; - econfig.stride = 1; - econfig.word_size = 1; - econfig.reg_read = mtk_reg_read; -diff --git a/drivers/nvmem/qcom-spmi-sdam.c b/drivers/nvmem/qcom-spmi-sdam.c -index 70f2d4f2efbf1..9aa8f42faa4c9 100644 ---- a/drivers/nvmem/qcom-spmi-sdam.c -+++ b/drivers/nvmem/qcom-spmi-sdam.c -@@ -142,6 +142,7 @@ static int sdam_probe(struct platform_device *pdev) - sdam->sdam_config.name = "spmi_sdam"; - sdam->sdam_config.id = NVMEM_DEVID_AUTO; - sdam->sdam_config.owner = THIS_MODULE; -+ sdam->sdam_config.add_legacy_fixed_of_cells = true; - sdam->sdam_config.stride = 1; - sdam->sdam_config.word_size = 1; - sdam->sdam_config.reg_read = sdam_read; -diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c -index 14814cba2dd65..6c554040c6e67 100644 ---- a/drivers/nvmem/qfprom.c -+++ b/drivers/nvmem/qfprom.c -@@ -357,6 +357,7 @@ static int qfprom_probe(struct platform_device *pdev) - { - struct nvmem_config econfig = { - .name = "qfprom", -+ .add_legacy_fixed_of_cells = true, - .stride = 1, - .word_size = 1, - .id = NVMEM_DEVID_AUTO, -diff --git a/drivers/nvmem/rave-sp-eeprom.c b/drivers/nvmem/rave-sp-eeprom.c -index df6a1c594b781..9ecf3873cbb76 100644 ---- a/drivers/nvmem/rave-sp-eeprom.c -+++ b/drivers/nvmem/rave-sp-eeprom.c -@@ -328,6 +328,7 @@ static int rave_sp_eeprom_probe(struct platform_device *pdev) - of_property_read_string(np, "zii,eeprom-name", &config.name); - config.priv = eeprom; - config.dev = dev; -+ config.add_legacy_fixed_of_cells = true; - config.size = size; - config.reg_read = rave_sp_eeprom_reg_read; - config.reg_write = rave_sp_eeprom_reg_write; -diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c -index 4004c5bece423..2b40978ddb18c 100644 ---- a/drivers/nvmem/rockchip-efuse.c -+++ b/drivers/nvmem/rockchip-efuse.c -@@ -205,6 +205,7 @@ static int rockchip_rk3399_efuse_read(void *context, unsigned int offset, - - static struct nvmem_config econfig = { - .name = "rockchip-efuse", -+ .add_legacy_fixed_of_cells = true, - .stride = 1, - .word_size = 1, - .read_only = true, -diff --git a/drivers/nvmem/sc27xx-efuse.c b/drivers/nvmem/sc27xx-efuse.c -index 2210da40dfbd7..bff27011f4ff2 100644 ---- a/drivers/nvmem/sc27xx-efuse.c -+++ b/drivers/nvmem/sc27xx-efuse.c -@@ -247,6 +247,7 @@ static int sc27xx_efuse_probe(struct platform_device *pdev) - econfig.reg_read = sc27xx_efuse_read; - econfig.priv = efuse; - econfig.dev = &pdev->dev; -+ econfig.add_legacy_fixed_of_cells = true; - nvmem = devm_nvmem_register(&pdev->dev, &econfig); - if (IS_ERR(nvmem)) { - dev_err(&pdev->dev, "failed to register nvmem config\n"); -diff --git a/drivers/nvmem/sec-qfprom.c b/drivers/nvmem/sec-qfprom.c -index e48c2dc0c44b3..19799b3fe00aa 100644 ---- a/drivers/nvmem/sec-qfprom.c -+++ b/drivers/nvmem/sec-qfprom.c -@@ -47,6 +47,7 @@ static int sec_qfprom_probe(struct platform_device *pdev) - { - struct nvmem_config econfig = { - .name = "sec-qfprom", -+ .add_legacy_fixed_of_cells = true, - .stride = 1, - .word_size = 1, - .id = NVMEM_DEVID_AUTO, -diff --git a/drivers/nvmem/sprd-efuse.c b/drivers/nvmem/sprd-efuse.c -index 7e6e31db4baae..bb3105f3291fc 100644 ---- a/drivers/nvmem/sprd-efuse.c -+++ b/drivers/nvmem/sprd-efuse.c -@@ -408,6 +408,7 @@ static int sprd_efuse_probe(struct platform_device *pdev) - econfig.read_only = false; - econfig.name = "sprd-efuse"; - econfig.size = efuse->data->blk_nums * SPRD_EFUSE_BLOCK_WIDTH; -+ econfig.add_legacy_fixed_of_cells = true; - econfig.reg_read = sprd_efuse_read; - econfig.reg_write = sprd_efuse_write; - econfig.priv = efuse; -diff --git a/drivers/nvmem/stm32-romem.c b/drivers/nvmem/stm32-romem.c -index 0f84044bd1ade..1541c20709d25 100644 ---- a/drivers/nvmem/stm32-romem.c -+++ b/drivers/nvmem/stm32-romem.c -@@ -207,6 +207,7 @@ static int stm32_romem_probe(struct platform_device *pdev) - priv->cfg.priv = priv; - priv->cfg.owner = THIS_MODULE; - priv->cfg.type = NVMEM_TYPE_OTP; -+ priv->cfg.add_legacy_fixed_of_cells = true; - - priv->lower = 0; - -diff --git a/drivers/nvmem/sunplus-ocotp.c b/drivers/nvmem/sunplus-ocotp.c -index f3a18aa0a6c73..38f5d9df39cd5 100644 ---- a/drivers/nvmem/sunplus-ocotp.c -+++ b/drivers/nvmem/sunplus-ocotp.c -@@ -145,6 +145,7 @@ static int sp_ocotp_read(void *priv, unsigned int offset, void *value, size_t by - - static struct nvmem_config sp_ocotp_nvmem_config = { - .name = "sp-ocotp", -+ .add_legacy_fixed_of_cells = true, - .read_only = true, - .word_size = 1, - .size = QAC628_OTP_SIZE, -diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c -index 5d364d85347fc..ba14a76208ab6 100644 ---- a/drivers/nvmem/sunxi_sid.c -+++ b/drivers/nvmem/sunxi_sid.c -@@ -153,6 +153,7 @@ static int sunxi_sid_probe(struct platform_device *pdev) - nvmem_cfg->dev = dev; - nvmem_cfg->name = "sunxi-sid"; - nvmem_cfg->type = NVMEM_TYPE_OTP; -+ nvmem_cfg->add_legacy_fixed_of_cells = true; - nvmem_cfg->read_only = true; - nvmem_cfg->size = cfg->size; - nvmem_cfg->word_size = 1; -diff --git a/drivers/nvmem/uniphier-efuse.c b/drivers/nvmem/uniphier-efuse.c -index 0a1dbb80537ec..6ad3295d31951 100644 ---- a/drivers/nvmem/uniphier-efuse.c -+++ b/drivers/nvmem/uniphier-efuse.c -@@ -52,6 +52,7 @@ static int uniphier_efuse_probe(struct platform_device *pdev) - econfig.size = resource_size(res); - econfig.priv = priv; - econfig.dev = dev; -+ econfig.add_legacy_fixed_of_cells = true; - nvmem = devm_nvmem_register(dev, &econfig); - - return PTR_ERR_OR_ZERO(nvmem); -diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c -index f49bb9a26d053..7f15aa89a9d09 100644 ---- a/drivers/nvmem/zynqmp_nvmem.c -+++ b/drivers/nvmem/zynqmp_nvmem.c -@@ -58,6 +58,7 @@ static int zynqmp_nvmem_probe(struct platform_device *pdev) - - priv->dev = dev; - econfig.dev = dev; -+ econfig.add_legacy_fixed_of_cells = true; - econfig.reg_read = zynqmp_nvmem_read; - econfig.priv = priv; - -diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c -index 80838dc54b3ab..7938741136a2c 100644 ---- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c -+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c -@@ -43,7 +43,7 @@ - #define SCU614 0x614 /* Disable GPIO Internal Pull-Down #1 */ - #define SCU618 0x618 /* Disable GPIO Internal Pull-Down #2 */ - #define SCU61C 0x61c /* Disable GPIO Internal Pull-Down #3 */ --#define SCU620 0x620 /* Disable GPIO Internal Pull-Down #4 */ -+#define SCU630 0x630 /* Disable GPIO Internal Pull-Down #4 */ - #define SCU634 0x634 /* Disable GPIO Internal Pull-Down #5 */ - #define SCU638 0x638 /* Disable GPIO Internal Pull-Down #6 */ - #define SCU690 0x690 /* Multi-function Pin Control #24 */ -@@ -2494,38 +2494,38 @@ static struct aspeed_pin_config aspeed_g6_configs[] = { - ASPEED_PULL_DOWN_PINCONF(D14, SCU61C, 0), - - /* GPIOS7 */ -- ASPEED_PULL_DOWN_PINCONF(T24, SCU620, 23), -+ ASPEED_PULL_DOWN_PINCONF(T24, SCU630, 23), - /* GPIOS6 */ -- ASPEED_PULL_DOWN_PINCONF(P23, SCU620, 22), -+ ASPEED_PULL_DOWN_PINCONF(P23, SCU630, 22), - /* GPIOS5 */ -- ASPEED_PULL_DOWN_PINCONF(P24, SCU620, 21), -+ ASPEED_PULL_DOWN_PINCONF(P24, SCU630, 21), - /* GPIOS4 */ -- ASPEED_PULL_DOWN_PINCONF(R26, SCU620, 20), -+ ASPEED_PULL_DOWN_PINCONF(R26, SCU630, 20), - /* GPIOS3*/ -- ASPEED_PULL_DOWN_PINCONF(R24, SCU620, 19), -+ ASPEED_PULL_DOWN_PINCONF(R24, SCU630, 19), - /* GPIOS2 */ -- ASPEED_PULL_DOWN_PINCONF(T26, SCU620, 18), -+ ASPEED_PULL_DOWN_PINCONF(T26, SCU630, 18), - /* GPIOS1 */ -- ASPEED_PULL_DOWN_PINCONF(T25, SCU620, 17), -+ ASPEED_PULL_DOWN_PINCONF(T25, SCU630, 17), - /* GPIOS0 */ -- ASPEED_PULL_DOWN_PINCONF(R23, SCU620, 16), -+ ASPEED_PULL_DOWN_PINCONF(R23, SCU630, 16), - - /* GPIOR7 */ -- ASPEED_PULL_DOWN_PINCONF(U26, SCU620, 15), -+ ASPEED_PULL_DOWN_PINCONF(U26, SCU630, 15), - /* GPIOR6 */ -- ASPEED_PULL_DOWN_PINCONF(W26, SCU620, 14), -+ ASPEED_PULL_DOWN_PINCONF(W26, SCU630, 14), - /* GPIOR5 */ -- ASPEED_PULL_DOWN_PINCONF(T23, SCU620, 13), -+ ASPEED_PULL_DOWN_PINCONF(T23, SCU630, 13), - /* GPIOR4 */ -- ASPEED_PULL_DOWN_PINCONF(U25, SCU620, 12), -+ ASPEED_PULL_DOWN_PINCONF(U25, SCU630, 12), - /* GPIOR3*/ -- ASPEED_PULL_DOWN_PINCONF(V26, SCU620, 11), -+ ASPEED_PULL_DOWN_PINCONF(V26, SCU630, 11), - /* GPIOR2 */ -- ASPEED_PULL_DOWN_PINCONF(V24, SCU620, 10), -+ ASPEED_PULL_DOWN_PINCONF(V24, SCU630, 10), - /* GPIOR1 */ -- ASPEED_PULL_DOWN_PINCONF(U24, SCU620, 9), -+ ASPEED_PULL_DOWN_PINCONF(U24, SCU630, 9), - /* GPIOR0 */ -- ASPEED_PULL_DOWN_PINCONF(V25, SCU620, 8), -+ ASPEED_PULL_DOWN_PINCONF(V25, SCU630, 8), - - /* GPIOX7 */ - ASPEED_PULL_DOWN_PINCONF(AB10, SCU634, 31), -diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c -index 184ec92241ca8..9e7b3e6c79cb1 100644 ---- a/drivers/pinctrl/core.c -+++ b/drivers/pinctrl/core.c -@@ -2116,13 +2116,7 @@ int pinctrl_enable(struct pinctrl_dev *pctldev) - - error = pinctrl_claim_hogs(pctldev); - if (error) { -- dev_err(pctldev->dev, "could not claim hogs: %i\n", -- error); -- pinctrl_free_pindescs(pctldev, pctldev->desc->pins, -- pctldev->desc->npins); -- mutex_destroy(&pctldev->mutex); -- kfree(pctldev); -- -+ dev_err(pctldev->dev, "could not claim hogs: %i\n", error); - return error; - } - -diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c -index 6e0a40962f384..5ee746cb81f59 100644 ---- a/drivers/pinctrl/devicetree.c -+++ b/drivers/pinctrl/devicetree.c -@@ -220,14 +220,16 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev) - for (state = 0; ; state++) { - /* Retrieve the pinctrl-* property */ - propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state); -- if (!propname) -- return -ENOMEM; -+ if (!propname) { -+ ret = -ENOMEM; -+ goto err; -+ } - prop = of_find_property(np, propname, &size); - kfree(propname); - if (!prop) { - if (state == 0) { -- of_node_put(np); -- return -ENODEV; -+ ret = -ENODEV; -+ goto err; - } - break; - } -diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c -index 95a8a3a22b2b4..0aaeb54a64765 100644 ---- a/drivers/pinctrl/intel/pinctrl-baytrail.c -+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c -@@ -277,33 +277,33 @@ static const unsigned int byt_score_plt_clk5_pins[] = { 101 }; - static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 }; - - static const struct intel_pingroup byt_score_groups[] = { -- PIN_GROUP("uart1_grp", byt_score_uart1_pins, 1), -- PIN_GROUP("uart2_grp", byt_score_uart2_pins, 1), -- PIN_GROUP("pwm0_grp", byt_score_pwm0_pins, 1), -- PIN_GROUP("pwm1_grp", byt_score_pwm1_pins, 1), -- PIN_GROUP("ssp2_grp", byt_score_ssp2_pins, 1), -- PIN_GROUP("sio_spi_grp", byt_score_sio_spi_pins, 1), -- PIN_GROUP("i2c5_grp", byt_score_i2c5_pins, 1), -- PIN_GROUP("i2c6_grp", byt_score_i2c6_pins, 1), -- PIN_GROUP("i2c4_grp", byt_score_i2c4_pins, 1), -- PIN_GROUP("i2c3_grp", byt_score_i2c3_pins, 1), -- PIN_GROUP("i2c2_grp", byt_score_i2c2_pins, 1), -- PIN_GROUP("i2c1_grp", byt_score_i2c1_pins, 1), -- PIN_GROUP("i2c0_grp", byt_score_i2c0_pins, 1), -- PIN_GROUP("ssp0_grp", byt_score_ssp0_pins, 1), -- PIN_GROUP("ssp1_grp", byt_score_ssp1_pins, 1), -- PIN_GROUP("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values), -- PIN_GROUP("sdio_grp", byt_score_sdio_pins, 1), -- PIN_GROUP("emmc_grp", byt_score_emmc_pins, 1), -- PIN_GROUP("lpc_grp", byt_score_ilb_lpc_pins, 1), -- PIN_GROUP("sata_grp", byt_score_sata_pins, 1), -- PIN_GROUP("plt_clk0_grp", byt_score_plt_clk0_pins, 1), -- PIN_GROUP("plt_clk1_grp", byt_score_plt_clk1_pins, 1), -- PIN_GROUP("plt_clk2_grp", byt_score_plt_clk2_pins, 1), -- PIN_GROUP("plt_clk3_grp", byt_score_plt_clk3_pins, 1), -- PIN_GROUP("plt_clk4_grp", byt_score_plt_clk4_pins, 1), -- PIN_GROUP("plt_clk5_grp", byt_score_plt_clk5_pins, 1), -- PIN_GROUP("smbus_grp", byt_score_smbus_pins, 1), -+ PIN_GROUP_GPIO("uart1_grp", byt_score_uart1_pins, 1), -+ PIN_GROUP_GPIO("uart2_grp", byt_score_uart2_pins, 1), -+ PIN_GROUP_GPIO("pwm0_grp", byt_score_pwm0_pins, 1), -+ PIN_GROUP_GPIO("pwm1_grp", byt_score_pwm1_pins, 1), -+ PIN_GROUP_GPIO("ssp2_grp", byt_score_ssp2_pins, 1), -+ PIN_GROUP_GPIO("sio_spi_grp", byt_score_sio_spi_pins, 1), -+ PIN_GROUP_GPIO("i2c5_grp", byt_score_i2c5_pins, 1), -+ PIN_GROUP_GPIO("i2c6_grp", byt_score_i2c6_pins, 1), -+ PIN_GROUP_GPIO("i2c4_grp", byt_score_i2c4_pins, 1), -+ PIN_GROUP_GPIO("i2c3_grp", byt_score_i2c3_pins, 1), -+ PIN_GROUP_GPIO("i2c2_grp", byt_score_i2c2_pins, 1), -+ PIN_GROUP_GPIO("i2c1_grp", byt_score_i2c1_pins, 1), -+ PIN_GROUP_GPIO("i2c0_grp", byt_score_i2c0_pins, 1), -+ PIN_GROUP_GPIO("ssp0_grp", byt_score_ssp0_pins, 1), -+ PIN_GROUP_GPIO("ssp1_grp", byt_score_ssp1_pins, 1), -+ PIN_GROUP_GPIO("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values), -+ PIN_GROUP_GPIO("sdio_grp", byt_score_sdio_pins, 1), -+ PIN_GROUP_GPIO("emmc_grp", byt_score_emmc_pins, 1), -+ PIN_GROUP_GPIO("lpc_grp", byt_score_ilb_lpc_pins, 1), -+ PIN_GROUP_GPIO("sata_grp", byt_score_sata_pins, 1), -+ PIN_GROUP_GPIO("plt_clk0_grp", byt_score_plt_clk0_pins, 1), -+ PIN_GROUP_GPIO("plt_clk1_grp", byt_score_plt_clk1_pins, 1), -+ PIN_GROUP_GPIO("plt_clk2_grp", byt_score_plt_clk2_pins, 1), -+ PIN_GROUP_GPIO("plt_clk3_grp", byt_score_plt_clk3_pins, 1), -+ PIN_GROUP_GPIO("plt_clk4_grp", byt_score_plt_clk4_pins, 1), -+ PIN_GROUP_GPIO("plt_clk5_grp", byt_score_plt_clk5_pins, 1), -+ PIN_GROUP_GPIO("smbus_grp", byt_score_smbus_pins, 1), - }; - - static const char * const byt_score_uart_groups[] = { -@@ -331,12 +331,14 @@ static const char * const byt_score_plt_clk_groups[] = { - }; - static const char * const byt_score_smbus_groups[] = { "smbus_grp" }; - static const char * const byt_score_gpio_groups[] = { -- "uart1_grp", "uart2_grp", "pwm0_grp", "pwm1_grp", "ssp0_grp", -- "ssp1_grp", "ssp2_grp", "sio_spi_grp", "i2c0_grp", "i2c1_grp", -- "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", "i2c6_grp", -- "sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp", -- "plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp", -- "plt_clk4_grp", "plt_clk5_grp", "smbus_grp", -+ "uart1_grp_gpio", "uart2_grp_gpio", "pwm0_grp_gpio", -+ "pwm1_grp_gpio", "ssp0_grp_gpio", "ssp1_grp_gpio", "ssp2_grp_gpio", -+ "sio_spi_grp_gpio", "i2c0_grp_gpio", "i2c1_grp_gpio", "i2c2_grp_gpio", -+ "i2c3_grp_gpio", "i2c4_grp_gpio", "i2c5_grp_gpio", "i2c6_grp_gpio", -+ "sdcard_grp_gpio", "sdio_grp_gpio", "emmc_grp_gpio", "lpc_grp_gpio", -+ "sata_grp_gpio", "plt_clk0_grp_gpio", "plt_clk1_grp_gpio", -+ "plt_clk2_grp_gpio", "plt_clk3_grp_gpio", "plt_clk4_grp_gpio", -+ "plt_clk5_grp_gpio", "smbus_grp_gpio", - }; - - static const struct intel_function byt_score_functions[] = { -@@ -455,8 +457,8 @@ static const struct intel_pingroup byt_sus_groups[] = { - PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values), - PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values), - PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values), -- PIN_GROUP("pmu_clk1_grp", byt_sus_pmu_clk1_pins, 1), -- PIN_GROUP("pmu_clk2_grp", byt_sus_pmu_clk2_pins, 1), -+ PIN_GROUP_GPIO("pmu_clk1_grp", byt_sus_pmu_clk1_pins, 1), -+ PIN_GROUP_GPIO("pmu_clk2_grp", byt_sus_pmu_clk2_pins, 1), - }; - - static const char * const byt_sus_usb_groups[] = { -@@ -468,7 +470,7 @@ static const char * const byt_sus_pmu_clk_groups[] = { - }; - static const char * const byt_sus_gpio_groups[] = { - "usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio", -- "pmu_clk1_grp", "pmu_clk2_grp", -+ "pmu_clk1_grp_gpio", "pmu_clk2_grp_gpio", - }; - - static const struct intel_function byt_sus_functions[] = { -diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h -index cee512f97b566..45216b9e852dc 100644 ---- a/drivers/pinctrl/intel/pinctrl-intel.h -+++ b/drivers/pinctrl/intel/pinctrl-intel.h -@@ -179,6 +179,10 @@ struct intel_community { - .modes = __builtin_choose_expr(__builtin_constant_p((m)), NULL, (m)), \ - } - -+#define PIN_GROUP_GPIO(n, p, m) \ -+ PIN_GROUP(n, p, m), \ -+ PIN_GROUP(n "_gpio", p, 0) -+ - #define FUNCTION(n, g) \ - { \ - .func = PINCTRL_PINFUNCTION((n), (g), ARRAY_SIZE(g)), \ -diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c -index 33d6c3fb79080..9cd7fe3c3e0df 100644 ---- a/drivers/pinctrl/mediatek/pinctrl-paris.c -+++ b/drivers/pinctrl/mediatek/pinctrl-paris.c -@@ -165,20 +165,21 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret); - break; - case PIN_CONFIG_INPUT_ENABLE: -- case PIN_CONFIG_OUTPUT_ENABLE: -+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_IES, &ret); -+ if (!ret) -+ err = -EINVAL; -+ break; -+ case PIN_CONFIG_OUTPUT: - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret); - if (err) - break; -- /* CONFIG Current direction return value -- * ------------- ----------------- ---------------------- -- * OUTPUT_ENABLE output 1 (= HW value) -- * input 0 (= HW value) -- * INPUT_ENABLE output 0 (= reverse HW value) -- * input 1 (= reverse HW value) -- */ -- if (param == PIN_CONFIG_INPUT_ENABLE) -- ret = !ret; - -+ if (!ret) { -+ err = -EINVAL; -+ break; -+ } -+ -+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DO, &ret); - break; - case PIN_CONFIG_INPUT_SCHMITT_ENABLE: - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret); -@@ -193,6 +194,8 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev, - } - - err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &ret); -+ if (!ret) -+ err = -EINVAL; - break; - case PIN_CONFIG_DRIVE_STRENGTH: - if (!hw->soc->drive_get) -@@ -281,26 +284,9 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, - break; - err = hw->soc->bias_set_combo(hw, desc, 0, arg); - break; -- case PIN_CONFIG_OUTPUT_ENABLE: -- err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, -- MTK_DISABLE); -- /* Keep set direction to consider the case that a GPIO pin -- * does not have SMT control -- */ -- if (err != -ENOTSUPP) -- break; -- -- err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, -- MTK_OUTPUT); -- break; - case PIN_CONFIG_INPUT_ENABLE: - /* regard all non-zero value as enable */ - err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, !!arg); -- if (err) -- break; -- -- err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, -- MTK_INPUT); - break; - case PIN_CONFIG_SLEW_RATE: - /* regard all non-zero value as enable */ -diff --git a/drivers/pinctrl/meson/pinctrl-meson-a1.c b/drivers/pinctrl/meson/pinctrl-meson-a1.c -index 79f5d753d7e1a..50a87d9618a8e 100644 ---- a/drivers/pinctrl/meson/pinctrl-meson-a1.c -+++ b/drivers/pinctrl/meson/pinctrl-meson-a1.c -@@ -250,7 +250,7 @@ static const unsigned int pdm_dclk_x_pins[] = { GPIOX_10 }; - static const unsigned int pdm_din2_a_pins[] = { GPIOA_6 }; - static const unsigned int pdm_din1_a_pins[] = { GPIOA_7 }; - static const unsigned int pdm_din0_a_pins[] = { GPIOA_8 }; --static const unsigned int pdm_dclk_pins[] = { GPIOA_9 }; -+static const unsigned int pdm_dclk_a_pins[] = { GPIOA_9 }; - - /* gen_clk */ - static const unsigned int gen_clk_x_pins[] = { GPIOX_7 }; -@@ -591,7 +591,7 @@ static struct meson_pmx_group meson_a1_periphs_groups[] = { - GROUP(pdm_din2_a, 3), - GROUP(pdm_din1_a, 3), - GROUP(pdm_din0_a, 3), -- GROUP(pdm_dclk, 3), -+ GROUP(pdm_dclk_a, 3), - GROUP(pwm_c_a, 3), - GROUP(pwm_b_a, 3), - -@@ -755,7 +755,7 @@ static const char * const spi_a_groups[] = { - - static const char * const pdm_groups[] = { - "pdm_din0_x", "pdm_din1_x", "pdm_din2_x", "pdm_dclk_x", "pdm_din2_a", -- "pdm_din1_a", "pdm_din0_a", "pdm_dclk", -+ "pdm_din1_a", "pdm_din0_a", "pdm_dclk_a", - }; - - static const char * const gen_clk_groups[] = { -diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c -index 08df9494603c5..30951f7131cd9 100644 ---- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c -+++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c -@@ -719,6 +719,7 @@ static struct miscdevice isst_if_char_driver = { - }; - - static const struct x86_cpu_id hpm_cpu_ids[] = { -+ X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_D, NULL), - X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_X, NULL), - X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT_X, NULL), - {} -diff --git a/drivers/power/supply/mt6360_charger.c b/drivers/power/supply/mt6360_charger.c -index 1305cba61edd4..aca123783efcc 100644 ---- a/drivers/power/supply/mt6360_charger.c -+++ b/drivers/power/supply/mt6360_charger.c -@@ -588,7 +588,7 @@ static const struct regulator_ops mt6360_chg_otg_ops = { - }; - - static const struct regulator_desc mt6360_otg_rdesc = { -- .of_match = "usb-otg-vbus", -+ .of_match = "usb-otg-vbus-regulator", - .name = "usb-otg-vbus", - .ops = &mt6360_chg_otg_ops, - .owner = THIS_MODULE, -diff --git a/drivers/power/supply/rt9455_charger.c b/drivers/power/supply/rt9455_charger.c -index c345a77f9f78c..e4dbacd50a437 100644 ---- a/drivers/power/supply/rt9455_charger.c -+++ b/drivers/power/supply/rt9455_charger.c -@@ -192,6 +192,7 @@ static const int rt9455_voreg_values[] = { - 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000 - }; - -+#if IS_ENABLED(CONFIG_USB_PHY) - /* - * When the charger is in boost mode, REG02[7:2] represent boost output - * voltage. -@@ -207,6 +208,7 @@ static const int rt9455_boost_voltage_values[] = { - 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, - 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, - }; -+#endif - - /* REG07[3:0] (VMREG) in uV */ - static const int rt9455_vmreg_values[] = { -diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c -index a7b3e548ea5ac..dfb986377a989 100644 ---- a/drivers/regulator/core.c -+++ b/drivers/regulator/core.c -@@ -1909,19 +1909,24 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, - } - } - -- if (err != -EEXIST) -+ if (err != -EEXIST) { - regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs); -- if (IS_ERR(regulator->debugfs)) -- rdev_dbg(rdev, "Failed to create debugfs directory\n"); -+ if (IS_ERR(regulator->debugfs)) { -+ rdev_dbg(rdev, "Failed to create debugfs directory\n"); -+ regulator->debugfs = NULL; -+ } -+ } - -- debugfs_create_u32("uA_load", 0444, regulator->debugfs, -- ®ulator->uA_load); -- debugfs_create_u32("min_uV", 0444, regulator->debugfs, -- ®ulator->voltage[PM_SUSPEND_ON].min_uV); -- debugfs_create_u32("max_uV", 0444, regulator->debugfs, -- ®ulator->voltage[PM_SUSPEND_ON].max_uV); -- debugfs_create_file("constraint_flags", 0444, regulator->debugfs, -- regulator, &constraint_flags_fops); -+ if (regulator->debugfs) { -+ debugfs_create_u32("uA_load", 0444, regulator->debugfs, -+ ®ulator->uA_load); -+ debugfs_create_u32("min_uV", 0444, regulator->debugfs, -+ ®ulator->voltage[PM_SUSPEND_ON].min_uV); -+ debugfs_create_u32("max_uV", 0444, regulator->debugfs, -+ ®ulator->voltage[PM_SUSPEND_ON].max_uV); -+ debugfs_create_file("constraint_flags", 0444, regulator->debugfs, -+ regulator, &constraint_flags_fops); -+ } - - /* - * Check now if the regulator is an always on regulator - if -diff --git a/drivers/regulator/mt6360-regulator.c b/drivers/regulator/mt6360-regulator.c -index ad6587a378d09..24cc9fc94e900 100644 ---- a/drivers/regulator/mt6360-regulator.c -+++ b/drivers/regulator/mt6360-regulator.c -@@ -319,15 +319,15 @@ static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode) - } - } - --#define MT6360_REGULATOR_DESC(_name, _sname, ereg, emask, vreg, vmask, \ -- mreg, mmask, streg, stmask, vranges, \ -- vcnts, offon_delay, irq_tbls) \ -+#define MT6360_REGULATOR_DESC(match, _name, _sname, ereg, emask, vreg, \ -+ vmask, mreg, mmask, streg, stmask, \ -+ vranges, vcnts, offon_delay, irq_tbls) \ - { \ - .desc = { \ - .name = #_name, \ - .supply_name = #_sname, \ - .id = MT6360_REGULATOR_##_name, \ -- .of_match = of_match_ptr(#_name), \ -+ .of_match = of_match_ptr(match), \ - .regulators_node = of_match_ptr("regulator"), \ - .of_map_mode = mt6360_regulator_of_map_mode, \ - .owner = THIS_MODULE, \ -@@ -351,21 +351,29 @@ static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode) - } - - static const struct mt6360_regulator_desc mt6360_regulator_descs[] = { -- MT6360_REGULATOR_DESC(BUCK1, BUCK1_VIN, 0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04, -+ MT6360_REGULATOR_DESC("buck1", BUCK1, BUCK1_VIN, -+ 0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04, - buck_vout_ranges, 256, 0, buck1_irq_tbls), -- MT6360_REGULATOR_DESC(BUCK2, BUCK2_VIN, 0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04, -+ MT6360_REGULATOR_DESC("buck2", BUCK2, BUCK2_VIN, -+ 0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04, - buck_vout_ranges, 256, 0, buck2_irq_tbls), -- MT6360_REGULATOR_DESC(LDO6, LDO_VIN3, 0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04, -+ MT6360_REGULATOR_DESC("ldo6", LDO6, LDO_VIN3, -+ 0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04, - ldo_vout_ranges1, 256, 0, ldo6_irq_tbls), -- MT6360_REGULATOR_DESC(LDO7, LDO_VIN3, 0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04, -+ MT6360_REGULATOR_DESC("ldo7", LDO7, LDO_VIN3, -+ 0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04, - ldo_vout_ranges1, 256, 0, ldo7_irq_tbls), -- MT6360_REGULATOR_DESC(LDO1, LDO_VIN1, 0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04, -+ MT6360_REGULATOR_DESC("ldo1", LDO1, LDO_VIN1, -+ 0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04, - ldo_vout_ranges2, 256, 0, ldo1_irq_tbls), -- MT6360_REGULATOR_DESC(LDO2, LDO_VIN1, 0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04, -+ MT6360_REGULATOR_DESC("ldo2", LDO2, LDO_VIN1, -+ 0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04, - ldo_vout_ranges2, 256, 0, ldo2_irq_tbls), -- MT6360_REGULATOR_DESC(LDO3, LDO_VIN1, 0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04, -+ MT6360_REGULATOR_DESC("ldo3", LDO3, LDO_VIN1, -+ 0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04, - ldo_vout_ranges2, 256, 100, ldo3_irq_tbls), -- MT6360_REGULATOR_DESC(LDO5, LDO_VIN2, 0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04, -+ MT6360_REGULATOR_DESC("ldo5", LDO5, LDO_VIN2, -+ 0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04, - ldo_vout_ranges3, 128, 100, ldo5_irq_tbls), - }; - -diff --git a/drivers/regulator/tps65132-regulator.c b/drivers/regulator/tps65132-regulator.c -index a06f5f2d79329..9c2f0dd42613d 100644 ---- a/drivers/regulator/tps65132-regulator.c -+++ b/drivers/regulator/tps65132-regulator.c -@@ -267,10 +267,17 @@ static const struct i2c_device_id tps65132_id[] = { - }; - MODULE_DEVICE_TABLE(i2c, tps65132_id); - -+static const struct of_device_id __maybe_unused tps65132_of_match[] = { -+ { .compatible = "ti,tps65132" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, tps65132_of_match); -+ - static struct i2c_driver tps65132_i2c_driver = { - .driver = { - .name = "tps65132", - .probe_type = PROBE_PREFER_ASYNCHRONOUS, -+ .of_match_table = of_match_ptr(tps65132_of_match), - }, - .probe = tps65132_probe, - .id_table = tps65132_id, -diff --git a/drivers/rtc/nvmem.c b/drivers/rtc/nvmem.c -index 07ede21cee347..37df7e80525b4 100644 ---- a/drivers/rtc/nvmem.c -+++ b/drivers/rtc/nvmem.c -@@ -21,6 +21,7 @@ int devm_rtc_nvmem_register(struct rtc_device *rtc, - - nvmem_config->dev = dev; - nvmem_config->owner = rtc->owner; -+ nvmem_config->add_legacy_fixed_of_cells = true; - nvmem = devm_nvmem_register(dev, nvmem_config); - if (IS_ERR(nvmem)) - dev_err(dev, "failed to register nvmem device for RTC\n"); -diff --git a/drivers/s390/cio/cio_inject.c b/drivers/s390/cio/cio_inject.c -index 8613fa937237b..a2e771ebae8eb 100644 ---- a/drivers/s390/cio/cio_inject.c -+++ b/drivers/s390/cio/cio_inject.c -@@ -95,7 +95,7 @@ static ssize_t crw_inject_write(struct file *file, const char __user *buf, - return -EINVAL; - } - -- buffer = vmemdup_user(buf, lbuf); -+ buffer = memdup_user_nul(buf, lbuf); - if (IS_ERR(buffer)) - return -ENOMEM; - -diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c -index 1148b4ecabdde..f0f3b6272d5b8 100644 ---- a/drivers/s390/net/qeth_core_main.c -+++ b/drivers/s390/net/qeth_core_main.c -@@ -364,30 +364,33 @@ static int qeth_cq_init(struct qeth_card *card) - return rc; - } - -+static void qeth_free_cq(struct qeth_card *card) -+{ -+ if (card->qdio.c_q) { -+ qeth_free_qdio_queue(card->qdio.c_q); -+ card->qdio.c_q = NULL; -+ } -+} -+ - static int qeth_alloc_cq(struct qeth_card *card) - { - if (card->options.cq == QETH_CQ_ENABLED) { - QETH_CARD_TEXT(card, 2, "cqon"); -- card->qdio.c_q = qeth_alloc_qdio_queue(); - if (!card->qdio.c_q) { -- dev_err(&card->gdev->dev, "Failed to create completion queue\n"); -- return -ENOMEM; -+ card->qdio.c_q = qeth_alloc_qdio_queue(); -+ if (!card->qdio.c_q) { -+ dev_err(&card->gdev->dev, -+ "Failed to create completion queue\n"); -+ return -ENOMEM; -+ } - } - } else { - QETH_CARD_TEXT(card, 2, "nocq"); -- card->qdio.c_q = NULL; -+ qeth_free_cq(card); - } - return 0; - } - --static void qeth_free_cq(struct qeth_card *card) --{ -- if (card->qdio.c_q) { -- qeth_free_qdio_queue(card->qdio.c_q); -- card->qdio.c_q = NULL; -- } --} -- - static enum iucv_tx_notify qeth_compute_cq_notification(int sbalf15, - int delayed) - { -@@ -2628,6 +2631,10 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card) - - QETH_CARD_TEXT(card, 2, "allcqdbf"); - -+ /* completion */ -+ if (qeth_alloc_cq(card)) -+ goto out_err; -+ - if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED, - QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED) - return 0; -@@ -2663,10 +2670,6 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card) - queue->priority = QETH_QIB_PQUE_PRIO_DEFAULT; - } - -- /* completion */ -- if (qeth_alloc_cq(card)) -- goto out_freeoutq; -- - return 0; - - out_freeoutq: -@@ -2677,6 +2680,8 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card) - qeth_free_buffer_pool(card); - out_buffer_pool: - atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); -+ qeth_free_cq(card); -+out_err: - return -ENOMEM; - } - -@@ -2684,11 +2689,12 @@ static void qeth_free_qdio_queues(struct qeth_card *card) - { - int i, j; - -+ qeth_free_cq(card); -+ - if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) == - QETH_QDIO_UNINITIALIZED) - return; - -- qeth_free_cq(card); - for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { - if (card->qdio.in_q->bufs[j].rx_skb) { - consume_skb(card->qdio.in_q->bufs[j].rx_skb); -@@ -3742,24 +3748,11 @@ static void qeth_qdio_poll(struct ccw_device *cdev, unsigned long card_ptr) - - int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq) - { -- int rc; -- -- if (card->options.cq == QETH_CQ_NOTAVAILABLE) { -- rc = -1; -- goto out; -- } else { -- if (card->options.cq == cq) { -- rc = 0; -- goto out; -- } -- -- qeth_free_qdio_queues(card); -- card->options.cq = cq; -- rc = 0; -- } --out: -- return rc; -+ if (card->options.cq == QETH_CQ_NOTAVAILABLE) -+ return -1; - -+ card->options.cq = cq; -+ return 0; - } - EXPORT_SYMBOL_GPL(qeth_configure_cq); - -diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c -index 2c246e80c1c4d..d91659811eb3c 100644 ---- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c -+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c -@@ -833,7 +833,6 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba, - - BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n"); - -- spin_lock_bh(&tgt->cq_lock); - ctx_base_ptr = tgt->ctx_base; - tgt->ctx_base = NULL; - -@@ -889,7 +888,6 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba, - tgt->sq, tgt->sq_dma); - tgt->sq = NULL; - } -- spin_unlock_bh(&tgt->cq_lock); - - if (ctx_base_ptr) - iounmap(ctx_base_ptr); -diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c -index e914c0c13bb5b..6b97c066e6631 100644 ---- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c -+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c -@@ -2245,7 +2245,15 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, - case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: - if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) && - (sipc_rx_err_type & RX_FIS_STATUS_ERR_MSK)) { -- ts->stat = SAS_PROTO_RESPONSE; -+ if (task->ata_task.use_ncq) { -+ struct domain_device *device = task->dev; -+ struct hisi_sas_device *sas_dev = device->lldd_dev; -+ -+ sas_dev->dev_status = HISI_SAS_DEV_NCQ_ERR; -+ slot->abort = 1; -+ } else { -+ ts->stat = SAS_PROTO_RESPONSE; -+ } - } else if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) { - ts->residual = trans_tx_fail_type; - ts->stat = SAS_DATA_UNDERRUN; -diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c -index 5c261005b74e4..f6e6db8b8aba9 100644 ---- a/drivers/scsi/libsas/sas_expander.c -+++ b/drivers/scsi/libsas/sas_expander.c -@@ -135,7 +135,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size, - - static inline void *alloc_smp_req(int size) - { -- u8 *p = kzalloc(size, GFP_KERNEL); -+ u8 *p = kzalloc(ALIGN(size, ARCH_DMA_MINALIGN), GFP_KERNEL); - if (p) - p[0] = SMP_REQUEST; - return p; -diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h -index 04d608ea91060..9670cb2bf198e 100644 ---- a/drivers/scsi/lpfc/lpfc.h -+++ b/drivers/scsi/lpfc/lpfc.h -@@ -1325,7 +1325,6 @@ struct lpfc_hba { - struct timer_list fabric_block_timer; - unsigned long bit_flags; - atomic_t num_rsrc_err; -- atomic_t num_cmd_success; - unsigned long last_rsrc_error_time; - unsigned long last_ramp_down_time; - #ifdef CONFIG_SCSI_LPFC_DEBUG_FS -@@ -1430,6 +1429,7 @@ struct lpfc_hba { - struct timer_list inactive_vmid_poll; - - /* RAS Support */ -+ spinlock_t ras_fwlog_lock; /* do not take while holding another lock */ - struct lpfc_ras_fwlog ras_fwlog; - - uint32_t iocb_cnt; -diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c -index b1c9107d34083..79b45ea5fdb5e 100644 ---- a/drivers/scsi/lpfc/lpfc_attr.c -+++ b/drivers/scsi/lpfc/lpfc_attr.c -@@ -5864,9 +5864,9 @@ lpfc_ras_fwlog_buffsize_set(struct lpfc_hba *phba, uint val) - if (phba->cfg_ras_fwlog_func != PCI_FUNC(phba->pcidev->devfn)) - return -EINVAL; - -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - state = phba->ras_fwlog.state; -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - - if (state == REG_INPROGRESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "6147 RAS Logging " -diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c -index 2919579fa0846..c305d16cfae9a 100644 ---- a/drivers/scsi/lpfc/lpfc_bsg.c -+++ b/drivers/scsi/lpfc/lpfc_bsg.c -@@ -5070,12 +5070,12 @@ lpfc_bsg_get_ras_config(struct bsg_job *job) - bsg_reply->reply_data.vendor_reply.vendor_rsp; - - /* Current logging state */ -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - if (ras_fwlog->state == ACTIVE) - ras_reply->state = LPFC_RASLOG_STATE_RUNNING; - else - ras_reply->state = LPFC_RASLOG_STATE_STOPPED; -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - - ras_reply->log_level = phba->ras_fwlog.fw_loglevel; - ras_reply->log_buff_sz = phba->cfg_ras_fwlog_buffsize; -@@ -5132,13 +5132,13 @@ lpfc_bsg_set_ras_config(struct bsg_job *job) - - if (action == LPFC_RASACTION_STOP_LOGGING) { - /* Check if already disabled */ -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - if (ras_fwlog->state != ACTIVE) { -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - rc = -ESRCH; - goto ras_job_error; - } -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - - /* Disable logging */ - lpfc_ras_stop_fwlog(phba); -@@ -5149,10 +5149,10 @@ lpfc_bsg_set_ras_config(struct bsg_job *job) - * FW-logging with new log-level. Return status - * "Logging already Running" to caller. - **/ -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - if (ras_fwlog->state != INACTIVE) - action_status = -EINPROGRESS; -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - - /* Enable logging */ - rc = lpfc_sli4_ras_fwlog_init(phba, log_level, -@@ -5268,13 +5268,13 @@ lpfc_bsg_get_ras_fwlog(struct bsg_job *job) - goto ras_job_error; - - /* Logging to be stopped before reading */ -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - if (ras_fwlog->state == ACTIVE) { -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - rc = -EINPROGRESS; - goto ras_job_error; - } -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - - if (job->request_len < - sizeof(struct fc_bsg_request) + -diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c -index ea9b42225e629..20662b4f339eb 100644 ---- a/drivers/scsi/lpfc/lpfc_debugfs.c -+++ b/drivers/scsi/lpfc/lpfc_debugfs.c -@@ -2196,12 +2196,12 @@ static int lpfc_debugfs_ras_log_data(struct lpfc_hba *phba, - - memset(buffer, 0, size); - -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - if (phba->ras_fwlog.state != ACTIVE) { -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - return -EINVAL; - } -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - - list_for_each_entry_safe(dmabuf, next, - &phba->ras_fwlog.fwlog_buff_list, list) { -@@ -2252,13 +2252,13 @@ lpfc_debugfs_ras_log_open(struct inode *inode, struct file *file) - int size; - int rc = -ENOMEM; - -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - if (phba->ras_fwlog.state != ACTIVE) { -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - rc = -EINVAL; - goto out; - } -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - - if (check_mul_overflow(LPFC_RAS_MIN_BUFF_POST_SIZE, - phba->cfg_ras_fwlog_buffsize, &size)) -diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c -index 18b8325fd419e..44d3ada9fbbcb 100644 ---- a/drivers/scsi/lpfc/lpfc_els.c -+++ b/drivers/scsi/lpfc/lpfc_els.c -@@ -4432,23 +4432,23 @@ lpfc_els_retry_delay(struct timer_list *t) - unsigned long flags; - struct lpfc_work_evt *evtp = &ndlp->els_retry_evt; - -+ /* Hold a node reference for outstanding queued work */ -+ if (!lpfc_nlp_get(ndlp)) -+ return; -+ - spin_lock_irqsave(&phba->hbalock, flags); - if (!list_empty(&evtp->evt_listp)) { - spin_unlock_irqrestore(&phba->hbalock, flags); -+ lpfc_nlp_put(ndlp); - return; - } - -- /* We need to hold the node by incrementing the reference -- * count until the queued work is done -- */ -- evtp->evt_arg1 = lpfc_nlp_get(ndlp); -- if (evtp->evt_arg1) { -- evtp->evt = LPFC_EVT_ELS_RETRY; -- list_add_tail(&evtp->evt_listp, &phba->work_list); -- lpfc_worker_wake_up(phba); -- } -+ evtp->evt_arg1 = ndlp; -+ evtp->evt = LPFC_EVT_ELS_RETRY; -+ list_add_tail(&evtp->evt_listp, &phba->work_list); - spin_unlock_irqrestore(&phba->hbalock, flags); -- return; -+ -+ lpfc_worker_wake_up(phba); - } - - /** -diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c -index 5154eeaee0ec3..93703ab6ce037 100644 ---- a/drivers/scsi/lpfc/lpfc_hbadisc.c -+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c -@@ -257,7 +257,9 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) - if (evtp->evt_arg1) { - evtp->evt = LPFC_EVT_DEV_LOSS; - list_add_tail(&evtp->evt_listp, &phba->work_list); -+ spin_unlock_irqrestore(&phba->hbalock, iflags); - lpfc_worker_wake_up(phba); -+ return; - } - spin_unlock_irqrestore(&phba->hbalock, iflags); - } else { -@@ -275,10 +277,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) - lpfc_disc_state_machine(vport, ndlp, NULL, - NLP_EVT_DEVICE_RM); - } -- - } -- -- return; - } - - /** -diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c -index 2c336953e56ca..416816d74ea1c 100644 ---- a/drivers/scsi/lpfc/lpfc_init.c -+++ b/drivers/scsi/lpfc/lpfc_init.c -@@ -7698,6 +7698,9 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba) - "NVME" : " "), - (phba->nvmet_support ? "NVMET" : " ")); - -+ /* ras_fwlog state */ -+ spin_lock_init(&phba->ras_fwlog_lock); -+ - /* Initialize the IO buffer list used by driver for SLI3 SCSI */ - spin_lock_init(&phba->scsi_buf_list_get_lock); - INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_get); -@@ -13051,7 +13054,7 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba) - rc = request_threaded_irq(eqhdl->irq, - &lpfc_sli4_hba_intr_handler, - &lpfc_sli4_hba_intr_handler_th, -- IRQF_ONESHOT, name, eqhdl); -+ 0, name, eqhdl); - if (rc) { - lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, - "0486 MSI-X fast-path (%d) " -diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c -index 96e11a26c297e..a7479258e8055 100644 ---- a/drivers/scsi/lpfc/lpfc_nvme.c -+++ b/drivers/scsi/lpfc/lpfc_nvme.c -@@ -2614,9 +2614,9 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) - /* No concern about the role change on the nvme remoteport. - * The transport will update it. - */ -- spin_lock_irq(&vport->phba->hbalock); -+ spin_lock_irq(&ndlp->lock); - ndlp->fc4_xpt_flags |= NVME_XPT_UNREG_WAIT; -- spin_unlock_irq(&vport->phba->hbalock); -+ spin_unlock_irq(&ndlp->lock); - - /* Don't let the host nvme transport keep sending keep-alives - * on this remoteport. Vport is unloading, no recovery. The -diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c -index bf879d81846b6..cf506556f3b0b 100644 ---- a/drivers/scsi/lpfc/lpfc_scsi.c -+++ b/drivers/scsi/lpfc/lpfc_scsi.c -@@ -167,11 +167,10 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) - struct Scsi_Host *shost; - struct scsi_device *sdev; - unsigned long new_queue_depth; -- unsigned long num_rsrc_err, num_cmd_success; -+ unsigned long num_rsrc_err; - int i; - - num_rsrc_err = atomic_read(&phba->num_rsrc_err); -- num_cmd_success = atomic_read(&phba->num_cmd_success); - - /* - * The error and success command counters are global per -@@ -186,20 +185,16 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) - for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { - shost = lpfc_shost_from_vport(vports[i]); - shost_for_each_device(sdev, shost) { -- new_queue_depth = -- sdev->queue_depth * num_rsrc_err / -- (num_rsrc_err + num_cmd_success); -- if (!new_queue_depth) -- new_queue_depth = sdev->queue_depth - 1; -+ if (num_rsrc_err >= sdev->queue_depth) -+ new_queue_depth = 1; - else - new_queue_depth = sdev->queue_depth - -- new_queue_depth; -+ num_rsrc_err; - scsi_change_queue_depth(sdev, new_queue_depth); - } - } - lpfc_destroy_vport_work_array(phba, vports); - atomic_set(&phba->num_rsrc_err, 0); -- atomic_set(&phba->num_cmd_success, 0); - } - - /** -diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c -index 4dfadf254a727..5af669b930193 100644 ---- a/drivers/scsi/lpfc/lpfc_sli.c -+++ b/drivers/scsi/lpfc/lpfc_sli.c -@@ -1217,9 +1217,9 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, - empty = list_empty(&phba->active_rrq_list); - list_add_tail(&rrq->list, &phba->active_rrq_list); - phba->hba_flag |= HBA_RRQ_ACTIVE; -+ spin_unlock_irqrestore(&phba->hbalock, iflags); - if (empty) - lpfc_worker_wake_up(phba); -- spin_unlock_irqrestore(&phba->hbalock, iflags); - return 0; - out: - spin_unlock_irqrestore(&phba->hbalock, iflags); -@@ -6844,9 +6844,9 @@ lpfc_ras_stop_fwlog(struct lpfc_hba *phba) - { - struct lpfc_ras_fwlog *ras_fwlog = &phba->ras_fwlog; - -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - ras_fwlog->state = INACTIVE; -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - - /* Disable FW logging to host memory */ - writel(LPFC_CTL_PDEV_CTL_DDL_RAS, -@@ -6889,9 +6889,9 @@ lpfc_sli4_ras_dma_free(struct lpfc_hba *phba) - ras_fwlog->lwpd.virt = NULL; - } - -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - ras_fwlog->state = INACTIVE; -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - } - - /** -@@ -6993,9 +6993,9 @@ lpfc_sli4_ras_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) - goto disable_ras; - } - -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - ras_fwlog->state = ACTIVE; -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - mempool_free(pmb, phba->mbox_mem_pool); - - return; -@@ -7027,9 +7027,9 @@ lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba, - uint32_t len = 0, fwlog_buffsize, fwlog_entry_count; - int rc = 0; - -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - ras_fwlog->state = INACTIVE; -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - - fwlog_buffsize = (LPFC_RAS_MIN_BUFF_POST_SIZE * - phba->cfg_ras_fwlog_buffsize); -@@ -7090,9 +7090,9 @@ lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba, - mbx_fwlog->u.request.lwpd.addr_lo = putPaddrLow(ras_fwlog->lwpd.phys); - mbx_fwlog->u.request.lwpd.addr_hi = putPaddrHigh(ras_fwlog->lwpd.phys); - -- spin_lock_irq(&phba->hbalock); -+ spin_lock_irq(&phba->ras_fwlog_lock); - ras_fwlog->state = REG_INPROGRESS; -- spin_unlock_irq(&phba->hbalock); -+ spin_unlock_irq(&phba->ras_fwlog_lock); - mbox->vport = phba->pport; - mbox->mbox_cmpl = lpfc_sli4_ras_mbox_cmpl; - -@@ -11369,18 +11369,18 @@ lpfc_sli_post_recovery_event(struct lpfc_hba *phba, - unsigned long iflags; - struct lpfc_work_evt *evtp = &ndlp->recovery_evt; - -+ /* Hold a node reference for outstanding queued work */ -+ if (!lpfc_nlp_get(ndlp)) -+ return; -+ - spin_lock_irqsave(&phba->hbalock, iflags); - if (!list_empty(&evtp->evt_listp)) { - spin_unlock_irqrestore(&phba->hbalock, iflags); -+ lpfc_nlp_put(ndlp); - return; - } - -- /* Incrementing the reference count until the queued work is done. */ -- evtp->evt_arg1 = lpfc_nlp_get(ndlp); -- if (!evtp->evt_arg1) { -- spin_unlock_irqrestore(&phba->hbalock, iflags); -- return; -- } -+ evtp->evt_arg1 = ndlp; - evtp->evt = LPFC_EVT_RECOVER_PORT; - list_add_tail(&evtp->evt_listp, &phba->work_list); - spin_unlock_irqrestore(&phba->hbalock, iflags); -diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c -index 6c7559cf1a4b6..9e0e9e02d2c47 100644 ---- a/drivers/scsi/lpfc/lpfc_vport.c -+++ b/drivers/scsi/lpfc/lpfc_vport.c -@@ -683,10 +683,6 @@ lpfc_vport_delete(struct fc_vport *fc_vport) - lpfc_free_sysfs_attr(vport); - lpfc_debugfs_terminate(vport); - -- /* Remove FC host to break driver binding. */ -- fc_remove_host(shost); -- scsi_remove_host(shost); -- - /* Send the DA_ID and Fabric LOGO to cleanup Nameserver entries. */ - ndlp = lpfc_findnode_did(vport, Fabric_DID); - if (!ndlp) -@@ -730,6 +726,10 @@ lpfc_vport_delete(struct fc_vport *fc_vport) - - skip_logo: - -+ /* Remove FC host to break driver binding. */ -+ fc_remove_host(shost); -+ scsi_remove_host(shost); -+ - lpfc_cleanup(vport); - - /* Remove scsi host now. The nodes are cleaned up. */ -diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c -index 9dacbb8570c93..aa5b535e6662b 100644 ---- a/drivers/scsi/mpi3mr/mpi3mr_app.c -+++ b/drivers/scsi/mpi3mr/mpi3mr_app.c -@@ -1345,7 +1345,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job, unsigned int *reply - if ((mpirep_offset != 0xFF) && - drv_bufs[mpirep_offset].bsg_buf_len) { - drv_buf_iter = &drv_bufs[mpirep_offset]; -- drv_buf_iter->kern_buf_len = (sizeof(*bsg_reply_buf) - 1 + -+ drv_buf_iter->kern_buf_len = (sizeof(*bsg_reply_buf) + - mrioc->reply_sz); - bsg_reply_buf = kzalloc(drv_buf_iter->kern_buf_len, GFP_KERNEL); - -diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c -index 77aa6d26476cd..0da5d9d1af037 100644 ---- a/drivers/slimbus/qcom-ngd-ctrl.c -+++ b/drivers/slimbus/qcom-ngd-ctrl.c -@@ -1451,7 +1451,11 @@ static void qcom_slim_ngd_up_worker(struct work_struct *work) - ctrl = container_of(work, struct qcom_slim_ngd_ctrl, ngd_up_work); - - /* Make sure qmi service is up before continuing */ -- wait_for_completion_interruptible(&ctrl->qmi_up); -+ if (!wait_for_completion_interruptible_timeout(&ctrl->qmi_up, -+ msecs_to_jiffies(MSEC_PER_SEC))) { -+ dev_err(ctrl->dev, "QMI wait timeout\n"); -+ return; -+ } - - mutex_lock(&ctrl->ssr_lock); - qcom_slim_ngd_enable(ctrl, true); -diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c -index 0258c9a72fdcc..9faee4fcc049a 100644 ---- a/drivers/spi/spi-axi-spi-engine.c -+++ b/drivers/spi/spi-axi-spi-engine.c -@@ -6,6 +6,8 @@ - */ - - #include -+#include -+#include - #include - #include - #include -@@ -13,12 +15,6 @@ - #include - #include - --#define SPI_ENGINE_VERSION_MAJOR(x) ((x >> 16) & 0xff) --#define SPI_ENGINE_VERSION_MINOR(x) ((x >> 8) & 0xff) --#define SPI_ENGINE_VERSION_PATCH(x) (x & 0xff) -- --#define SPI_ENGINE_REG_VERSION 0x00 -- - #define SPI_ENGINE_REG_RESET 0x40 - - #define SPI_ENGINE_REG_INT_ENABLE 0x80 -@@ -78,28 +74,42 @@ struct spi_engine_program { - uint16_t instructions[]; - }; - --struct spi_engine { -- struct clk *clk; -- struct clk *ref_clk; -- -- spinlock_t lock; -- -- void __iomem *base; -- -- struct spi_message *msg; -+/** -+ * struct spi_engine_message_state - SPI engine per-message state -+ */ -+struct spi_engine_message_state { -+ /** Instructions for executing this message. */ - struct spi_engine_program *p; -+ /** Number of elements in cmd_buf array. */ - unsigned cmd_length; -+ /** Array of commands not yet written to CMD FIFO. */ - const uint16_t *cmd_buf; -- -+ /** Next xfer with tx_buf not yet fully written to TX FIFO. */ - struct spi_transfer *tx_xfer; -+ /** Size of tx_buf in bytes. */ - unsigned int tx_length; -+ /** Bytes not yet written to TX FIFO. */ - const uint8_t *tx_buf; -- -+ /** Next xfer with rx_buf not yet fully written to RX FIFO. */ - struct spi_transfer *rx_xfer; -+ /** Size of tx_buf in bytes. */ - unsigned int rx_length; -+ /** Bytes not yet written to the RX FIFO. */ - uint8_t *rx_buf; -+ /** ID to correlate SYNC interrupts with this message. */ -+ u8 sync_id; -+}; -+ -+struct spi_engine { -+ struct clk *clk; -+ struct clk *ref_clk; -+ -+ spinlock_t lock; -+ -+ void __iomem *base; - -- unsigned int sync_id; -+ struct spi_message *msg; -+ struct ida sync_ida; - unsigned int completed_id; - - unsigned int int_enable; -@@ -258,100 +268,105 @@ static void spi_engine_xfer_next(struct spi_engine *spi_engine, - - static void spi_engine_tx_next(struct spi_engine *spi_engine) - { -- struct spi_transfer *xfer = spi_engine->tx_xfer; -+ struct spi_engine_message_state *st = spi_engine->msg->state; -+ struct spi_transfer *xfer = st->tx_xfer; - - do { - spi_engine_xfer_next(spi_engine, &xfer); - } while (xfer && !xfer->tx_buf); - -- spi_engine->tx_xfer = xfer; -+ st->tx_xfer = xfer; - if (xfer) { -- spi_engine->tx_length = xfer->len; -- spi_engine->tx_buf = xfer->tx_buf; -+ st->tx_length = xfer->len; -+ st->tx_buf = xfer->tx_buf; - } else { -- spi_engine->tx_buf = NULL; -+ st->tx_buf = NULL; - } - } - - static void spi_engine_rx_next(struct spi_engine *spi_engine) - { -- struct spi_transfer *xfer = spi_engine->rx_xfer; -+ struct spi_engine_message_state *st = spi_engine->msg->state; -+ struct spi_transfer *xfer = st->rx_xfer; - - do { - spi_engine_xfer_next(spi_engine, &xfer); - } while (xfer && !xfer->rx_buf); - -- spi_engine->rx_xfer = xfer; -+ st->rx_xfer = xfer; - if (xfer) { -- spi_engine->rx_length = xfer->len; -- spi_engine->rx_buf = xfer->rx_buf; -+ st->rx_length = xfer->len; -+ st->rx_buf = xfer->rx_buf; - } else { -- spi_engine->rx_buf = NULL; -+ st->rx_buf = NULL; - } - } - - static bool spi_engine_write_cmd_fifo(struct spi_engine *spi_engine) - { - void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_CMD_FIFO; -+ struct spi_engine_message_state *st = spi_engine->msg->state; - unsigned int n, m, i; - const uint16_t *buf; - - n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_CMD_FIFO_ROOM); -- while (n && spi_engine->cmd_length) { -- m = min(n, spi_engine->cmd_length); -- buf = spi_engine->cmd_buf; -+ while (n && st->cmd_length) { -+ m = min(n, st->cmd_length); -+ buf = st->cmd_buf; - for (i = 0; i < m; i++) - writel_relaxed(buf[i], addr); -- spi_engine->cmd_buf += m; -- spi_engine->cmd_length -= m; -+ st->cmd_buf += m; -+ st->cmd_length -= m; - n -= m; - } - -- return spi_engine->cmd_length != 0; -+ return st->cmd_length != 0; - } - - static bool spi_engine_write_tx_fifo(struct spi_engine *spi_engine) - { - void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_SDO_DATA_FIFO; -+ struct spi_engine_message_state *st = spi_engine->msg->state; - unsigned int n, m, i; - const uint8_t *buf; - - n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_SDO_FIFO_ROOM); -- while (n && spi_engine->tx_length) { -- m = min(n, spi_engine->tx_length); -- buf = spi_engine->tx_buf; -+ while (n && st->tx_length) { -+ m = min(n, st->tx_length); -+ buf = st->tx_buf; - for (i = 0; i < m; i++) - writel_relaxed(buf[i], addr); -- spi_engine->tx_buf += m; -- spi_engine->tx_length -= m; -+ st->tx_buf += m; -+ st->tx_length -= m; - n -= m; -- if (spi_engine->tx_length == 0) -+ if (st->tx_length == 0) - spi_engine_tx_next(spi_engine); - } - -- return spi_engine->tx_length != 0; -+ return st->tx_length != 0; - } - - static bool spi_engine_read_rx_fifo(struct spi_engine *spi_engine) - { - void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_SDI_DATA_FIFO; -+ struct spi_engine_message_state *st = spi_engine->msg->state; - unsigned int n, m, i; - uint8_t *buf; - - n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_SDI_FIFO_LEVEL); -- while (n && spi_engine->rx_length) { -- m = min(n, spi_engine->rx_length); -- buf = spi_engine->rx_buf; -+ while (n && st->rx_length) { -+ m = min(n, st->rx_length); -+ buf = st->rx_buf; - for (i = 0; i < m; i++) - buf[i] = readl_relaxed(addr); -- spi_engine->rx_buf += m; -- spi_engine->rx_length -= m; -+ st->rx_buf += m; -+ st->rx_length -= m; - n -= m; -- if (spi_engine->rx_length == 0) -+ if (st->rx_length == 0) - spi_engine_rx_next(spi_engine); - } - -- return spi_engine->rx_length != 0; -+ return st->rx_length != 0; - } - - static irqreturn_t spi_engine_irq(int irq, void *devid) -@@ -387,12 +402,16 @@ static irqreturn_t spi_engine_irq(int irq, void *devid) - disable_int |= SPI_ENGINE_INT_SDI_ALMOST_FULL; - } - -- if (pending & SPI_ENGINE_INT_SYNC) { -- if (spi_engine->msg && -- spi_engine->completed_id == spi_engine->sync_id) { -+ if (pending & SPI_ENGINE_INT_SYNC && spi_engine->msg) { -+ struct spi_engine_message_state *st = spi_engine->msg->state; -+ -+ if (spi_engine->completed_id == st->sync_id) { - struct spi_message *msg = spi_engine->msg; -+ struct spi_engine_message_state *st = msg->state; - -- kfree(spi_engine->p); -+ ida_free(&spi_engine->sync_ida, st->sync_id); -+ kfree(st->p); -+ kfree(st); - msg->status = 0; - msg->actual_length = msg->frame_length; - spi_engine->msg = NULL; -@@ -417,29 +436,46 @@ static int spi_engine_transfer_one_message(struct spi_controller *host, - { - struct spi_engine_program p_dry, *p; - struct spi_engine *spi_engine = spi_controller_get_devdata(host); -+ struct spi_engine_message_state *st; - unsigned int int_enable = 0; - unsigned long flags; - size_t size; -+ int ret; -+ -+ st = kzalloc(sizeof(*st), GFP_KERNEL); -+ if (!st) -+ return -ENOMEM; - - p_dry.length = 0; - spi_engine_compile_message(spi_engine, msg, true, &p_dry); - - size = sizeof(*p->instructions) * (p_dry.length + 1); - p = kzalloc(sizeof(*p) + size, GFP_KERNEL); -- if (!p) -+ if (!p) { -+ kfree(st); - return -ENOMEM; -+ } -+ -+ ret = ida_alloc_range(&spi_engine->sync_ida, 0, U8_MAX, GFP_KERNEL); -+ if (ret < 0) { -+ kfree(p); -+ kfree(st); -+ return ret; -+ } -+ -+ st->sync_id = ret; -+ - spi_engine_compile_message(spi_engine, msg, false, p); - - spin_lock_irqsave(&spi_engine->lock, flags); -- spi_engine->sync_id = (spi_engine->sync_id + 1) & 0xff; -- spi_engine_program_add_cmd(p, false, -- SPI_ENGINE_CMD_SYNC(spi_engine->sync_id)); -+ spi_engine_program_add_cmd(p, false, SPI_ENGINE_CMD_SYNC(st->sync_id)); - -+ msg->state = st; - spi_engine->msg = msg; -- spi_engine->p = p; -+ st->p = p; - -- spi_engine->cmd_buf = p->instructions; -- spi_engine->cmd_length = p->length; -+ st->cmd_buf = p->instructions; -+ st->cmd_length = p->length; - if (spi_engine_write_cmd_fifo(spi_engine)) - int_enable |= SPI_ENGINE_INT_CMD_ALMOST_EMPTY; - -@@ -448,7 +484,7 @@ static int spi_engine_transfer_one_message(struct spi_controller *host, - int_enable |= SPI_ENGINE_INT_SDO_ALMOST_EMPTY; - - spi_engine_rx_next(spi_engine); -- if (spi_engine->rx_length != 0) -+ if (st->rx_length != 0) - int_enable |= SPI_ENGINE_INT_SDI_ALMOST_FULL; - - int_enable |= SPI_ENGINE_INT_SYNC; -@@ -473,52 +509,34 @@ static int spi_engine_probe(struct platform_device *pdev) - if (irq < 0) - return irq; - -- spi_engine = devm_kzalloc(&pdev->dev, sizeof(*spi_engine), GFP_KERNEL); -- if (!spi_engine) -- return -ENOMEM; -- -- host = spi_alloc_host(&pdev->dev, 0); -+ host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi_engine)); - if (!host) - return -ENOMEM; - -- spi_controller_set_devdata(host, spi_engine); -+ spi_engine = spi_controller_get_devdata(host); - - spin_lock_init(&spi_engine->lock); -+ ida_init(&spi_engine->sync_ida); - -- spi_engine->clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); -- if (IS_ERR(spi_engine->clk)) { -- ret = PTR_ERR(spi_engine->clk); -- goto err_put_host; -- } -- -- spi_engine->ref_clk = devm_clk_get(&pdev->dev, "spi_clk"); -- if (IS_ERR(spi_engine->ref_clk)) { -- ret = PTR_ERR(spi_engine->ref_clk); -- goto err_put_host; -- } -+ spi_engine->clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk"); -+ if (IS_ERR(spi_engine->clk)) -+ return PTR_ERR(spi_engine->clk); - -- ret = clk_prepare_enable(spi_engine->clk); -- if (ret) -- goto err_put_host; -- -- ret = clk_prepare_enable(spi_engine->ref_clk); -- if (ret) -- goto err_clk_disable; -+ spi_engine->ref_clk = devm_clk_get_enabled(&pdev->dev, "spi_clk"); -+ if (IS_ERR(spi_engine->ref_clk)) -+ return PTR_ERR(spi_engine->ref_clk); - - spi_engine->base = devm_platform_ioremap_resource(pdev, 0); -- if (IS_ERR(spi_engine->base)) { -- ret = PTR_ERR(spi_engine->base); -- goto err_ref_clk_disable; -- } -- -- version = readl(spi_engine->base + SPI_ENGINE_REG_VERSION); -- if (SPI_ENGINE_VERSION_MAJOR(version) != 1) { -- dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%c\n", -- SPI_ENGINE_VERSION_MAJOR(version), -- SPI_ENGINE_VERSION_MINOR(version), -- SPI_ENGINE_VERSION_PATCH(version)); -- ret = -ENODEV; -- goto err_ref_clk_disable; -+ if (IS_ERR(spi_engine->base)) -+ return PTR_ERR(spi_engine->base); -+ -+ version = readl(spi_engine->base + ADI_AXI_REG_VERSION); -+ if (ADI_AXI_PCORE_VER_MAJOR(version) != 1) { -+ dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%u\n", -+ ADI_AXI_PCORE_VER_MAJOR(version), -+ ADI_AXI_PCORE_VER_MINOR(version), -+ ADI_AXI_PCORE_VER_PATCH(version)); -+ return -ENODEV; - } - - writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_RESET); -@@ -527,7 +545,7 @@ static int spi_engine_probe(struct platform_device *pdev) - - ret = request_irq(irq, spi_engine_irq, 0, pdev->name, host); - if (ret) -- goto err_ref_clk_disable; -+ return ret; - - host->dev.of_node = pdev->dev.of_node; - host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE; -@@ -545,18 +563,12 @@ static int spi_engine_probe(struct platform_device *pdev) - return 0; - err_free_irq: - free_irq(irq, host); --err_ref_clk_disable: -- clk_disable_unprepare(spi_engine->ref_clk); --err_clk_disable: -- clk_disable_unprepare(spi_engine->clk); --err_put_host: -- spi_controller_put(host); - return ret; - } - - static void spi_engine_remove(struct platform_device *pdev) - { -- struct spi_controller *host = spi_controller_get(platform_get_drvdata(pdev)); -+ struct spi_controller *host = platform_get_drvdata(pdev); - struct spi_engine *spi_engine = spi_controller_get_devdata(host); - int irq = platform_get_irq(pdev, 0); - -@@ -564,14 +576,9 @@ static void spi_engine_remove(struct platform_device *pdev) - - free_irq(irq, host); - -- spi_controller_put(host); -- - writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING); - writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); - writel_relaxed(0x01, spi_engine->base + SPI_ENGINE_REG_RESET); -- -- clk_disable_unprepare(spi_engine->ref_clk); -- clk_disable_unprepare(spi_engine->clk); - } - - static const struct of_device_id spi_engine_match_table[] = { -diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c -index 35ef5e8e2ffd2..77e9738e42f60 100644 ---- a/drivers/spi/spi-hisi-kunpeng.c -+++ b/drivers/spi/spi-hisi-kunpeng.c -@@ -151,8 +151,6 @@ static const struct debugfs_reg32 hisi_spi_regs[] = { - HISI_SPI_DBGFS_REG("ENR", HISI_SPI_ENR), - HISI_SPI_DBGFS_REG("FIFOC", HISI_SPI_FIFOC), - HISI_SPI_DBGFS_REG("IMR", HISI_SPI_IMR), -- HISI_SPI_DBGFS_REG("DIN", HISI_SPI_DIN), -- HISI_SPI_DBGFS_REG("DOUT", HISI_SPI_DOUT), - HISI_SPI_DBGFS_REG("SR", HISI_SPI_SR), - HISI_SPI_DBGFS_REG("RISR", HISI_SPI_RISR), - HISI_SPI_DBGFS_REG("ISR", HISI_SPI_ISR), -diff --git a/drivers/spi/spi-microchip-core-qspi.c b/drivers/spi/spi-microchip-core-qspi.c -index 4f76ddf97b10f..32a0fa4ba50f7 100644 ---- a/drivers/spi/spi-microchip-core-qspi.c -+++ b/drivers/spi/spi-microchip-core-qspi.c -@@ -283,6 +283,7 @@ static int mchp_coreqspi_setup_clock(struct mchp_coreqspi *qspi, struct spi_devi - } - - control = readl_relaxed(qspi->regs + REG_CONTROL); -+ control &= ~CONTROL_CLKRATE_MASK; - control |= baud_rate_val << CONTROL_CLKRATE_SHIFT; - writel_relaxed(control, qspi->regs + REG_CONTROL); - control = readl_relaxed(qspi->regs + REG_CONTROL); -diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c -index 1e08cd571d21a..76383ddbd6a6f 100644 ---- a/drivers/spi/spi.c -+++ b/drivers/spi/spi.c -@@ -4261,6 +4261,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message) - wait_for_completion(&done); - status = message->status; - } -+ message->complete = NULL; - message->context = NULL; - - return status; -diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c -index d5860c1c1f469..9a88774836c9d 100644 ---- a/drivers/target/target_core_configfs.c -+++ b/drivers/target/target_core_configfs.c -@@ -3634,6 +3634,8 @@ static int __init target_core_init_configfs(void) - { - struct configfs_subsystem *subsys = &target_core_fabrics; - struct t10_alua_lu_gp *lu_gp; -+ struct cred *kern_cred; -+ const struct cred *old_cred; - int ret; - - pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage" -@@ -3710,11 +3712,21 @@ static int __init target_core_init_configfs(void) - if (ret < 0) - goto out; - -+ /* We use the kernel credentials to access the target directory */ -+ kern_cred = prepare_kernel_cred(&init_task); -+ if (!kern_cred) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ old_cred = override_creds(kern_cred); - target_init_dbroot(); -+ revert_creds(old_cred); -+ put_cred(kern_cred); - - return 0; - - out: -+ target_xcopy_release_pt(); - configfs_unregister_subsystem(subsys); - core_dev_release_virtual_lun0(); - rd_module_exit(); -diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c -index 0787456c2b892..c873fd8239427 100644 ---- a/drivers/ufs/core/ufs-mcq.c -+++ b/drivers/ufs/core/ufs-mcq.c -@@ -94,7 +94,7 @@ void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds) - - val = ufshcd_readl(hba, REG_UFS_MCQ_CFG); - val &= ~MCQ_CFG_MAC_MASK; -- val |= FIELD_PREP(MCQ_CFG_MAC_MASK, max_active_cmds); -+ val |= FIELD_PREP(MCQ_CFG_MAC_MASK, max_active_cmds - 1); - ufshcd_writel(hba, val, REG_UFS_MCQ_CFG); - } - EXPORT_SYMBOL_GPL(ufshcd_mcq_config_mac); -diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c -index ee9119b708f01..344806330be16 100644 ---- a/drivers/ufs/core/ufshcd.c -+++ b/drivers/ufs/core/ufshcd.c -@@ -3064,7 +3064,9 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba, - - /* MCQ mode */ - if (is_mcq_enabled(hba)) { -- err = ufshcd_clear_cmd(hba, lrbp->task_tag); -+ /* successfully cleared the command, retry if needed */ -+ if (ufshcd_clear_cmd(hba, lrbp->task_tag) == 0) -+ err = -EAGAIN; - hba->dev_cmd.complete = NULL; - return err; - } -@@ -9547,7 +9549,10 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) - - /* UFS device & link must be active before we enter in this function */ - if (!ufshcd_is_ufs_dev_active(hba) || !ufshcd_is_link_active(hba)) { -- ret = -EINVAL; -+ /* Wait err handler finish or trigger err recovery */ -+ if (!ufshcd_eh_in_progress(hba)) -+ ufshcd_force_error_recovery(hba); -+ ret = -EBUSY; - goto enable_scaling; - } - -diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c -index 20d9762331bd7..6be3462b109ff 100644 ---- a/drivers/uio/uio_hv_generic.c -+++ b/drivers/uio/uio_hv_generic.c -@@ -181,12 +181,14 @@ hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata) - { - if (pdata->send_gpadl.gpadl_handle) { - vmbus_teardown_gpadl(dev->channel, &pdata->send_gpadl); -- vfree(pdata->send_buf); -+ if (!pdata->send_gpadl.decrypted) -+ vfree(pdata->send_buf); - } - - if (pdata->recv_gpadl.gpadl_handle) { - vmbus_teardown_gpadl(dev->channel, &pdata->recv_gpadl); -- vfree(pdata->recv_buf); -+ if (!pdata->recv_gpadl.decrypted) -+ vfree(pdata->recv_buf); - } - } - -@@ -295,7 +297,8 @@ hv_uio_probe(struct hv_device *dev, - ret = vmbus_establish_gpadl(channel, pdata->recv_buf, - RECV_BUFFER_SIZE, &pdata->recv_gpadl); - if (ret) { -- vfree(pdata->recv_buf); -+ if (!pdata->recv_gpadl.decrypted) -+ vfree(pdata->recv_buf); - goto fail_close; - } - -@@ -317,7 +320,8 @@ hv_uio_probe(struct hv_device *dev, - ret = vmbus_establish_gpadl(channel, pdata->send_buf, - SEND_BUFFER_SIZE, &pdata->send_gpadl); - if (ret) { -- vfree(pdata->send_buf); -+ if (!pdata->send_gpadl.decrypted) -+ vfree(pdata->send_buf); - goto fail_close; - } - -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 7417972202b8b..1ba3feb5e1900 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -5077,9 +5077,10 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, - } - if (usb_endpoint_maxp(&udev->ep0.desc) == i) { - ; /* Initial ep0 maxpacket guess is right */ -- } else if ((udev->speed == USB_SPEED_FULL || -+ } else if (((udev->speed == USB_SPEED_FULL || - udev->speed == USB_SPEED_HIGH) && -- (i == 8 || i == 16 || i == 32 || i == 64)) { -+ (i == 8 || i == 16 || i == 32 || i == 64)) || -+ (udev->speed >= USB_SPEED_SUPER && i > 0)) { - /* Initial guess is wrong; use the descriptor's value */ - if (udev->speed == USB_SPEED_FULL) - dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i); -diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c -index 76e00bfedc25c..5fb3f55ef06db 100644 ---- a/drivers/usb/core/port.c -+++ b/drivers/usb/core/port.c -@@ -50,13 +50,15 @@ static ssize_t disable_show(struct device *dev, - struct usb_port *port_dev = to_usb_port(dev); - struct usb_device *hdev = to_usb_device(dev->parent->parent); - struct usb_hub *hub = usb_hub_to_struct_hub(hdev); -- struct usb_interface *intf = to_usb_interface(hub->intfdev); -+ struct usb_interface *intf = to_usb_interface(dev->parent); - int port1 = port_dev->portnum; - u16 portstatus, unused; - bool disabled; - int rc; - struct kernfs_node *kn; - -+ if (!hub) -+ return -ENODEV; - hub_get(hub); - rc = usb_autopm_get_interface(intf); - if (rc < 0) -@@ -100,12 +102,14 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr, - struct usb_port *port_dev = to_usb_port(dev); - struct usb_device *hdev = to_usb_device(dev->parent->parent); - struct usb_hub *hub = usb_hub_to_struct_hub(hdev); -- struct usb_interface *intf = to_usb_interface(hub->intfdev); -+ struct usb_interface *intf = to_usb_interface(dev->parent); - int port1 = port_dev->portnum; - bool disabled; - int rc; - struct kernfs_node *kn; - -+ if (!hub) -+ return -ENODEV; - rc = kstrtobool(buf, &disabled); - if (rc) - return rc; -diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c -index 7d50c81ce97ee..1f66578c671e7 100644 ---- a/drivers/usb/dwc3/core.c -+++ b/drivers/usb/dwc3/core.c -@@ -104,6 +104,27 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) - return 0; - } - -+void dwc3_enable_susphy(struct dwc3 *dwc, bool enable) -+{ -+ u32 reg; -+ -+ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); -+ if (enable && !dwc->dis_u3_susphy_quirk) -+ reg |= DWC3_GUSB3PIPECTL_SUSPHY; -+ else -+ reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; -+ -+ dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); -+ -+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); -+ if (enable && !dwc->dis_u2_susphy_quirk) -+ reg |= DWC3_GUSB2PHYCFG_SUSPHY; -+ else -+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; -+ -+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); -+} -+ - void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) - { - u32 reg; -@@ -585,11 +606,8 @@ static int dwc3_core_ulpi_init(struct dwc3 *dwc) - */ - static int dwc3_phy_setup(struct dwc3 *dwc) - { -- unsigned int hw_mode; - u32 reg; - -- hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); -- - reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); - - /* -@@ -599,21 +617,16 @@ static int dwc3_phy_setup(struct dwc3 *dwc) - reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX; - - /* -- * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY -- * to '0' during coreConsultant configuration. So default value -- * will be '0' when the core is reset. Application needs to set it -- * to '1' after the core initialization is completed. -- */ -- if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) -- reg |= DWC3_GUSB3PIPECTL_SUSPHY; -- -- /* -- * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be cleared after -- * power-on reset, and it can be set after core initialization, which is -- * after device soft-reset during initialization. -+ * Above DWC_usb3.0 1.94a, it is recommended to set -+ * DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration. -+ * So default value will be '0' when the core is reset. Application -+ * needs to set it to '1' after the core initialization is completed. -+ * -+ * Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be -+ * cleared after power-on reset, and it can be set after core -+ * initialization. - */ -- if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD) -- reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; -+ reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; - - if (dwc->u2ss_inp3_quirk) - reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; -@@ -639,9 +652,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc) - if (dwc->tx_de_emphasis_quirk) - reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); - -- if (dwc->dis_u3_susphy_quirk) -- reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; -- - if (dwc->dis_del_phy_power_chg_quirk) - reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE; - -@@ -689,24 +699,15 @@ static int dwc3_phy_setup(struct dwc3 *dwc) - } - - /* -- * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to -- * '0' during coreConsultant configuration. So default value will -- * be '0' when the core is reset. Application needs to set it to -- * '1' after the core initialization is completed. -- */ -- if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) -- reg |= DWC3_GUSB2PHYCFG_SUSPHY; -- -- /* -- * For DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared after -- * power-on reset, and it can be set after core initialization, which is -- * after device soft-reset during initialization. -+ * Above DWC_usb3.0 1.94a, it is recommended to set -+ * DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration. -+ * So default value will be '0' when the core is reset. Application -+ * needs to set it to '1' after the core initialization is completed. -+ * -+ * Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared -+ * after power-on reset, and it can be set after core initialization. - */ -- if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD) -- reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; -- -- if (dwc->dis_u2_susphy_quirk) -- reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; -+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; - - if (dwc->dis_enblslpm_quirk) - reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; -@@ -1213,21 +1214,6 @@ static int dwc3_core_init(struct dwc3 *dwc) - if (ret) - goto err_exit_phy; - -- if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD && -- !DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) { -- if (!dwc->dis_u3_susphy_quirk) { -- reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); -- reg |= DWC3_GUSB3PIPECTL_SUSPHY; -- dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); -- } -- -- if (!dwc->dis_u2_susphy_quirk) { -- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); -- reg |= DWC3_GUSB2PHYCFG_SUSPHY; -- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); -- } -- } -- - dwc3_core_setup_global_control(dwc); - dwc3_core_num_eps(dwc); - -diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h -index 5e6ead35dffc2..69b734a7bae1c 100644 ---- a/drivers/usb/dwc3/core.h -+++ b/drivers/usb/dwc3/core.h -@@ -1567,6 +1567,7 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc); - void dwc3_event_buffers_cleanup(struct dwc3 *dwc); - - int dwc3_core_soft_reset(struct dwc3 *dwc); -+void dwc3_enable_susphy(struct dwc3 *dwc, bool enable); - - #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) - int dwc3_host_init(struct dwc3 *dwc); -diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c -index 07820b1a88a24..4062a486b9e63 100644 ---- a/drivers/usb/dwc3/gadget.c -+++ b/drivers/usb/dwc3/gadget.c -@@ -2937,6 +2937,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) - dwc3_ep0_out_start(dwc); - - dwc3_gadget_enable_irq(dwc); -+ dwc3_enable_susphy(dwc, true); - - return 0; - -@@ -4703,6 +4704,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc) - if (!dwc->gadget) - return; - -+ dwc3_enable_susphy(dwc, false); - usb_del_gadget(dwc->gadget); - dwc3_gadget_free_endpoints(dwc); - usb_put_gadget(dwc->gadget); -diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c -index f6a020d77fa18..6c143f7d24103 100644 ---- a/drivers/usb/dwc3/host.c -+++ b/drivers/usb/dwc3/host.c -@@ -10,9 +10,30 @@ - #include - #include - #include -+#include -+#include - -+#include "../host/xhci-plat.h" - #include "core.h" - -+static void dwc3_xhci_plat_start(struct usb_hcd *hcd) -+{ -+ struct platform_device *pdev; -+ struct dwc3 *dwc; -+ -+ if (!usb_hcd_is_primary_hcd(hcd)) -+ return; -+ -+ pdev = to_platform_device(hcd->self.controller); -+ dwc = dev_get_drvdata(pdev->dev.parent); -+ -+ dwc3_enable_susphy(dwc, true); -+} -+ -+static const struct xhci_plat_priv dwc3_xhci_plat_quirk = { -+ .plat_start = dwc3_xhci_plat_start, -+}; -+ - static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc, - int irq, char *name) - { -@@ -117,6 +138,11 @@ int dwc3_host_init(struct dwc3 *dwc) - } - } - -+ ret = platform_device_add_data(xhci, &dwc3_xhci_plat_quirk, -+ sizeof(struct xhci_plat_priv)); -+ if (ret) -+ goto err; -+ - ret = platform_device_add(xhci); - if (ret) { - dev_err(dwc->dev, "failed to register xHCI device\n"); -@@ -142,6 +168,7 @@ void dwc3_host_exit(struct dwc3 *dwc) - if (dwc->sys_wakeup) - device_init_wakeup(&dwc->xhci->dev, false); - -+ dwc3_enable_susphy(dwc, false); - platform_device_unregister(dwc->xhci); - dwc->xhci = NULL; - } -diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c -index 0ace45b66a31c..0e151b54aae82 100644 ---- a/drivers/usb/gadget/composite.c -+++ b/drivers/usb/gadget/composite.c -@@ -2112,7 +2112,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) - buf[5] = 0x01; - switch (ctrl->bRequestType & USB_RECIP_MASK) { - case USB_RECIP_DEVICE: -- if (w_index != 0x4 || (w_value >> 8)) -+ if (w_index != 0x4 || (w_value & 0xff)) - break; - buf[6] = w_index; - /* Number of ext compat interfaces */ -@@ -2128,9 +2128,9 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) - } - break; - case USB_RECIP_INTERFACE: -- if (w_index != 0x5 || (w_value >> 8)) -+ if (w_index != 0x5 || (w_value & 0xff)) - break; -- interface = w_value & 0xFF; -+ interface = w_value >> 8; - if (interface >= MAX_CONFIG_INTERFACES || - !os_desc_cfg->interface[interface]) - break; -diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c -index 6e9ef35a43a7b..fd0f4879f38e8 100644 ---- a/drivers/usb/gadget/function/f_fs.c -+++ b/drivers/usb/gadget/function/f_fs.c -@@ -821,6 +821,7 @@ static void ffs_user_copy_worker(struct work_struct *work) - work); - int ret = io_data->status; - bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD; -+ unsigned long flags; - - if (io_data->read && ret > 0) { - kthread_use_mm(io_data->mm); -@@ -833,6 +834,11 @@ static void ffs_user_copy_worker(struct work_struct *work) - if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd) - eventfd_signal(io_data->ffs->ffs_eventfd, 1); - -+ spin_lock_irqsave(&io_data->ffs->eps_lock, flags); -+ usb_ep_free_request(io_data->ep, io_data->req); -+ io_data->req = NULL; -+ spin_unlock_irqrestore(&io_data->ffs->eps_lock, flags); -+ - if (io_data->read) - kfree(io_data->to_free); - ffs_free_buffer(io_data); -@@ -846,7 +852,6 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep, - struct ffs_data *ffs = io_data->ffs; - - io_data->status = req->status ? req->status : req->actual; -- usb_ep_free_request(_ep, req); - - INIT_WORK(&io_data->work, ffs_user_copy_worker); - queue_work(ffs->io_completion_wq, &io_data->work); -@@ -3331,7 +3336,7 @@ static int ffs_func_setup(struct usb_function *f, - __ffs_event_add(ffs, FUNCTIONFS_SETUP); - spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags); - -- return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0; -+ return ffs->ev.setup.wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0; - } - - static bool ffs_func_req_match(struct usb_function *f, -diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c -index 9bf0e985acfab..d16c04d2961b6 100644 ---- a/drivers/usb/gadget/function/uvc_configfs.c -+++ b/drivers/usb/gadget/function/uvc_configfs.c -@@ -92,10 +92,10 @@ static int __uvcg_iter_item_entries(const char *page, size_t len, - - while (pg - page < len) { - i = 0; -- while (i < sizeof(buf) && (pg - page < len) && -+ while (i < bufsize && (pg - page < len) && - *pg != '\0' && *pg != '\n') - buf[i++] = *pg++; -- if (i == sizeof(buf)) { -+ if (i == bufsize) { - ret = -EINVAL; - goto out_free_buf; - } -diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c -index 4f9982ecfb583..5cec7640e913c 100644 ---- a/drivers/usb/host/ohci-hcd.c -+++ b/drivers/usb/host/ohci-hcd.c -@@ -888,6 +888,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) - /* Check for an all 1's result which is a typical consequence - * of dead, unclocked, or unplugged (CardBus...) devices - */ -+again: - if (ints == ~(u32)0) { - ohci->rh_state = OHCI_RH_HALTED; - ohci_dbg (ohci, "device removed!\n"); -@@ -982,6 +983,13 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) - } - spin_unlock(&ohci->lock); - -+ /* repeat until all enabled interrupts are handled */ -+ if (ohci->rh_state != OHCI_RH_HALTED) { -+ ints = ohci_readl(ohci, ®s->intrstatus); -+ if (ints && (ints & ohci_readl(ohci, ®s->intrenable))) -+ goto again; -+ } -+ - return IRQ_HANDLED; - } - -diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h -index 2d15386f2c504..6475130eac4b3 100644 ---- a/drivers/usb/host/xhci-plat.h -+++ b/drivers/usb/host/xhci-plat.h -@@ -8,7 +8,9 @@ - #ifndef _XHCI_PLAT_H - #define _XHCI_PLAT_H - --#include "xhci.h" /* for hcd_to_xhci() */ -+struct device; -+struct platform_device; -+struct usb_hcd; - - struct xhci_plat_priv { - const char *firmware_name; -diff --git a/drivers/usb/host/xhci-rzv2m.c b/drivers/usb/host/xhci-rzv2m.c -index ec65b24eafa86..4f59867d7117c 100644 ---- a/drivers/usb/host/xhci-rzv2m.c -+++ b/drivers/usb/host/xhci-rzv2m.c -@@ -6,6 +6,7 @@ - */ - - #include -+#include "xhci.h" - #include "xhci-plat.h" - #include "xhci-rzv2m.h" - -diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c -index 68e024a8a1f9a..08efd4a6bd1dd 100644 ---- a/drivers/usb/typec/tcpm/tcpm.c -+++ b/drivers/usb/typec/tcpm/tcpm.c -@@ -1488,7 +1488,8 @@ static void svdm_consume_identity(struct tcpm_port *port, const u32 *p, int cnt) - port->partner_ident.cert_stat = p[VDO_INDEX_CSTAT]; - port->partner_ident.product = product; - -- typec_partner_set_identity(port->partner); -+ if (port->partner) -+ typec_partner_set_identity(port->partner); - - tcpm_log(port, "Identity: %04x:%04x.%04x", - PD_IDH_VID(vdo), -@@ -1576,6 +1577,9 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port) - struct typec_altmode *altmode; - int i; - -+ if (!port->partner) -+ return; -+ - for (i = 0; i < modep->altmodes; i++) { - altmode = typec_partner_register_altmode(port->partner, - &modep->altmode_desc[i]); -@@ -2422,7 +2426,7 @@ static int tcpm_register_sink_caps(struct tcpm_port *port) - { - struct usb_power_delivery_desc desc = { port->negotiated_rev }; - struct usb_power_delivery_capabilities_desc caps = { }; -- struct usb_power_delivery_capabilities *cap; -+ struct usb_power_delivery_capabilities *cap = port->partner_source_caps; - - if (!port->partner_pd) - port->partner_pd = usb_power_delivery_register(NULL, &desc); -@@ -2432,6 +2436,9 @@ static int tcpm_register_sink_caps(struct tcpm_port *port) - memcpy(caps.pdo, port->sink_caps, sizeof(u32) * port->nr_sink_caps); - caps.role = TYPEC_SINK; - -+ if (cap) -+ usb_power_delivery_unregister_capabilities(cap); -+ - cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps); - if (IS_ERR(cap)) - return PTR_ERR(cap); -@@ -3571,7 +3578,10 @@ static int tcpm_init_vconn(struct tcpm_port *port) - - static void tcpm_typec_connect(struct tcpm_port *port) - { -+ struct typec_partner *partner; -+ - if (!port->connected) { -+ port->connected = true; - /* Make sure we don't report stale identity information */ - memset(&port->partner_ident, 0, sizeof(port->partner_ident)); - port->partner_desc.usb_pd = port->pd_capable; -@@ -3581,9 +3591,13 @@ static void tcpm_typec_connect(struct tcpm_port *port) - port->partner_desc.accessory = TYPEC_ACCESSORY_AUDIO; - else - port->partner_desc.accessory = TYPEC_ACCESSORY_NONE; -- port->partner = typec_register_partner(port->typec_port, -- &port->partner_desc); -- port->connected = true; -+ partner = typec_register_partner(port->typec_port, &port->partner_desc); -+ if (IS_ERR(partner)) { -+ dev_err(port->dev, "Failed to register partner (%ld)\n", PTR_ERR(partner)); -+ return; -+ } -+ -+ port->partner = partner; - typec_partner_set_usb_power_delivery(port->partner, port->partner_pd); - } - } -@@ -3653,9 +3667,11 @@ static int tcpm_src_attach(struct tcpm_port *port) - static void tcpm_typec_disconnect(struct tcpm_port *port) - { - if (port->connected) { -- typec_partner_set_usb_power_delivery(port->partner, NULL); -- typec_unregister_partner(port->partner); -- port->partner = NULL; -+ if (port->partner) { -+ typec_partner_set_usb_power_delivery(port->partner, NULL); -+ typec_unregister_partner(port->partner); -+ port->partner = NULL; -+ } - port->connected = false; - } - } -@@ -3871,6 +3887,9 @@ static enum typec_cc_status tcpm_pwr_opmode_to_rp(enum typec_pwr_opmode opmode) - - static void tcpm_set_initial_svdm_version(struct tcpm_port *port) - { -+ if (!port->partner) -+ return; -+ - switch (port->negotiated_rev) { - case PD_REV30: - break; -@@ -4859,6 +4878,7 @@ static void run_state_machine(struct tcpm_port *port) - break; - case PORT_RESET: - tcpm_reset_port(port); -+ port->pd_events = 0; - if (port->self_powered) - tcpm_set_cc(port, TYPEC_CC_OPEN); - else -diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c -index c4f5ee171cdeb..7d2ca39ad7622 100644 ---- a/drivers/usb/typec/ucsi/ucsi.c -+++ b/drivers/usb/typec/ucsi/ucsi.c -@@ -972,7 +972,7 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num) - struct ucsi_connector *con = &ucsi->connector[num - 1]; - - if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) { -- dev_dbg(ucsi->dev, "Bogus connector change event\n"); -+ dev_dbg(ucsi->dev, "Early connector change event\n"); - return; - } - -@@ -1403,6 +1403,7 @@ static int ucsi_init(struct ucsi *ucsi) - { - struct ucsi_connector *con, *connector; - u64 command, ntfy; -+ u32 cci; - int ret; - int i; - -@@ -1455,6 +1456,15 @@ static int ucsi_init(struct ucsi *ucsi) - - ucsi->connector = connector; - ucsi->ntfy = ntfy; -+ -+ mutex_lock(&ucsi->ppm_lock); -+ ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); -+ mutex_unlock(&ucsi->ppm_lock); -+ if (ret) -+ return ret; -+ if (UCSI_CCI_CONNECTOR(cci)) -+ ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci)); -+ - return 0; - - err_unregister: -diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c -index cb5b7f865d585..e727941f589de 100644 ---- a/drivers/vfio/pci/vfio_pci.c -+++ b/drivers/vfio/pci/vfio_pci.c -@@ -71,6 +71,8 @@ static bool vfio_pci_dev_in_denylist(struct pci_dev *pdev) - case PCI_DEVICE_ID_INTEL_QAT_C62X_VF: - case PCI_DEVICE_ID_INTEL_QAT_DH895XCC: - case PCI_DEVICE_ID_INTEL_QAT_DH895XCC_VF: -+ case PCI_DEVICE_ID_INTEL_DSA_SPR0: -+ case PCI_DEVICE_ID_INTEL_IAX_SPR0: - return true; - default: - return false; -diff --git a/drivers/w1/slaves/w1_ds250x.c b/drivers/w1/slaves/w1_ds250x.c -index 7592c7050d1d7..cb426f7dd23d4 100644 ---- a/drivers/w1/slaves/w1_ds250x.c -+++ b/drivers/w1/slaves/w1_ds250x.c -@@ -168,6 +168,7 @@ static int w1_eprom_add_slave(struct w1_slave *sl) - struct nvmem_device *nvmem; - struct nvmem_config nvmem_cfg = { - .dev = &sl->dev, -+ .add_legacy_fixed_of_cells = true, - .reg_read = w1_nvmem_read, - .type = NVMEM_TYPE_OTP, - .read_only = true, -diff --git a/fs/9p/fid.h b/fs/9p/fid.h -index 29281b7c38870..0d6138bee2a3d 100644 ---- a/fs/9p/fid.h -+++ b/fs/9p/fid.h -@@ -49,9 +49,6 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry) - static inline void v9fs_fid_add_modes(struct p9_fid *fid, unsigned int s_flags, - unsigned int s_cache, unsigned int f_flags) - { -- if (fid->qid.type != P9_QTFILE) -- return; -- - if ((!s_cache) || - ((fid->qid.version == 0) && !(s_flags & V9FS_IGNORE_QV)) || - (s_flags & V9FS_DIRECT_IO) || (f_flags & O_DIRECT)) { -diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c -index 11cd8d23f6f23..8566ddad49ad5 100644 ---- a/fs/9p/vfs_file.c -+++ b/fs/9p/vfs_file.c -@@ -591,6 +591,7 @@ const struct file_operations v9fs_file_operations = { - .splice_read = v9fs_file_splice_read, - .splice_write = iter_file_splice_write, - .fsync = v9fs_file_fsync, -+ .setlease = simple_nosetlease, - }; - - const struct file_operations v9fs_file_operations_dotl = { -@@ -605,4 +606,5 @@ const struct file_operations v9fs_file_operations_dotl = { - .splice_read = v9fs_file_splice_read, - .splice_write = iter_file_splice_write, - .fsync = v9fs_file_fsync_dotl, -+ .setlease = simple_nosetlease, - }; -diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c -index ea695c4a7a3fb..853c63b836815 100644 ---- a/fs/9p/vfs_inode.c -+++ b/fs/9p/vfs_inode.c -@@ -83,7 +83,7 @@ static int p9mode2perm(struct v9fs_session_info *v9ses, - int res; - int mode = stat->mode; - -- res = mode & S_IALLUGO; -+ res = mode & 0777; /* S_IRWXUGO */ - if (v9fs_proto_dotu(v9ses)) { - if ((mode & P9_DMSETUID) == P9_DMSETUID) - res |= S_ISUID; -@@ -178,6 +178,9 @@ int v9fs_uflags2omode(int uflags, int extended) - break; - } - -+ if (uflags & O_TRUNC) -+ ret |= P9_OTRUNC; -+ - if (extended) { - if (uflags & O_EXCL) - ret |= P9_OEXCL; -diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c -index 73db55c050bf1..958efc8423334 100644 ---- a/fs/9p/vfs_super.c -+++ b/fs/9p/vfs_super.c -@@ -320,6 +320,7 @@ static const struct super_operations v9fs_super_ops = { - .alloc_inode = v9fs_alloc_inode, - .free_inode = v9fs_free_inode, - .statfs = simple_statfs, -+ .drop_inode = v9fs_drop_inode, - .evict_inode = v9fs_evict_inode, - .show_options = v9fs_show_options, - .umount_begin = v9fs_umount_begin, -diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c -index 5acb2cb79d4bf..9fbffd84b16c5 100644 ---- a/fs/btrfs/extent_io.c -+++ b/fs/btrfs/extent_io.c -@@ -686,24 +686,14 @@ int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array) - unsigned int last = allocated; - - allocated = alloc_pages_bulk_array(GFP_NOFS, nr_pages, page_array); -- -- if (allocated == nr_pages) -- return 0; -- -- /* -- * During this iteration, no page could be allocated, even -- * though alloc_pages_bulk_array() falls back to alloc_page() -- * if it could not bulk-allocate. So we must be out of memory. -- */ -- if (allocated == last) { -+ if (unlikely(allocated == last)) { -+ /* No progress, fail and do cleanup. */ - for (int i = 0; i < allocated; i++) { - __free_page(page_array[i]); - page_array[i] = NULL; - } - return -ENOMEM; - } -- -- memalloc_retry_wait(GFP_NOFS); - } - return 0; - } -diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c -index 33d0efa5ed794..5ddee801a8303 100644 ---- a/fs/btrfs/inode.c -+++ b/fs/btrfs/inode.c -@@ -2510,7 +2510,7 @@ void btrfs_clear_delalloc_extent(struct btrfs_inode *inode, - */ - if (bits & EXTENT_CLEAR_META_RESV && - root != fs_info->tree_root) -- btrfs_delalloc_release_metadata(inode, len, false); -+ btrfs_delalloc_release_metadata(inode, len, true); - - /* For sanity tests. */ - if (btrfs_is_testing(fs_info)) -diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c -index 2b8ff8b53af04..8a3c46cb67f53 100644 ---- a/fs/btrfs/ordered-data.c -+++ b/fs/btrfs/ordered-data.c -@@ -1202,6 +1202,7 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent( - ordered->disk_bytenr += len; - ordered->num_bytes -= len; - ordered->disk_num_bytes -= len; -+ ordered->ram_bytes -= len; - - if (test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags)) { - ASSERT(ordered->bytes_left == 0); -diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c -index b430e03260fbf..651f0865bb0df 100644 ---- a/fs/btrfs/send.c -+++ b/fs/btrfs/send.c -@@ -8222,8 +8222,8 @@ long btrfs_ioctl_send(struct inode *inode, struct btrfs_ioctl_send_args *arg) - goto out; - } - -- sctx->clone_roots = kvcalloc(sizeof(*sctx->clone_roots), -- arg->clone_sources_count + 1, -+ sctx->clone_roots = kvcalloc(arg->clone_sources_count + 1, -+ sizeof(*sctx->clone_roots), - GFP_KERNEL); - if (!sctx->clone_roots) { - ret = -ENOMEM; -diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c -index 457ec7d02a9ac..0548072c642fb 100644 ---- a/fs/btrfs/transaction.c -+++ b/fs/btrfs/transaction.c -@@ -1449,6 +1449,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans) - radix_tree_tag_clear(&fs_info->fs_roots_radix, - (unsigned long)root->root_key.objectid, - BTRFS_ROOT_TRANS_TAG); -+ btrfs_qgroup_free_meta_all_pertrans(root); - spin_unlock(&fs_info->fs_roots_radix_lock); - - btrfs_free_log(trans, root); -@@ -1473,7 +1474,6 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans) - if (ret2) - return ret2; - spin_lock(&fs_info->fs_roots_radix_lock); -- btrfs_qgroup_free_meta_all_pertrans(root); - } - } - spin_unlock(&fs_info->fs_roots_radix_lock); -diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c -index 453d037987fb3..d2285c9726e7b 100644 ---- a/fs/btrfs/volumes.c -+++ b/fs/btrfs/volumes.c -@@ -1224,23 +1224,30 @@ static int open_fs_devices(struct btrfs_fs_devices *fs_devices, - struct btrfs_device *device; - struct btrfs_device *latest_dev = NULL; - struct btrfs_device *tmp_device; -+ int ret = 0; - - list_for_each_entry_safe(device, tmp_device, &fs_devices->devices, - dev_list) { -- int ret; -+ int ret2; - -- ret = btrfs_open_one_device(fs_devices, device, flags, holder); -- if (ret == 0 && -+ ret2 = btrfs_open_one_device(fs_devices, device, flags, holder); -+ if (ret2 == 0 && - (!latest_dev || device->generation > latest_dev->generation)) { - latest_dev = device; -- } else if (ret == -ENODATA) { -+ } else if (ret2 == -ENODATA) { - fs_devices->num_devices--; - list_del(&device->dev_list); - btrfs_free_device(device); - } -+ if (ret == 0 && ret2 != 0) -+ ret = ret2; - } -- if (fs_devices->open_devices == 0) -+ -+ if (fs_devices->open_devices == 0) { -+ if (ret) -+ return ret; - return -EINVAL; -+ } - - fs_devices->opened = 1; - fs_devices->latest_dev = latest_dev; -@@ -3361,6 +3368,7 @@ static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info) - * alignment and size). - */ - ret = -EUCLEAN; -+ mutex_unlock(&fs_info->reclaim_bgs_lock); - goto error; - } - -diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c -index ef7017fb69512..2b578615607e4 100644 ---- a/fs/gfs2/bmap.c -+++ b/fs/gfs2/bmap.c -@@ -1715,7 +1715,8 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) - struct buffer_head *dibh, *bh; - struct gfs2_holder rd_gh; - unsigned int bsize_shift = sdp->sd_sb.sb_bsize_shift; -- u64 lblock = (offset + (1 << bsize_shift) - 1) >> bsize_shift; -+ unsigned int bsize = 1 << bsize_shift; -+ u64 lblock = (offset + bsize - 1) >> bsize_shift; - __u16 start_list[GFS2_MAX_META_HEIGHT]; - __u16 __end_list[GFS2_MAX_META_HEIGHT], *end_list = NULL; - unsigned int start_aligned, end_aligned; -@@ -1726,7 +1727,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) - u64 prev_bnr = 0; - __be64 *start, *end; - -- if (offset >= maxsize) { -+ if (offset + bsize - 1 >= maxsize) { - /* - * The starting point lies beyond the allocated metadata; - * there are no blocks to deallocate. -diff --git a/fs/nfs/client.c b/fs/nfs/client.c -index 44eca51b28085..4d9249c99989f 100644 ---- a/fs/nfs/client.c -+++ b/fs/nfs/client.c -@@ -73,7 +73,6 @@ const struct rpc_program nfs_program = { - .number = NFS_PROGRAM, - .nrvers = ARRAY_SIZE(nfs_version), - .version = nfs_version, -- .stats = &nfs_rpcstat, - .pipe_dir_name = NFS_PIPE_DIRNAME, - }; - -@@ -502,6 +501,7 @@ int nfs_create_rpc_client(struct nfs_client *clp, - const struct nfs_client_initdata *cl_init, - rpc_authflavor_t flavor) - { -+ struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); - struct rpc_clnt *clnt = NULL; - struct rpc_create_args args = { - .net = clp->cl_net, -@@ -513,6 +513,7 @@ int nfs_create_rpc_client(struct nfs_client *clp, - .servername = clp->cl_hostname, - .nodename = cl_init->nodename, - .program = &nfs_program, -+ .stats = &nn->rpcstats, - .version = clp->rpc_ops->version, - .authflavor = flavor, - .cred = cl_init->cred, -@@ -1175,6 +1176,8 @@ void nfs_clients_init(struct net *net) - #endif - spin_lock_init(&nn->nfs_client_lock); - nn->boot_time = ktime_get_real(); -+ memset(&nn->rpcstats, 0, sizeof(nn->rpcstats)); -+ nn->rpcstats.program = &nfs_program; - - nfs_netns_sysfs_setup(nn, net); - } -diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c -index e21c073158e5b..ca76b0b51b779 100644 ---- a/fs/nfs/inode.c -+++ b/fs/nfs/inode.c -@@ -2426,12 +2426,21 @@ EXPORT_SYMBOL_GPL(nfs_net_id); - - static int nfs_net_init(struct net *net) - { -+ struct nfs_net *nn = net_generic(net, nfs_net_id); -+ - nfs_clients_init(net); -+ -+ if (!rpc_proc_register(net, &nn->rpcstats)) { -+ nfs_clients_exit(net); -+ return -ENOMEM; -+ } -+ - return nfs_fs_proc_net_init(net); - } - - static void nfs_net_exit(struct net *net) - { -+ rpc_proc_unregister(net, "nfs"); - nfs_fs_proc_net_exit(net); - nfs_clients_exit(net); - } -@@ -2486,15 +2495,12 @@ static int __init init_nfs_fs(void) - if (err) - goto out1; - -- rpc_proc_register(&init_net, &nfs_rpcstat); -- - err = register_nfs_fs(); - if (err) - goto out0; - - return 0; - out0: -- rpc_proc_unregister(&init_net, "nfs"); - nfs_destroy_directcache(); - out1: - nfs_destroy_writepagecache(); -@@ -2524,7 +2530,6 @@ static void __exit exit_nfs_fs(void) - nfs_destroy_inodecache(); - nfs_destroy_nfspagecache(); - unregister_pernet_subsys(&nfs_net_ops); -- rpc_proc_unregister(&init_net, "nfs"); - unregister_nfs_fs(); - nfs_fs_proc_exit(); - nfsiod_stop(); -diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h -index b1fa81c9dff6f..c91bce41931fb 100644 ---- a/fs/nfs/internal.h -+++ b/fs/nfs/internal.h -@@ -449,8 +449,6 @@ int nfs_try_get_tree(struct fs_context *); - int nfs_get_tree_common(struct fs_context *); - void nfs_kill_super(struct super_block *); - --extern struct rpc_stat nfs_rpcstat; -- - extern int __init register_nfs_fs(void); - extern void __exit unregister_nfs_fs(void); - extern bool nfs_sb_active(struct super_block *sb); -diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h -index c8374f74dce11..a68b21603ea9a 100644 ---- a/fs/nfs/netns.h -+++ b/fs/nfs/netns.h -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - - struct bl_dev_msg { - int32_t status; -@@ -34,6 +35,7 @@ struct nfs_net { - struct nfs_netns_client *nfs_client; - spinlock_t nfs_client_lock; - ktime_t boot_time; -+ struct rpc_stat rpcstats; - #ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc_nfsfs; - #endif -diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h -index 12a48e1d80c3f..b598c7ed497bb 100644 ---- a/fs/smb/client/cifsglob.h -+++ b/fs/smb/client/cifsglob.h -@@ -1049,6 +1049,7 @@ struct cifs_ses { - and after mount option parsing we fill it */ - char *domainName; - char *password; -+ char *password2; /* When key rotation used, new password may be set before it expires */ - char workstation_name[CIFS_MAX_WORKSTATION_LEN]; - struct session_key auth_key; - struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */ -diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c -index c5705de7f9de2..cb3bed8364e07 100644 ---- a/fs/smb/client/connect.c -+++ b/fs/smb/client/connect.c -@@ -2178,6 +2178,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses) - } - - ++delim; -+ /* BB consider adding support for password2 (Key Rotation) for multiuser in future */ - ctx->password = kstrndup(delim, len, GFP_KERNEL); - if (!ctx->password) { - cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n", -@@ -2201,6 +2202,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses) - kfree(ctx->username); - ctx->username = NULL; - kfree_sensitive(ctx->password); -+ /* no need to free ctx->password2 since not allocated in this path */ - ctx->password = NULL; - goto out_key_put; - } -@@ -2312,6 +2314,12 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) - if (!ses->password) - goto get_ses_fail; - } -+ /* ctx->password freed at unmount */ -+ if (ctx->password2) { -+ ses->password2 = kstrdup(ctx->password2, GFP_KERNEL); -+ if (!ses->password2) -+ goto get_ses_fail; -+ } - if (ctx->domainname) { - ses->domainName = kstrdup(ctx->domainname, GFP_KERNEL); - if (!ses->domainName) -diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c -index 103421791bb5d..4d9e57be84dbc 100644 ---- a/fs/smb/client/fs_context.c -+++ b/fs/smb/client/fs_context.c -@@ -161,6 +161,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { - fsparam_string("username", Opt_user), - fsparam_string("pass", Opt_pass), - fsparam_string("password", Opt_pass), -+ fsparam_string("password2", Opt_pass2), - fsparam_string("ip", Opt_ip), - fsparam_string("addr", Opt_ip), - fsparam_string("domain", Opt_domain), -@@ -314,6 +315,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx - new_ctx->nodename = NULL; - new_ctx->username = NULL; - new_ctx->password = NULL; -+ new_ctx->password2 = NULL; - new_ctx->server_hostname = NULL; - new_ctx->domainname = NULL; - new_ctx->UNC = NULL; -@@ -326,6 +328,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx - DUP_CTX_STR(prepath); - DUP_CTX_STR(username); - DUP_CTX_STR(password); -+ DUP_CTX_STR(password2); - DUP_CTX_STR(server_hostname); - DUP_CTX_STR(UNC); - DUP_CTX_STR(source); -@@ -884,6 +887,8 @@ static int smb3_reconfigure(struct fs_context *fc) - else { - kfree_sensitive(ses->password); - ses->password = kstrdup(ctx->password, GFP_KERNEL); -+ kfree_sensitive(ses->password2); -+ ses->password2 = kstrdup(ctx->password2, GFP_KERNEL); - } - STEAL_STRING(cifs_sb, ctx, domainname); - STEAL_STRING(cifs_sb, ctx, nodename); -@@ -1283,6 +1288,18 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, - goto cifs_parse_mount_err; - } - break; -+ case Opt_pass2: -+ kfree_sensitive(ctx->password2); -+ ctx->password2 = NULL; -+ if (strlen(param->string) == 0) -+ break; -+ -+ ctx->password2 = kstrdup(param->string, GFP_KERNEL); -+ if (ctx->password2 == NULL) { -+ cifs_errorf(fc, "OOM when copying password2 string\n"); -+ goto cifs_parse_mount_err; -+ } -+ break; - case Opt_ip: - if (strlen(param->string) == 0) { - ctx->got_ip = false; -@@ -1582,6 +1599,8 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, - cifs_parse_mount_err: - kfree_sensitive(ctx->password); - ctx->password = NULL; -+ kfree_sensitive(ctx->password2); -+ ctx->password2 = NULL; - return -EINVAL; - } - -@@ -1684,6 +1703,8 @@ smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx) - ctx->username = NULL; - kfree_sensitive(ctx->password); - ctx->password = NULL; -+ kfree_sensitive(ctx->password2); -+ ctx->password2 = NULL; - kfree(ctx->server_hostname); - ctx->server_hostname = NULL; - kfree(ctx->UNC); -diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h -index 4e409238fe8f7..d7c090dbe75db 100644 ---- a/fs/smb/client/fs_context.h -+++ b/fs/smb/client/fs_context.h -@@ -137,6 +137,7 @@ enum cifs_param { - Opt_source, - Opt_user, - Opt_pass, -+ Opt_pass2, - Opt_ip, - Opt_domain, - Opt_srcaddr, -@@ -170,6 +171,7 @@ struct smb3_fs_context { - - char *username; - char *password; -+ char *password2; - char *domainname; - char *source; - char *server_hostname; -diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c -index 0d13db80e67c9..d56959d02e36d 100644 ---- a/fs/smb/client/misc.c -+++ b/fs/smb/client/misc.c -@@ -101,6 +101,7 @@ sesInfoFree(struct cifs_ses *buf_to_free) - kfree(buf_to_free->serverDomain); - kfree(buf_to_free->serverNOS); - kfree_sensitive(buf_to_free->password); -+ kfree_sensitive(buf_to_free->password2); - kfree(buf_to_free->user_name); - kfree(buf_to_free->domainName); - kfree_sensitive(buf_to_free->auth_key.response); -diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c -index 94bd4c6d2d682..70530108b9bb9 100644 ---- a/fs/smb/client/smb2pdu.c -+++ b/fs/smb/client/smb2pdu.c -@@ -367,6 +367,17 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, - } - - rc = cifs_setup_session(0, ses, server, nls_codepage); -+ if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) { -+ /* -+ * Try alternate password for next reconnect (key rotation -+ * could be enabled on the server e.g.) if an alternate -+ * password is available and the current password is expired, -+ * but do not swap on non pwd related errors like host down -+ */ -+ if (ses->password2) -+ swap(ses->password2, ses->password); -+ } -+ - if ((rc == -EACCES) && !tcon->retry) { - mutex_unlock(&ses->session_mutex); - rc = -EHOSTDOWN; -diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c -index 53dfaac425c68..dc729ab980dc0 100644 ---- a/fs/smb/server/oplock.c -+++ b/fs/smb/server/oplock.c -@@ -612,13 +612,23 @@ static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level) - - if (opinfo->op_state == OPLOCK_CLOSING) - return -ENOENT; -- else if (!opinfo->is_lease && opinfo->level <= req_op_level) -- return 1; -+ else if (opinfo->level <= req_op_level) { -+ if (opinfo->is_lease && -+ opinfo->o_lease->state != -+ (SMB2_LEASE_HANDLE_CACHING_LE | -+ SMB2_LEASE_READ_CACHING_LE)) -+ return 1; -+ } - } - -- if (!opinfo->is_lease && opinfo->level <= req_op_level) { -- wake_up_oplock_break(opinfo); -- return 1; -+ if (opinfo->level <= req_op_level) { -+ if (opinfo->is_lease && -+ opinfo->o_lease->state != -+ (SMB2_LEASE_HANDLE_CACHING_LE | -+ SMB2_LEASE_READ_CACHING_LE)) { -+ wake_up_oplock_break(opinfo); -+ return 1; -+ } - } - return 0; - } -@@ -886,7 +896,6 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level) - struct lease *lease = brk_opinfo->o_lease; - - atomic_inc(&brk_opinfo->breaking_cnt); -- - err = oplock_break_pending(brk_opinfo, req_op_level); - if (err) - return err < 0 ? err : 0; -@@ -1199,7 +1208,9 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid, - - /* Only v2 leases handle the directory */ - if (S_ISDIR(file_inode(fp->filp)->i_mode)) { -- if (!lctx || lctx->version != 2) -+ if (!lctx || lctx->version != 2 || -+ (lctx->flags != SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE && -+ !lctx->epoch)) - return 0; - } - -@@ -1461,8 +1472,9 @@ void create_lease_buf(u8 *rbuf, struct lease *lease) - buf->lcontext.LeaseFlags = lease->flags; - buf->lcontext.Epoch = cpu_to_le16(lease->epoch); - buf->lcontext.LeaseState = lease->state; -- memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key, -- SMB2_LEASE_KEY_SIZE); -+ if (lease->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE) -+ memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key, -+ SMB2_LEASE_KEY_SIZE); - buf->ccontext.DataOffset = cpu_to_le16(offsetof - (struct create_lease_v2, lcontext)); - buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2)); -@@ -1527,8 +1539,9 @@ struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir) - lreq->flags = lc->lcontext.LeaseFlags; - lreq->epoch = lc->lcontext.Epoch; - lreq->duration = lc->lcontext.LeaseDuration; -- memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey, -- SMB2_LEASE_KEY_SIZE); -+ if (lreq->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE) -+ memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey, -+ SMB2_LEASE_KEY_SIZE); - lreq->version = 2; - } else { - struct create_lease *lc = (struct create_lease *)cc; -diff --git a/fs/smb/server/transport_tcp.c b/fs/smb/server/transport_tcp.c -index 9d4222154dcc0..0012919309f11 100644 ---- a/fs/smb/server/transport_tcp.c -+++ b/fs/smb/server/transport_tcp.c -@@ -446,6 +446,10 @@ static int create_socket(struct interface *iface) - sin6.sin6_family = PF_INET6; - sin6.sin6_addr = in6addr_any; - sin6.sin6_port = htons(server_conf.tcp_port); -+ -+ lock_sock(ksmbd_socket->sk); -+ ksmbd_socket->sk->sk_ipv6only = false; -+ release_sock(ksmbd_socket->sk); - } - - ksmbd_tcp_nodelay(ksmbd_socket); -diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c -index 110e8a2721890..56d1741fe0413 100644 ---- a/fs/tracefs/event_inode.c -+++ b/fs/tracefs/event_inode.c -@@ -164,21 +164,7 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry, - * determined by the parent directory. - */ - if (dentry->d_inode->i_mode & S_IFDIR) { -- /* -- * The events directory dentry is never freed, unless its -- * part of an instance that is deleted. It's attr is the -- * default for its child files and directories. -- * Do not update it. It's not used for its own mode or ownership. -- */ -- if (ei->is_events) { -- /* But it still needs to know if it was modified */ -- if (iattr->ia_valid & ATTR_UID) -- ei->attr.mode |= EVENTFS_SAVE_UID; -- if (iattr->ia_valid & ATTR_GID) -- ei->attr.mode |= EVENTFS_SAVE_GID; -- } else { -- update_attr(&ei->attr, iattr); -- } -+ update_attr(&ei->attr, iattr); - - } else { - name = dentry->d_name.name; -@@ -265,6 +251,35 @@ static const struct file_operations eventfs_file_operations = { - .llseek = generic_file_llseek, - }; - -+/* -+ * On a remount of tracefs, if UID or GID options are set, then -+ * the mount point inode permissions should be used. -+ * Reset the saved permission flags appropriately. -+ */ -+void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid) -+{ -+ struct eventfs_inode *ei = ti->private; -+ -+ if (!ei) -+ return; -+ -+ if (update_uid) -+ ei->attr.mode &= ~EVENTFS_SAVE_UID; -+ -+ if (update_gid) -+ ei->attr.mode &= ~EVENTFS_SAVE_GID; -+ -+ if (!ei->entry_attrs) -+ return; -+ -+ for (int i = 0; i < ei->nr_entries; i++) { -+ if (update_uid) -+ ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_UID; -+ if (update_gid) -+ ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_GID; -+ } -+} -+ - /* Return the evenfs_inode of the "events" directory */ - static struct eventfs_inode *eventfs_find_events(struct dentry *dentry) - { -diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c -index 99caf1c3d0c41..48ed6c900ece8 100644 ---- a/fs/tracefs/inode.c -+++ b/fs/tracefs/inode.c -@@ -30,20 +30,47 @@ static struct vfsmount *tracefs_mount; - static int tracefs_mount_count; - static bool tracefs_registered; - -+/* -+ * Keep track of all tracefs_inodes in order to update their -+ * flags if necessary on a remount. -+ */ -+static DEFINE_SPINLOCK(tracefs_inode_lock); -+static LIST_HEAD(tracefs_inodes); -+ - static struct inode *tracefs_alloc_inode(struct super_block *sb) - { - struct tracefs_inode *ti; -+ unsigned long flags; - - ti = kmem_cache_alloc(tracefs_inode_cachep, GFP_KERNEL); - if (!ti) - return NULL; - -+ spin_lock_irqsave(&tracefs_inode_lock, flags); -+ list_add_rcu(&ti->list, &tracefs_inodes); -+ spin_unlock_irqrestore(&tracefs_inode_lock, flags); -+ - return &ti->vfs_inode; - } - -+static void tracefs_free_inode_rcu(struct rcu_head *rcu) -+{ -+ struct tracefs_inode *ti; -+ -+ ti = container_of(rcu, struct tracefs_inode, rcu); -+ kmem_cache_free(tracefs_inode_cachep, ti); -+} -+ - static void tracefs_free_inode(struct inode *inode) - { -- kmem_cache_free(tracefs_inode_cachep, get_tracefs(inode)); -+ struct tracefs_inode *ti = get_tracefs(inode); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&tracefs_inode_lock, flags); -+ list_del_rcu(&ti->list); -+ spin_unlock_irqrestore(&tracefs_inode_lock, flags); -+ -+ call_rcu(&ti->rcu, tracefs_free_inode_rcu); - } - - static ssize_t default_read_file(struct file *file, char __user *buf, -@@ -153,16 +180,39 @@ static void set_tracefs_inode_owner(struct inode *inode) - { - struct tracefs_inode *ti = get_tracefs(inode); - struct inode *root_inode = ti->private; -+ kuid_t uid; -+ kgid_t gid; -+ -+ uid = root_inode->i_uid; -+ gid = root_inode->i_gid; -+ -+ /* -+ * If the root is not the mount point, then check the root's -+ * permissions. If it was never set, then default to the -+ * mount point. -+ */ -+ if (root_inode != d_inode(root_inode->i_sb->s_root)) { -+ struct tracefs_inode *rti; -+ -+ rti = get_tracefs(root_inode); -+ root_inode = d_inode(root_inode->i_sb->s_root); -+ -+ if (!(rti->flags & TRACEFS_UID_PERM_SET)) -+ uid = root_inode->i_uid; -+ -+ if (!(rti->flags & TRACEFS_GID_PERM_SET)) -+ gid = root_inode->i_gid; -+ } - - /* - * If this inode has never been referenced, then update - * the permissions to the superblock. - */ - if (!(ti->flags & TRACEFS_UID_PERM_SET)) -- inode->i_uid = root_inode->i_uid; -+ inode->i_uid = uid; - - if (!(ti->flags & TRACEFS_GID_PERM_SET)) -- inode->i_gid = root_inode->i_gid; -+ inode->i_gid = gid; - } - - static int tracefs_permission(struct mnt_idmap *idmap, -@@ -313,6 +363,8 @@ static int tracefs_apply_options(struct super_block *sb, bool remount) - struct tracefs_fs_info *fsi = sb->s_fs_info; - struct inode *inode = d_inode(sb->s_root); - struct tracefs_mount_opts *opts = &fsi->mount_opts; -+ struct tracefs_inode *ti; -+ bool update_uid, update_gid; - umode_t tmp_mode; - - /* -@@ -332,6 +384,25 @@ static int tracefs_apply_options(struct super_block *sb, bool remount) - if (!remount || opts->opts & BIT(Opt_gid)) - inode->i_gid = opts->gid; - -+ if (remount && (opts->opts & BIT(Opt_uid) || opts->opts & BIT(Opt_gid))) { -+ -+ update_uid = opts->opts & BIT(Opt_uid); -+ update_gid = opts->opts & BIT(Opt_gid); -+ -+ rcu_read_lock(); -+ list_for_each_entry_rcu(ti, &tracefs_inodes, list) { -+ if (update_uid) -+ ti->flags &= ~TRACEFS_UID_PERM_SET; -+ -+ if (update_gid) -+ ti->flags &= ~TRACEFS_GID_PERM_SET; -+ -+ if (ti->flags & TRACEFS_EVENT_INODE) -+ eventfs_remount(ti, update_uid, update_gid); -+ } -+ rcu_read_unlock(); -+ } -+ - return 0; - } - -@@ -398,7 +469,22 @@ static int tracefs_d_revalidate(struct dentry *dentry, unsigned int flags) - return !(ei && ei->is_freed); - } - -+static void tracefs_d_iput(struct dentry *dentry, struct inode *inode) -+{ -+ struct tracefs_inode *ti = get_tracefs(inode); -+ -+ /* -+ * This inode is being freed and cannot be used for -+ * eventfs. Clear the flag so that it doesn't call into -+ * eventfs during the remount flag updates. The eventfs_inode -+ * gets freed after an RCU cycle, so the content will still -+ * be safe if the iteration is going on now. -+ */ -+ ti->flags &= ~TRACEFS_EVENT_INODE; -+} -+ - static const struct dentry_operations tracefs_dentry_operations = { -+ .d_iput = tracefs_d_iput, - .d_revalidate = tracefs_d_revalidate, - .d_release = tracefs_d_release, - }; -diff --git a/fs/tracefs/internal.h b/fs/tracefs/internal.h -index beb3dcd0e4342..824cbe83679cc 100644 ---- a/fs/tracefs/internal.h -+++ b/fs/tracefs/internal.h -@@ -11,8 +11,12 @@ enum { - }; - - struct tracefs_inode { -- struct inode vfs_inode; -+ union { -+ struct inode vfs_inode; -+ struct rcu_head rcu; -+ }; - /* The below gets initialized with memset_after(ti, 0, vfs_inode) */ -+ struct list_head list; - unsigned long flags; - void *private; - }; -@@ -75,6 +79,7 @@ struct dentry *tracefs_end_creating(struct dentry *dentry); - struct dentry *tracefs_failed_creating(struct dentry *dentry); - struct inode *tracefs_get_inode(struct super_block *sb); - -+void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid); - void eventfs_d_release(struct dentry *dentry); - - #endif /* _TRACEFS_INTERNAL_H */ -diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c -index 56eaae9dac1ab..1f47ff83a9c22 100644 ---- a/fs/userfaultfd.c -+++ b/fs/userfaultfd.c -@@ -921,6 +921,10 @@ static int userfaultfd_release(struct inode *inode, struct file *file) - prev = vma; - continue; - } -+ /* Reset ptes for the whole vma range if wr-protected */ -+ if (userfaultfd_wp(vma)) -+ uffd_wp_range(vma, vma->vm_start, -+ vma->vm_end - vma->vm_start, false); - new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS; - prev = vma_merge(&vmi, mm, prev, vma->vm_start, vma->vm_end, - new_flags, vma->anon_vma, -diff --git a/fs/vboxsf/file.c b/fs/vboxsf/file.c -index 2307f8037efc3..118dedef8ebe8 100644 ---- a/fs/vboxsf/file.c -+++ b/fs/vboxsf/file.c -@@ -218,6 +218,7 @@ const struct file_operations vboxsf_reg_fops = { - .release = vboxsf_file_release, - .fsync = noop_fsync, - .splice_read = filemap_splice_read, -+ .setlease = simple_nosetlease, - }; - - const struct inode_operations vboxsf_reg_iops = { -diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h -index b2f9e2c409cf2..0a182f088c897 100644 ---- a/include/linux/compiler_types.h -+++ b/include/linux/compiler_types.h -@@ -280,6 +280,17 @@ struct ftrace_likely_data { - # define __no_kcsan - #endif - -+#ifdef __SANITIZE_MEMORY__ -+/* -+ * Similarly to KASAN and KCSAN, KMSAN loses function attributes of inlined -+ * functions, therefore disabling KMSAN checks also requires disabling inlining. -+ * -+ * __no_sanitize_or_inline effectively prevents KMSAN from reporting errors -+ * within the function and marks all its outputs as initialized. -+ */ -+# define __no_sanitize_or_inline __no_kmsan_checks notrace __maybe_unused -+#endif -+ - #ifndef __no_sanitize_or_inline - #define __no_sanitize_or_inline __always_inline - #endif -diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h -index fd4a823ce3cdb..b3772edca2e6e 100644 ---- a/include/linux/dma-fence.h -+++ b/include/linux/dma-fence.h -@@ -681,11 +681,4 @@ static inline bool dma_fence_is_container(struct dma_fence *fence) - return dma_fence_is_array(fence) || dma_fence_is_chain(fence); - } - --#define DMA_FENCE_WARN(f, fmt, args...) \ -- do { \ -- struct dma_fence *__ff = (f); \ -- pr_warn("f %llu#%llu: " fmt, __ff->context, __ff->seqno,\ -- ##args); \ -- } while (0) -- - #endif /* __LINUX_DMA_FENCE_H */ -diff --git a/include/linux/gfp_types.h b/include/linux/gfp_types.h -index 6583a58670c57..dfde1e1e321c3 100644 ---- a/include/linux/gfp_types.h -+++ b/include/linux/gfp_types.h -@@ -2,6 +2,8 @@ - #ifndef __LINUX_GFP_TYPES_H - #define __LINUX_GFP_TYPES_H - -+#include -+ - /* The typedef is in types.h but we want the documentation here */ - #if 0 - /** -diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h -index 6ef0557b4bff8..96ceb4095425e 100644 ---- a/include/linux/hyperv.h -+++ b/include/linux/hyperv.h -@@ -832,6 +832,7 @@ struct vmbus_gpadl { - u32 gpadl_handle; - u32 size; - void *buffer; -+ bool decrypted; - }; - - struct vmbus_channel { -diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h -index dae26295e6bed..1b81adebdb8be 100644 ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -82,6 +82,7 @@ struct nvmem_cell_info { - * @owner: Pointer to exporter module. Used for refcounting. - * @cells: Optional array of pre-defined NVMEM cells. - * @ncells: Number of elements in cells. -+ * @add_legacy_fixed_of_cells: Read fixed NVMEM cells from old OF syntax. - * @keepout: Optional array of keepout ranges (sorted ascending by start). - * @nkeepout: Number of elements in the keepout array. - * @type: Type of the nvmem storage -@@ -112,6 +113,7 @@ struct nvmem_config { - struct module *owner; - const struct nvmem_cell_info *cells; - int ncells; -+ bool add_legacy_fixed_of_cells; - const struct nvmem_keepout *keepout; - unsigned int nkeepout; - enum nvmem_type type; -diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h -index a6c66ea80194c..0a85ff5c8db3c 100644 ---- a/include/linux/pci_ids.h -+++ b/include/linux/pci_ids.h -@@ -2683,8 +2683,10 @@ - #define PCI_DEVICE_ID_INTEL_I960 0x0960 - #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 - #define PCI_DEVICE_ID_INTEL_HDA_HSW_0 0x0a0c -+#define PCI_DEVICE_ID_INTEL_DSA_SPR0 0x0b25 - #define PCI_DEVICE_ID_INTEL_HDA_HSW_2 0x0c0c - #define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60 -+#define PCI_DEVICE_ID_INTEL_IAX_SPR0 0x0cfe - #define PCI_DEVICE_ID_INTEL_HDA_HSW_3 0x0d0c - #define PCI_DEVICE_ID_INTEL_HDA_BYT 0x0f04 - #define PCI_DEVICE_ID_INTEL_SST_BYT 0x0f28 -diff --git a/include/linux/regmap.h b/include/linux/regmap.h -index c9182a47736ef..113261287af28 100644 ---- a/include/linux/regmap.h -+++ b/include/linux/regmap.h -@@ -1225,6 +1225,7 @@ int regmap_multi_reg_write_bypassed(struct regmap *map, - int regmap_raw_write_async(struct regmap *map, unsigned int reg, - const void *val, size_t val_len); - int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); -+int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val); - int regmap_raw_read(struct regmap *map, unsigned int reg, - void *val, size_t val_len); - int regmap_noinc_read(struct regmap *map, unsigned int reg, -@@ -1734,6 +1735,13 @@ static inline int regmap_read(struct regmap *map, unsigned int reg, - return -EINVAL; - } - -+static inline int regmap_read_bypassed(struct regmap *map, unsigned int reg, -+ unsigned int *val) -+{ -+ WARN_ONCE(1, "regmap API is disabled"); -+ return -EINVAL; -+} -+ - static inline int regmap_raw_read(struct regmap *map, unsigned int reg, - void *val, size_t val_len) - { -diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h -index 39b666b40ea61..2c526c8d10cc4 100644 ---- a/include/linux/regulator/consumer.h -+++ b/include/linux/regulator/consumer.h -@@ -365,13 +365,13 @@ devm_regulator_get_exclusive(struct device *dev, const char *id) - - static inline int devm_regulator_get_enable(struct device *dev, const char *id) - { -- return -ENODEV; -+ return 0; - } - - static inline int devm_regulator_get_enable_optional(struct device *dev, - const char *id) - { -- return -ENODEV; -+ return 0; - } - - static inline struct regulator *__must_check -diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h -index 7d54808a1e8f9..5f11f98733419 100644 ---- a/include/linux/skbuff.h -+++ b/include/linux/skbuff.h -@@ -2962,6 +2962,21 @@ static inline void skb_mac_header_rebuild(struct sk_buff *skb) - } - } - -+/* Move the full mac header up to current network_header. -+ * Leaves skb->data pointing at offset skb->mac_len into the mac_header. -+ * Must be provided the complete mac header length. -+ */ -+static inline void skb_mac_header_rebuild_full(struct sk_buff *skb, u32 full_mac_len) -+{ -+ if (skb_mac_header_was_set(skb)) { -+ const unsigned char *old_mac = skb_mac_header(skb); -+ -+ skb_set_mac_header(skb, -full_mac_len); -+ memmove(skb_mac_header(skb), old_mac, full_mac_len); -+ __skb_push(skb, full_mac_len - skb->mac_len); -+ } -+} -+ - static inline int skb_checksum_start_offset(const struct sk_buff *skb) - { - return skb->csum_start - skb_headroom(skb); -diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h -index bd4418377bacf..062fe440f5d09 100644 ---- a/include/linux/skmsg.h -+++ b/include/linux/skmsg.h -@@ -456,10 +456,12 @@ static inline void sk_psock_put(struct sock *sk, struct sk_psock *psock) - - static inline void sk_psock_data_ready(struct sock *sk, struct sk_psock *psock) - { -+ read_lock_bh(&sk->sk_callback_lock); - if (psock->saved_data_ready) - psock->saved_data_ready(sk); - else - sk->sk_data_ready(sk); -+ read_unlock_bh(&sk->sk_callback_lock); - } - - static inline void psock_set_prog(struct bpf_prog **pprog, -diff --git a/include/linux/slab.h b/include/linux/slab.h -index 8228d1276a2f6..5a67dab27f831 100644 ---- a/include/linux/slab.h -+++ b/include/linux/slab.h -@@ -228,7 +228,7 @@ void kfree(const void *objp); - void kfree_sensitive(const void *objp); - size_t __ksize(const void *objp); - --DEFINE_FREE(kfree, void *, if (_T) kfree(_T)) -+DEFINE_FREE(kfree, void *, if (!IS_ERR_OR_NULL(_T)) kfree(_T)) - - /** - * ksize - Report actual allocation size of associated object -diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h -index e9d4377d03c6e..17d84b3ee8a01 100644 ---- a/include/linux/sunrpc/clnt.h -+++ b/include/linux/sunrpc/clnt.h -@@ -139,6 +139,7 @@ struct rpc_create_args { - const char *servername; - const char *nodename; - const struct rpc_program *program; -+ struct rpc_stat *stats; - u32 prognumber; /* overrides program->number */ - u32 version; - rpc_authflavor_t authflavor; -diff --git a/include/net/gro.h b/include/net/gro.h -index 88644b3ca6600..018343254c90a 100644 ---- a/include/net/gro.h -+++ b/include/net/gro.h -@@ -86,6 +86,15 @@ struct napi_gro_cb { - - /* used to support CHECKSUM_COMPLETE for tunneling protocols */ - __wsum csum; -+ -+ /* L3 offsets */ -+ union { -+ struct { -+ u16 network_offset; -+ u16 inner_network_offset; -+ }; -+ u16 network_offsets[2]; -+ }; - }; - - #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb) -diff --git a/include/net/xfrm.h b/include/net/xfrm.h -index 363c7d5105542..a3fd2cfed5e33 100644 ---- a/include/net/xfrm.h -+++ b/include/net/xfrm.h -@@ -1047,6 +1047,9 @@ struct xfrm_offload { - #define CRYPTO_INVALID_PACKET_SYNTAX 64 - #define CRYPTO_INVALID_PROTOCOL 128 - -+ /* Used to keep whole l2 header for transport mode GRO */ -+ __u32 orig_mac_len; -+ - __u8 proto; - __u8 inner_ipproto; - }; -diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h -index 1af9e68193920..9cc10fab01a8c 100644 ---- a/include/sound/emu10k1.h -+++ b/include/sound/emu10k1.h -@@ -1684,8 +1684,7 @@ struct snd_emu1010 { - unsigned int clock_fallback; - unsigned int optical_in; /* 0:SPDIF, 1:ADAT */ - unsigned int optical_out; /* 0:SPDIF, 1:ADAT */ -- struct work_struct firmware_work; -- struct work_struct clock_work; -+ struct work_struct work; - }; - - struct snd_emu10k1 { -diff --git a/include/sound/sof.h b/include/sound/sof.h -index 51294f2ba302c..31121c6df0272 100644 ---- a/include/sound/sof.h -+++ b/include/sound/sof.h -@@ -52,11 +52,14 @@ enum sof_dsp_power_states { - - /* Definitions for multiple IPCs */ - enum sof_ipc_type { -- SOF_IPC, -- SOF_INTEL_IPC4, -+ SOF_IPC_TYPE_3, -+ SOF_IPC_TYPE_4, - SOF_IPC_TYPE_COUNT - }; - -+#define SOF_IPC SOF_IPC_TYPE_3 -+#define SOF_INTEL_IPC4 SOF_IPC_TYPE_4 -+ - /* - * SOF Platform data. - */ -diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h -index 0dd4a21d172da..3322fb93a260b 100644 ---- a/include/trace/events/rxrpc.h -+++ b/include/trace/events/rxrpc.h -@@ -83,7 +83,7 @@ - EM(rxrpc_badmsg_bad_abort, "bad-abort") \ - EM(rxrpc_badmsg_bad_jumbo, "bad-jumbo") \ - EM(rxrpc_badmsg_short_ack, "short-ack") \ -- EM(rxrpc_badmsg_short_ack_info, "short-ack-info") \ -+ EM(rxrpc_badmsg_short_ack_trailer, "short-ack-trailer") \ - EM(rxrpc_badmsg_short_hdr, "short-hdr") \ - EM(rxrpc_badmsg_unsupported_packet, "unsup-pkt") \ - EM(rxrpc_badmsg_zero_call, "zero-call") \ -diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h -index eeb2fdcbdcb70..cd924c959d732 100644 ---- a/include/uapi/linux/kfd_ioctl.h -+++ b/include/uapi/linux/kfd_ioctl.h -@@ -909,14 +909,25 @@ enum kfd_dbg_trap_exception_code { - KFD_EC_MASK(EC_DEVICE_NEW)) - #define KFD_EC_MASK_PROCESS (KFD_EC_MASK(EC_PROCESS_RUNTIME) | \ - KFD_EC_MASK(EC_PROCESS_DEVICE_REMOVE)) -+#define KFD_EC_MASK_PACKET (KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_DIM_INVALID) | \ -+ KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_GROUP_SEGMENT_SIZE_INVALID) | \ -+ KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_CODE_INVALID) | \ -+ KFD_EC_MASK(EC_QUEUE_PACKET_RESERVED) | \ -+ KFD_EC_MASK(EC_QUEUE_PACKET_UNSUPPORTED) | \ -+ KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_WORK_GROUP_SIZE_INVALID) | \ -+ KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_REGISTER_INVALID) | \ -+ KFD_EC_MASK(EC_QUEUE_PACKET_VENDOR_UNSUPPORTED)) - - /* Checks for exception code types for KFD search */ -+#define KFD_DBG_EC_IS_VALID(ecode) (ecode > EC_NONE && ecode < EC_MAX) - #define KFD_DBG_EC_TYPE_IS_QUEUE(ecode) \ -- (!!(KFD_EC_MASK(ecode) & KFD_EC_MASK_QUEUE)) -+ (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_QUEUE)) - #define KFD_DBG_EC_TYPE_IS_DEVICE(ecode) \ -- (!!(KFD_EC_MASK(ecode) & KFD_EC_MASK_DEVICE)) -+ (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_DEVICE)) - #define KFD_DBG_EC_TYPE_IS_PROCESS(ecode) \ -- (!!(KFD_EC_MASK(ecode) & KFD_EC_MASK_PROCESS)) -+ (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_PROCESS)) -+#define KFD_DBG_EC_TYPE_IS_PACKET(ecode) \ -+ (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_PACKET)) - - - /* Runtime enable states */ -diff --git a/include/uapi/scsi/scsi_bsg_mpi3mr.h b/include/uapi/scsi/scsi_bsg_mpi3mr.h -index 907d345f04f93..353183e863e47 100644 ---- a/include/uapi/scsi/scsi_bsg_mpi3mr.h -+++ b/include/uapi/scsi/scsi_bsg_mpi3mr.h -@@ -382,7 +382,7 @@ struct mpi3mr_bsg_in_reply_buf { - __u8 mpi_reply_type; - __u8 rsvd1; - __u16 rsvd2; -- __u8 reply_buf[1]; -+ __u8 reply_buf[]; - }; - - /** -diff --git a/kernel/bpf/bloom_filter.c b/kernel/bpf/bloom_filter.c -index addf3dd57b59b..35e1ddca74d21 100644 ---- a/kernel/bpf/bloom_filter.c -+++ b/kernel/bpf/bloom_filter.c -@@ -80,6 +80,18 @@ static int bloom_map_get_next_key(struct bpf_map *map, void *key, void *next_key - return -EOPNOTSUPP; - } - -+/* Called from syscall */ -+static int bloom_map_alloc_check(union bpf_attr *attr) -+{ -+ if (attr->value_size > KMALLOC_MAX_SIZE) -+ /* if value_size is bigger, the user space won't be able to -+ * access the elements. -+ */ -+ return -E2BIG; -+ -+ return 0; -+} -+ - static struct bpf_map *bloom_map_alloc(union bpf_attr *attr) - { - u32 bitset_bytes, bitset_mask, nr_hash_funcs, nr_bits; -@@ -191,6 +203,7 @@ static u64 bloom_map_mem_usage(const struct bpf_map *map) - BTF_ID_LIST_SINGLE(bpf_bloom_map_btf_ids, struct, bpf_bloom_filter) - const struct bpf_map_ops bloom_filter_map_ops = { - .map_meta_equal = bpf_map_meta_equal, -+ .map_alloc_check = bloom_map_alloc_check, - .map_alloc = bloom_map_alloc, - .map_free = bloom_map_free, - .map_get_next_key = bloom_map_get_next_key, -diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c -index c9fc734989c68..818bac019d0d3 100644 ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -17655,8 +17655,7 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env) - f = fdget(fd); - map = __bpf_map_get(f); - if (IS_ERR(map)) { -- verbose(env, "fd %d is not pointing to valid bpf_map\n", -- insn[0].imm); -+ verbose(env, "fd %d is not pointing to valid bpf_map\n", fd); - return PTR_ERR(map); - } - -diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c -index 675ae318f74f8..a7d5fb473b324 100644 ---- a/kernel/dma/swiotlb.c -+++ b/kernel/dma/swiotlb.c -@@ -1692,6 +1692,7 @@ static int rmem_swiotlb_device_init(struct reserved_mem *rmem, - mem->for_alloc = true; - #ifdef CONFIG_SWIOTLB_DYNAMIC - spin_lock_init(&mem->lock); -+ INIT_LIST_HEAD_RCU(&mem->pools); - #endif - add_mem_pool(mem, pool); - -diff --git a/kernel/workqueue.c b/kernel/workqueue.c -index fd7b84b06d926..8c7bafbee1b13 100644 ---- a/kernel/workqueue.c -+++ b/kernel/workqueue.c -@@ -1135,8 +1135,12 @@ static bool kick_pool(struct worker_pool *pool) - !cpumask_test_cpu(p->wake_cpu, pool->attrs->__pod_cpumask)) { - struct work_struct *work = list_first_entry(&pool->worklist, - struct work_struct, entry); -- p->wake_cpu = cpumask_any_distribute(pool->attrs->__pod_cpumask); -- get_work_pwq(work)->stats[PWQ_STAT_REPATRIATED]++; -+ int wake_cpu = cpumask_any_and_distribute(pool->attrs->__pod_cpumask, -+ cpu_online_mask); -+ if (wake_cpu < nr_cpu_ids) { -+ p->wake_cpu = wake_cpu; -+ get_work_pwq(work)->stats[PWQ_STAT_REPATRIATED]++; -+ } - } - #endif - wake_up_process(p); -diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug -index d2f73bb4121b0..da5513cfc1258 100644 ---- a/lib/Kconfig.debug -+++ b/lib/Kconfig.debug -@@ -373,7 +373,7 @@ config DEBUG_INFO_SPLIT - Incompatible with older versions of ccache. - - config DEBUG_INFO_BTF -- bool "Generate BTF typeinfo" -+ bool "Generate BTF type information" - depends on !DEBUG_INFO_SPLIT && !DEBUG_INFO_REDUCED - depends on !GCC_PLUGIN_RANDSTRUCT || COMPILE_TEST - depends on BPF_SYSCALL -@@ -404,7 +404,8 @@ config PAHOLE_HAS_LANG_EXCLUDE - using DEBUG_INFO_BTF_MODULES. - - config DEBUG_INFO_BTF_MODULES -- def_bool y -+ bool "Generate BTF type information for kernel modules" -+ default y - depends on DEBUG_INFO_BTF && MODULES && PAHOLE_HAS_SPLIT_BTF - help - Generate compact split BTF type information for kernel modules. -diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c -index 6fba6423cc10b..a5a687e1c9192 100644 ---- a/lib/dynamic_debug.c -+++ b/lib/dynamic_debug.c -@@ -302,7 +302,11 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords) - } else { - for (end = buf; *end && !isspace(*end); end++) - ; -- BUG_ON(end == buf); -+ if (end == buf) { -+ pr_err("parse err after word:%d=%s\n", nwords, -+ nwords ? words[nwords - 1] : ""); -+ return -EINVAL; -+ } - } - - /* `buf' is start of word, `end' is one past its end */ -diff --git a/lib/maple_tree.c b/lib/maple_tree.c -index 684689457d77f..41ef91590761b 100644 ---- a/lib/maple_tree.c -+++ b/lib/maple_tree.c -@@ -5085,18 +5085,18 @@ int mas_empty_area_rev(struct ma_state *mas, unsigned long min, - if (size == 0 || max - min < size - 1) - return -EINVAL; - -- if (mas_is_start(mas)) { -+ if (mas_is_start(mas)) - mas_start(mas); -- mas->offset = mas_data_end(mas); -- } else if (mas->offset >= 2) { -- mas->offset -= 2; -- } else if (!mas_rewind_node(mas)) { -+ else if ((mas->offset < 2) && (!mas_rewind_node(mas))) - return -EBUSY; -- } - -- /* Empty set. */ -- if (mas_is_none(mas) || mas_is_ptr(mas)) -+ if (unlikely(mas_is_none(mas) || mas_is_ptr(mas))) - return mas_sparse_area(mas, min, max, size, false); -+ else if (mas->offset >= 2) -+ mas->offset -= 2; -+ else -+ mas->offset = mas_data_end(mas); -+ - - /* The start of the window can only be within these values. */ - mas->index = min; -diff --git a/lib/scatterlist.c b/lib/scatterlist.c -index 68b45c82c37a6..7bc2220fea805 100644 ---- a/lib/scatterlist.c -+++ b/lib/scatterlist.c -@@ -1124,7 +1124,7 @@ static ssize_t extract_user_to_sg(struct iov_iter *iter, - do { - res = iov_iter_extract_pages(iter, &pages, maxsize, sg_max, - extraction_flags, &off); -- if (res < 0) -+ if (res <= 0) - goto failed; - - len = res; -diff --git a/mm/hugetlb.c b/mm/hugetlb.c -index 555cf1a80eaed..c2047608800fb 100644 ---- a/mm/hugetlb.c -+++ b/mm/hugetlb.c -@@ -1747,8 +1747,6 @@ static void add_hugetlb_folio(struct hstate *h, struct folio *folio, - static void __update_and_free_hugetlb_folio(struct hstate *h, - struct folio *folio) - { -- bool clear_dtor = folio_test_hugetlb_vmemmap_optimized(folio); -- - if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported()) - return; - -@@ -1782,7 +1780,7 @@ static void __update_and_free_hugetlb_folio(struct hstate *h, - * If vmemmap pages were allocated above, then we need to clear the - * hugetlb destructor under the hugetlb lock. - */ -- if (clear_dtor) { -+ if (folio_test_hugetlb(folio)) { - spin_lock_irq(&hugetlb_lock); - __clear_hugetlb_destructor(h, folio); - spin_unlock_irq(&hugetlb_lock); -diff --git a/mm/readahead.c b/mm/readahead.c -index 1d1a84deb5bc5..7c0449f8bec7f 100644 ---- a/mm/readahead.c -+++ b/mm/readahead.c -@@ -490,6 +490,7 @@ void page_cache_ra_order(struct readahead_control *ractl, - pgoff_t index = readahead_index(ractl); - pgoff_t limit = (i_size_read(mapping->host) - 1) >> PAGE_SHIFT; - pgoff_t mark = index + ra->size - ra->async_size; -+ unsigned int nofs; - int err = 0; - gfp_t gfp = readahead_gfp_mask(mapping); - -@@ -506,6 +507,8 @@ void page_cache_ra_order(struct readahead_control *ractl, - new_order--; - } - -+ /* See comment in page_cache_ra_unbounded() */ -+ nofs = memalloc_nofs_save(); - filemap_invalidate_lock_shared(mapping); - while (index <= limit) { - unsigned int order = new_order; -@@ -534,6 +537,7 @@ void page_cache_ra_order(struct readahead_control *ractl, - - read_pages(ractl); - filemap_invalidate_unlock_shared(mapping); -+ memalloc_nofs_restore(nofs); - - /* - * If there were already pages in the page cache, then we may have -diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c -index f001582345052..9404dd551dfd2 100644 ---- a/net/8021q/vlan_core.c -+++ b/net/8021q/vlan_core.c -@@ -478,6 +478,8 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head, - if (unlikely(!vhdr)) - goto out; - -+ NAPI_GRO_CB(skb)->network_offsets[NAPI_GRO_CB(skb)->encap_mark] = hlen; -+ - type = vhdr->h_vlan_encapsulated_proto; - - ptype = gro_find_receive_by_type(type); -diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c -index 0592369579ab2..befe645d3f9bf 100644 ---- a/net/bluetooth/hci_core.c -+++ b/net/bluetooth/hci_core.c -@@ -2736,8 +2736,6 @@ void hci_unregister_dev(struct hci_dev *hdev) - - hci_unregister_suspend_notifier(hdev); - -- msft_unregister(hdev); -- - hci_dev_do_close(hdev); - - if (!test_bit(HCI_INIT, &hdev->flags) && -@@ -2791,6 +2789,7 @@ void hci_release_dev(struct hci_dev *hdev) - hci_discovery_filter_clear(hdev); - hci_blocked_keys_clear(hdev); - hci_codec_list_clear(&hdev->local_codecs); -+ msft_release(hdev); - hci_dev_unlock(hdev); - - ida_destroy(&hdev->unset_handle_ida); -diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c -index 1b4abf8e90f6b..9274d32550493 100644 ---- a/net/bluetooth/hci_event.c -+++ b/net/bluetooth/hci_event.c -@@ -7200,6 +7200,8 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data, - u16 handle = le16_to_cpu(ev->bis[i]); - - bis = hci_conn_hash_lookup_handle(hdev, handle); -+ if (!bis) -+ continue; - - set_bit(HCI_CONN_BIG_SYNC_FAILED, &bis->flags); - hci_connect_cfm(bis, ev->status); -diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c -index 706d2478ddb33..1e961cfaa07b3 100644 ---- a/net/bluetooth/l2cap_core.c -+++ b/net/bluetooth/l2cap_core.c -@@ -415,6 +415,9 @@ static void l2cap_chan_timeout(struct work_struct *work) - - BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); - -+ if (!conn) -+ return; -+ - mutex_lock(&conn->chan_lock); - /* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling - * this work. No need to call l2cap_chan_hold(chan) here again. -diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c -index 9612c5d1b13f6..d039683d3bdd4 100644 ---- a/net/bluetooth/msft.c -+++ b/net/bluetooth/msft.c -@@ -769,7 +769,7 @@ void msft_register(struct hci_dev *hdev) - mutex_init(&msft->filter_lock); - } - --void msft_unregister(struct hci_dev *hdev) -+void msft_release(struct hci_dev *hdev) - { - struct msft_data *msft = hdev->msft_data; - -diff --git a/net/bluetooth/msft.h b/net/bluetooth/msft.h -index 2a63205b377b7..fe538e9c91c01 100644 ---- a/net/bluetooth/msft.h -+++ b/net/bluetooth/msft.h -@@ -14,7 +14,7 @@ - - bool msft_monitor_supported(struct hci_dev *hdev); - void msft_register(struct hci_dev *hdev); --void msft_unregister(struct hci_dev *hdev); -+void msft_release(struct hci_dev *hdev); - void msft_do_open(struct hci_dev *hdev); - void msft_do_close(struct hci_dev *hdev); - void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb); -@@ -35,7 +35,7 @@ static inline bool msft_monitor_supported(struct hci_dev *hdev) - } - - static inline void msft_register(struct hci_dev *hdev) {} --static inline void msft_unregister(struct hci_dev *hdev) {} -+static inline void msft_release(struct hci_dev *hdev) {} - static inline void msft_do_open(struct hci_dev *hdev) {} - static inline void msft_do_close(struct hci_dev *hdev) {} - static inline void msft_vendor_evt(struct hci_dev *hdev, void *data, -diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c -index 3cc9fab8e8384..ede7391f3aa98 100644 ---- a/net/bluetooth/sco.c -+++ b/net/bluetooth/sco.c -@@ -83,6 +83,10 @@ static void sco_sock_timeout(struct work_struct *work) - struct sock *sk; - - sco_conn_lock(conn); -+ if (!conn->hcon) { -+ sco_conn_unlock(conn); -+ return; -+ } - sk = conn->sk; - if (sk) - sock_hold(sk); -diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c -index 7431f89e897b9..d97064d460dc7 100644 ---- a/net/bridge/br_forward.c -+++ b/net/bridge/br_forward.c -@@ -258,6 +258,7 @@ static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb, - { - struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; - const unsigned char *src = eth_hdr(skb)->h_source; -+ struct sk_buff *nskb; - - if (!should_deliver(p, skb)) - return; -@@ -266,12 +267,16 @@ static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb, - if (skb->dev == p->dev && ether_addr_equal(src, addr)) - return; - -- skb = skb_copy(skb, GFP_ATOMIC); -- if (!skb) { -+ __skb_push(skb, ETH_HLEN); -+ nskb = pskb_copy(skb, GFP_ATOMIC); -+ __skb_pull(skb, ETH_HLEN); -+ if (!nskb) { - DEV_STATS_INC(dev, tx_dropped); - return; - } - -+ skb = nskb; -+ __skb_pull(skb, ETH_HLEN); - if (!is_broadcast_ether_addr(addr)) - memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN); - -diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c -index 65e9ed3851425..4488faf059a36 100644 ---- a/net/bridge/br_netlink.c -+++ b/net/bridge/br_netlink.c -@@ -455,7 +455,8 @@ static int br_fill_ifinfo(struct sk_buff *skb, - u32 filter_mask, const struct net_device *dev, - bool getlink) - { -- u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; -+ u8 operstate = netif_running(dev) ? READ_ONCE(dev->operstate) : -+ IF_OPER_DOWN; - struct nlattr *af = NULL; - struct net_bridge *br; - struct ifinfomsg *hdr; -diff --git a/net/core/filter.c b/net/core/filter.c -index 24f23a30c945e..df4578219e82c 100644 ---- a/net/core/filter.c -+++ b/net/core/filter.c -@@ -4334,10 +4334,12 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri, - enum bpf_map_type map_type = ri->map_type; - void *fwd = ri->tgt_value; - u32 map_id = ri->map_id; -+ u32 flags = ri->flags; - struct bpf_map *map; - int err; - - ri->map_id = 0; /* Valid map id idr range: [1,INT_MAX[ */ -+ ri->flags = 0; - ri->map_type = BPF_MAP_TYPE_UNSPEC; - - if (unlikely(!xdpf)) { -@@ -4349,11 +4351,20 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri, - case BPF_MAP_TYPE_DEVMAP: - fallthrough; - case BPF_MAP_TYPE_DEVMAP_HASH: -- map = READ_ONCE(ri->map); -- if (unlikely(map)) { -+ if (unlikely(flags & BPF_F_BROADCAST)) { -+ map = READ_ONCE(ri->map); -+ -+ /* The map pointer is cleared when the map is being torn -+ * down by bpf_clear_redirect_map() -+ */ -+ if (unlikely(!map)) { -+ err = -ENOENT; -+ break; -+ } -+ - WRITE_ONCE(ri->map, NULL); - err = dev_map_enqueue_multi(xdpf, dev, map, -- ri->flags & BPF_F_EXCLUDE_INGRESS); -+ flags & BPF_F_EXCLUDE_INGRESS); - } else { - err = dev_map_enqueue(fwd, xdpf, dev); - } -@@ -4416,9 +4427,9 @@ EXPORT_SYMBOL_GPL(xdp_do_redirect_frame); - static int xdp_do_generic_redirect_map(struct net_device *dev, - struct sk_buff *skb, - struct xdp_buff *xdp, -- struct bpf_prog *xdp_prog, -- void *fwd, -- enum bpf_map_type map_type, u32 map_id) -+ struct bpf_prog *xdp_prog, void *fwd, -+ enum bpf_map_type map_type, u32 map_id, -+ u32 flags) - { - struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); - struct bpf_map *map; -@@ -4428,11 +4439,20 @@ static int xdp_do_generic_redirect_map(struct net_device *dev, - case BPF_MAP_TYPE_DEVMAP: - fallthrough; - case BPF_MAP_TYPE_DEVMAP_HASH: -- map = READ_ONCE(ri->map); -- if (unlikely(map)) { -+ if (unlikely(flags & BPF_F_BROADCAST)) { -+ map = READ_ONCE(ri->map); -+ -+ /* The map pointer is cleared when the map is being torn -+ * down by bpf_clear_redirect_map() -+ */ -+ if (unlikely(!map)) { -+ err = -ENOENT; -+ break; -+ } -+ - WRITE_ONCE(ri->map, NULL); - err = dev_map_redirect_multi(dev, skb, xdp_prog, map, -- ri->flags & BPF_F_EXCLUDE_INGRESS); -+ flags & BPF_F_EXCLUDE_INGRESS); - } else { - err = dev_map_generic_redirect(fwd, skb, xdp_prog); - } -@@ -4469,9 +4489,11 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb, - enum bpf_map_type map_type = ri->map_type; - void *fwd = ri->tgt_value; - u32 map_id = ri->map_id; -+ u32 flags = ri->flags; - int err; - - ri->map_id = 0; /* Valid map id idr range: [1,INT_MAX[ */ -+ ri->flags = 0; - ri->map_type = BPF_MAP_TYPE_UNSPEC; - - if (map_type == BPF_MAP_TYPE_UNSPEC && map_id == INT_MAX) { -@@ -4491,7 +4513,7 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb, - return 0; - } - -- return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog, fwd, map_type, map_id); -+ return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog, fwd, map_type, map_id, flags); - err: - _trace_xdp_redirect_err(dev, xdp_prog, ri->tgt_index, err); - return err; -diff --git a/net/core/gro.c b/net/core/gro.c -index cefddf65f7db0..31e40f25fdf10 100644 ---- a/net/core/gro.c -+++ b/net/core/gro.c -@@ -373,6 +373,7 @@ static inline void skb_gro_reset_offset(struct sk_buff *skb, u32 nhoff) - const struct skb_shared_info *pinfo = skb_shinfo(skb); - const skb_frag_t *frag0 = &pinfo->frags[0]; - -+ NAPI_GRO_CB(skb)->network_offset = 0; - NAPI_GRO_CB(skb)->data_offset = 0; - NAPI_GRO_CB(skb)->frag0 = NULL; - NAPI_GRO_CB(skb)->frag0_len = 0; -diff --git a/net/core/link_watch.c b/net/core/link_watch.c -index c469d1c4db5d7..cb43f5aebfbcc 100644 ---- a/net/core/link_watch.c -+++ b/net/core/link_watch.c -@@ -67,7 +67,7 @@ static void rfc2863_policy(struct net_device *dev) - { - unsigned char operstate = default_operstate(dev); - -- if (operstate == dev->operstate) -+ if (operstate == READ_ONCE(dev->operstate)) - return; - - write_lock(&dev_base_lock); -@@ -87,7 +87,7 @@ static void rfc2863_policy(struct net_device *dev) - break; - } - -- dev->operstate = operstate; -+ WRITE_ONCE(dev->operstate, operstate); - - write_unlock(&dev_base_lock); - } -diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c -index fccaa5bac0ed0..5a9487af44e00 100644 ---- a/net/core/net-sysfs.c -+++ b/net/core/net-sysfs.c -@@ -307,11 +307,9 @@ static ssize_t operstate_show(struct device *dev, - const struct net_device *netdev = to_net_dev(dev); - unsigned char operstate; - -- read_lock(&dev_base_lock); -- operstate = netdev->operstate; -+ operstate = READ_ONCE(netdev->operstate); - if (!netif_running(netdev)) - operstate = IF_OPER_DOWN; -- read_unlock(&dev_base_lock); - - if (operstate >= ARRAY_SIZE(operstates)) - return -EINVAL; /* should not happen */ -diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c -index f4183c4c1ec82..ebea4fa69976a 100644 ---- a/net/core/net_namespace.c -+++ b/net/core/net_namespace.c -@@ -69,12 +69,15 @@ DEFINE_COOKIE(net_cookie); - - static struct net_generic *net_alloc_generic(void) - { -+ unsigned int gen_ptrs = READ_ONCE(max_gen_ptrs); -+ unsigned int generic_size; - struct net_generic *ng; -- unsigned int generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]); -+ -+ generic_size = offsetof(struct net_generic, ptr[gen_ptrs]); - - ng = kzalloc(generic_size, GFP_KERNEL); - if (ng) -- ng->s.len = max_gen_ptrs; -+ ng->s.len = gen_ptrs; - - return ng; - } -@@ -1229,7 +1232,11 @@ static int register_pernet_operations(struct list_head *list, - if (error < 0) - return error; - *ops->id = error; -- max_gen_ptrs = max(max_gen_ptrs, *ops->id + 1); -+ /* This does not require READ_ONCE as writers already hold -+ * pernet_ops_rwsem. But WRITE_ONCE is needed to protect -+ * net_alloc_generic. -+ */ -+ WRITE_ONCE(max_gen_ptrs, max(max_gen_ptrs, *ops->id + 1)); - } - error = __register_pernet_operations(list, ops); - if (error) { -diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c -index e8bf481e80f72..7ea66de1442cc 100644 ---- a/net/core/rtnetlink.c -+++ b/net/core/rtnetlink.c -@@ -880,9 +880,9 @@ static void set_operstate(struct net_device *dev, unsigned char transition) - break; - } - -- if (dev->operstate != operstate) { -+ if (READ_ONCE(dev->operstate) != operstate) { - write_lock(&dev_base_lock); -- dev->operstate = operstate; -+ WRITE_ONCE(dev->operstate, operstate); - write_unlock(&dev_base_lock); - netdev_state_change(dev); - } -@@ -2519,7 +2519,7 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr **tb) - - nla_for_each_nested(attr, tb[IFLA_VF_VLAN_LIST], rem) { - if (nla_type(attr) != IFLA_VF_VLAN_INFO || -- nla_len(attr) < NLA_HDRLEN) { -+ nla_len(attr) < sizeof(struct ifla_vf_vlan_info)) { - return -EINVAL; - } - if (len >= MAX_VLAN_LIST_LEN) -diff --git a/net/core/skbuff.c b/net/core/skbuff.c -index 60876262b3fb3..f0a9ef1aeaa29 100644 ---- a/net/core/skbuff.c -+++ b/net/core/skbuff.c -@@ -1971,11 +1971,17 @@ static inline int skb_alloc_rx_flag(const struct sk_buff *skb) - - struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask) - { -- int headerlen = skb_headroom(skb); -- unsigned int size = skb_end_offset(skb) + skb->data_len; -- struct sk_buff *n = __alloc_skb(size, gfp_mask, -- skb_alloc_rx_flag(skb), NUMA_NO_NODE); -+ struct sk_buff *n; -+ unsigned int size; -+ int headerlen; -+ -+ if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST)) -+ return NULL; - -+ headerlen = skb_headroom(skb); -+ size = skb_end_offset(skb) + skb->data_len; -+ n = __alloc_skb(size, gfp_mask, -+ skb_alloc_rx_flag(skb), NUMA_NO_NODE); - if (!n) - return NULL; - -@@ -2303,12 +2309,17 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, - /* - * Allocate the copy buffer - */ -- struct sk_buff *n = __alloc_skb(newheadroom + skb->len + newtailroom, -- gfp_mask, skb_alloc_rx_flag(skb), -- NUMA_NO_NODE); -- int oldheadroom = skb_headroom(skb); - int head_copy_len, head_copy_off; -+ struct sk_buff *n; -+ int oldheadroom; -+ -+ if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST)) -+ return NULL; - -+ oldheadroom = skb_headroom(skb); -+ n = __alloc_skb(newheadroom + skb->len + newtailroom, -+ gfp_mask, skb_alloc_rx_flag(skb), -+ NUMA_NO_NODE); - if (!n) - return NULL; - -diff --git a/net/core/skmsg.c b/net/core/skmsg.c -index 4d75ef9d24bfa..fd20aae30be23 100644 ---- a/net/core/skmsg.c -+++ b/net/core/skmsg.c -@@ -1226,11 +1226,8 @@ static void sk_psock_verdict_data_ready(struct sock *sk) - - rcu_read_lock(); - psock = sk_psock(sk); -- if (psock) { -- read_lock_bh(&sk->sk_callback_lock); -+ if (psock) - sk_psock_data_ready(sk, psock); -- read_unlock_bh(&sk->sk_callback_lock); -- } - rcu_read_unlock(); - } - } -diff --git a/net/core/sock.c b/net/core/sock.c -index 1471c0a862b36..7f64a7b95cfb2 100644 ---- a/net/core/sock.c -+++ b/net/core/sock.c -@@ -486,7 +486,7 @@ int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) - unsigned long flags; - struct sk_buff_head *list = &sk->sk_receive_queue; - -- if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) { -+ if (atomic_read(&sk->sk_rmem_alloc) >= READ_ONCE(sk->sk_rcvbuf)) { - atomic_inc(&sk->sk_drops); - trace_sock_rcvqueue_full(sk, skb); - return -ENOMEM; -@@ -556,7 +556,7 @@ int __sk_receive_skb(struct sock *sk, struct sk_buff *skb, - - skb->dev = NULL; - -- if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) { -+ if (sk_rcvqueues_full(sk, READ_ONCE(sk->sk_rcvbuf))) { - atomic_inc(&sk->sk_drops); - goto discard_and_relse; - } -diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c -index dd4b5f0aa1318..c5f7bd01379ce 100644 ---- a/net/hsr/hsr_device.c -+++ b/net/hsr/hsr_device.c -@@ -31,8 +31,8 @@ static bool is_slave_up(struct net_device *dev) - static void __hsr_set_operstate(struct net_device *dev, int transition) - { - write_lock(&dev_base_lock); -- if (dev->operstate != transition) { -- dev->operstate = transition; -+ if (READ_ONCE(dev->operstate) != transition) { -+ WRITE_ONCE(dev->operstate, transition); - write_unlock(&dev_base_lock); - netdev_state_change(dev); - } else { -@@ -71,39 +71,36 @@ static bool hsr_check_carrier(struct hsr_port *master) - return false; - } - --static void hsr_check_announce(struct net_device *hsr_dev, -- unsigned char old_operstate) -+static void hsr_check_announce(struct net_device *hsr_dev) - { - struct hsr_priv *hsr; - - hsr = netdev_priv(hsr_dev); -- -- if (hsr_dev->operstate == IF_OPER_UP && old_operstate != IF_OPER_UP) { -- /* Went up */ -- hsr->announce_count = 0; -- mod_timer(&hsr->announce_timer, -- jiffies + msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL)); -+ if (netif_running(hsr_dev) && netif_oper_up(hsr_dev)) { -+ /* Enable announce timer and start sending supervisory frames */ -+ if (!timer_pending(&hsr->announce_timer)) { -+ hsr->announce_count = 0; -+ mod_timer(&hsr->announce_timer, jiffies + -+ msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL)); -+ } -+ } else { -+ /* Deactivate the announce timer */ -+ timer_delete(&hsr->announce_timer); - } -- -- if (hsr_dev->operstate != IF_OPER_UP && old_operstate == IF_OPER_UP) -- /* Went down */ -- del_timer(&hsr->announce_timer); - } - - void hsr_check_carrier_and_operstate(struct hsr_priv *hsr) - { - struct hsr_port *master; -- unsigned char old_operstate; - bool has_carrier; - - master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); - /* netif_stacked_transfer_operstate() cannot be used here since - * it doesn't set IF_OPER_LOWERLAYERDOWN (?) - */ -- old_operstate = master->dev->operstate; - has_carrier = hsr_check_carrier(master); - hsr_set_operstate(master, has_carrier); -- hsr_check_announce(master->dev, old_operstate); -+ hsr_check_announce(master->dev); - } - - int hsr_get_max_mtu(struct hsr_priv *hsr) -diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c -index e59962f34caa6..b50308105551f 100644 ---- a/net/ipv4/af_inet.c -+++ b/net/ipv4/af_inet.c -@@ -1571,6 +1571,7 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb) - /* The above will be needed by the transport layer if there is one - * immediately following this IP hdr. - */ -+ NAPI_GRO_CB(skb)->inner_network_offset = off; - - /* Note : No need to call skb_gro_postpull_rcsum() here, - * as we already checked checksum over ipv4 header was 0 -diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c -index 196495ff3977b..2458461e24874 100644 ---- a/net/ipv4/ip_output.c -+++ b/net/ipv4/ip_output.c -@@ -1469,7 +1469,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk, - * by icmp_hdr(skb)->type. - */ - if (sk->sk_type == SOCK_RAW && -- !inet_test_bit(HDRINCL, sk)) -+ !(fl4->flowi4_flags & FLOWI_FLAG_KNOWN_NH)) - icmp_type = fl4->fl4_icmp_type; - else - icmp_type = icmp_hdr(skb)->type; -diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c -index ee55d0cbe4e63..39834b95ee59a 100644 ---- a/net/ipv4/raw.c -+++ b/net/ipv4/raw.c -@@ -604,6 +604,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) - (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), - daddr, saddr, 0, 0, sk->sk_uid); - -+ fl4.fl4_icmp_type = 0; -+ fl4.fl4_icmp_code = 0; -+ - if (!hdrincl) { - rfv.msg = msg; - rfv.hlen = 0; -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index f8df35f7352a5..7bf774bdb9386 100644 ---- a/net/ipv4/tcp.c -+++ b/net/ipv4/tcp.c -@@ -2710,7 +2710,7 @@ void tcp_shutdown(struct sock *sk, int how) - /* If we've already sent a FIN, or it's a closed state, skip this. */ - if ((1 << sk->sk_state) & - (TCPF_ESTABLISHED | TCPF_SYN_SENT | -- TCPF_SYN_RECV | TCPF_CLOSE_WAIT)) { -+ TCPF_CLOSE_WAIT)) { - /* Clear out any half completed packets. FIN if needed. */ - if (tcp_close_state(sk)) - tcp_send_fin(sk); -@@ -2819,7 +2819,7 @@ void __tcp_close(struct sock *sk, long timeout) - * machine. State transitions: - * - * TCP_ESTABLISHED -> TCP_FIN_WAIT1 -- * TCP_SYN_RECV -> TCP_FIN_WAIT1 (forget it, it's impossible) -+ * TCP_SYN_RECV -> TCP_FIN_WAIT1 (it is difficult) - * TCP_CLOSE_WAIT -> TCP_LAST_ACK - * - * are legal only when FIN has been sent (i.e. in window), -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index e6c4929549428..f938442b202d7 100644 ---- a/net/ipv4/tcp_input.c -+++ b/net/ipv4/tcp_input.c -@@ -6627,6 +6627,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) - - tcp_initialize_rcv_mss(sk); - tcp_fast_path_on(tp); -+ if (sk->sk_shutdown & SEND_SHUTDOWN) -+ tcp_shutdown(sk, SEND_SHUTDOWN); - break; - - case TCP_FIN_WAIT1: { -diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c -index c7ffab37a34cd..c464ced7137ee 100644 ---- a/net/ipv4/tcp_ipv4.c -+++ b/net/ipv4/tcp_ipv4.c -@@ -154,6 +154,12 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp) - if (tcptw->tw_ts_recent_stamp && - (!twp || (reuse && time_after32(ktime_get_seconds(), - tcptw->tw_ts_recent_stamp)))) { -+ /* inet_twsk_hashdance() sets sk_refcnt after putting twsk -+ * and releasing the bucket lock. -+ */ -+ if (unlikely(!refcount_inc_not_zero(&sktw->sk_refcnt))) -+ return 0; -+ - /* In case of repair and re-using TIME-WAIT sockets we still - * want to be sure that it is safe as above but honor the - * sequence numbers and time stamps set as part of the repair -@@ -174,7 +180,7 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp) - tp->rx_opt.ts_recent = tcptw->tw_ts_recent; - tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp; - } -- sock_hold(sktw); -+ - return 1; - } - -diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c -index ab3b7b4b4429b..5631041ae12cb 100644 ---- a/net/ipv4/tcp_output.c -+++ b/net/ipv4/tcp_output.c -@@ -3533,7 +3533,9 @@ void tcp_send_fin(struct sock *sk) - return; - } - } else { -- skb = alloc_skb_fclone(MAX_TCP_HEADER, sk->sk_allocation); -+ skb = alloc_skb_fclone(MAX_TCP_HEADER, -+ sk_gfp_mask(sk, GFP_ATOMIC | -+ __GFP_NOWARN)); - if (unlikely(!skb)) - return; - -diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c -index 5e9219623c0a6..ca576587f6d21 100644 ---- a/net/ipv4/udp.c -+++ b/net/ipv4/udp.c -@@ -534,7 +534,8 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb, - struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb, - __be16 sport, __be16 dport) - { -- const struct iphdr *iph = ip_hdr(skb); -+ const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation]; -+ const struct iphdr *iph = (struct iphdr *)(skb->data + offset); - struct net *net = dev_net(skb->dev); - int iif, sdif; - -diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c -index c3d67423ae189..e5971890d637d 100644 ---- a/net/ipv4/udp_offload.c -+++ b/net/ipv4/udp_offload.c -@@ -471,6 +471,7 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head, - struct sk_buff *p; - unsigned int ulen; - int ret = 0; -+ int flush; - - /* requires non zero csum, for symmetry with GSO */ - if (!uh->check) { -@@ -504,13 +505,22 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head, - return p; - } - -+ flush = NAPI_GRO_CB(p)->flush; -+ -+ if (NAPI_GRO_CB(p)->flush_id != 1 || -+ NAPI_GRO_CB(p)->count != 1 || -+ !NAPI_GRO_CB(p)->is_atomic) -+ flush |= NAPI_GRO_CB(p)->flush_id; -+ else -+ NAPI_GRO_CB(p)->is_atomic = false; -+ - /* Terminate the flow on len mismatch or if it grow "too much". - * Under small packet flood GRO count could elsewhere grow a lot - * leading to excessive truesize values. - * On len mismatch merge the first packet shorter than gso_size, - * otherwise complete the GRO packet. - */ -- if (ulen > ntohs(uh2->len)) { -+ if (ulen > ntohs(uh2->len) || flush) { - pp = p; - } else { - if (NAPI_GRO_CB(skb)->is_flist) { -@@ -718,7 +728,8 @@ EXPORT_SYMBOL(udp_gro_complete); - - INDIRECT_CALLABLE_SCOPE int udp4_gro_complete(struct sk_buff *skb, int nhoff) - { -- const struct iphdr *iph = ip_hdr(skb); -+ const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation]; -+ const struct iphdr *iph = (struct iphdr *)(skb->data + offset); - struct udphdr *uh = (struct udphdr *)(skb->data + nhoff); - - /* do fraglist only if there is no outer UDP encap (or we already processed it) */ -diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c -index 183f6dc372429..f6e90ba50b639 100644 ---- a/net/ipv4/xfrm4_input.c -+++ b/net/ipv4/xfrm4_input.c -@@ -61,7 +61,11 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async) - ip_send_check(iph); - - if (xo && (xo->flags & XFRM_GRO)) { -- skb_mac_header_rebuild(skb); -+ /* The full l2 header needs to be preserved so that re-injecting the packet at l2 -+ * works correctly in the presence of vlan tags. -+ */ -+ skb_mac_header_rebuild_full(skb, xo->orig_mac_len); -+ skb_reset_network_header(skb); - skb_reset_transport_header(skb); - return 0; - } -diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c -index d1806eee1687d..9dfbda164e8c1 100644 ---- a/net/ipv6/addrconf.c -+++ b/net/ipv6/addrconf.c -@@ -4160,7 +4160,7 @@ static void addrconf_dad_work(struct work_struct *w) - if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) && - ipv6_addr_equal(&ifp->addr, &addr)) { - /* DAD failed for link-local based on MAC */ -- idev->cnf.disable_ipv6 = 1; -+ WRITE_ONCE(idev->cnf.disable_ipv6, 1); - - pr_info("%s: IPv6 being disabled!\n", - ifp->idev->dev->name); -@@ -6011,7 +6011,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, - (dev->ifindex != dev_get_iflink(dev) && - nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) || - nla_put_u8(skb, IFLA_OPERSTATE, -- netif_running(dev) ? dev->operstate : IF_OPER_DOWN)) -+ netif_running(dev) ? READ_ONCE(dev->operstate) : IF_OPER_DOWN)) - goto nla_put_failure; - protoinfo = nla_nest_start_noflag(skb, IFLA_PROTINFO); - if (!protoinfo) -@@ -6321,7 +6321,8 @@ static void addrconf_disable_change(struct net *net, __s32 newf) - idev = __in6_dev_get(dev); - if (idev) { - int changed = (!idev->cnf.disable_ipv6) ^ (!newf); -- idev->cnf.disable_ipv6 = newf; -+ -+ WRITE_ONCE(idev->cnf.disable_ipv6, newf); - if (changed) - dev_disable_change(idev); - } -@@ -6338,7 +6339,7 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf) - - net = (struct net *)table->extra2; - old = *p; -- *p = newf; -+ WRITE_ONCE(*p, newf); - - if (p == &net->ipv6.devconf_dflt->disable_ipv6) { - rtnl_unlock(); -@@ -6346,7 +6347,7 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf) - } - - if (p == &net->ipv6.devconf_all->disable_ipv6) { -- net->ipv6.devconf_dflt->disable_ipv6 = newf; -+ WRITE_ONCE(net->ipv6.devconf_dflt->disable_ipv6, newf); - addrconf_disable_change(net, newf); - } else if ((!newf) ^ (!old)) - dev_disable_change((struct inet6_dev *)table->extra1); -diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c -index be52b18e08a6b..6eeab21512ba9 100644 ---- a/net/ipv6/fib6_rules.c -+++ b/net/ipv6/fib6_rules.c -@@ -233,8 +233,12 @@ static int __fib6_rule_action(struct fib_rule *rule, struct flowi *flp, - rt = pol_lookup_func(lookup, - net, table, flp6, arg->lookup_data, flags); - if (rt != net->ipv6.ip6_null_entry) { -+ struct inet6_dev *idev = ip6_dst_idev(&rt->dst); -+ -+ if (!idev) -+ goto again; - err = fib6_rule_saddr(net, rule, flags, flp6, -- ip6_dst_idev(&rt->dst)->dev); -+ idev->dev); - - if (err == -EAGAIN) - goto again; -diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c -index b8378814532ce..1ba97933c74fb 100644 ---- a/net/ipv6/ip6_input.c -+++ b/net/ipv6/ip6_input.c -@@ -168,9 +168,9 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev, - - SKB_DR_SET(reason, NOT_SPECIFIED); - if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL || -- !idev || unlikely(idev->cnf.disable_ipv6)) { -+ !idev || unlikely(READ_ONCE(idev->cnf.disable_ipv6))) { - __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS); -- if (idev && unlikely(idev->cnf.disable_ipv6)) -+ if (idev && unlikely(READ_ONCE(idev->cnf.disable_ipv6))) - SKB_DR_SET(reason, IPV6DISABLED); - goto drop; - } -diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c -index d6314287338da..7f014a8969fb2 100644 ---- a/net/ipv6/ip6_offload.c -+++ b/net/ipv6/ip6_offload.c -@@ -37,6 +37,40 @@ - INDIRECT_CALL_L4(cb, f2, f1, head, skb); \ - }) - -+static int ipv6_gro_pull_exthdrs(struct sk_buff *skb, int off, int proto) -+{ -+ const struct net_offload *ops = NULL; -+ struct ipv6_opt_hdr *opth; -+ -+ for (;;) { -+ int len; -+ -+ ops = rcu_dereference(inet6_offloads[proto]); -+ -+ if (unlikely(!ops)) -+ break; -+ -+ if (!(ops->flags & INET6_PROTO_GSO_EXTHDR)) -+ break; -+ -+ opth = skb_gro_header(skb, off + sizeof(*opth), off); -+ if (unlikely(!opth)) -+ break; -+ -+ len = ipv6_optlen(opth); -+ -+ opth = skb_gro_header(skb, off + len, off); -+ if (unlikely(!opth)) -+ break; -+ proto = opth->nexthdr; -+ -+ off += len; -+ } -+ -+ skb_gro_pull(skb, off - skb_network_offset(skb)); -+ return proto; -+} -+ - static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto) - { - const struct net_offload *ops = NULL; -@@ -206,28 +240,26 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head, - goto out; - - skb_set_network_header(skb, off); -- skb_gro_pull(skb, sizeof(*iph)); -- skb_set_transport_header(skb, skb_gro_offset(skb)); -+ NAPI_GRO_CB(skb)->inner_network_offset = off; - -- flush += ntohs(iph->payload_len) != skb_gro_len(skb); -+ flush += ntohs(iph->payload_len) != skb->len - hlen; - - proto = iph->nexthdr; - ops = rcu_dereference(inet6_offloads[proto]); - if (!ops || !ops->callbacks.gro_receive) { -- pskb_pull(skb, skb_gro_offset(skb)); -- skb_gro_frag0_invalidate(skb); -- proto = ipv6_gso_pull_exthdrs(skb, proto); -- skb_gro_pull(skb, -skb_transport_offset(skb)); -- skb_reset_transport_header(skb); -- __skb_push(skb, skb_gro_offset(skb)); -+ proto = ipv6_gro_pull_exthdrs(skb, hlen, proto); - - ops = rcu_dereference(inet6_offloads[proto]); - if (!ops || !ops->callbacks.gro_receive) - goto out; - -- iph = ipv6_hdr(skb); -+ iph = skb_gro_network_header(skb); -+ } else { -+ skb_gro_pull(skb, sizeof(*iph)); - } - -+ skb_set_transport_header(skb, skb_gro_offset(skb)); -+ - NAPI_GRO_CB(skb)->proto = proto; - - flush--; -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 53fe1375b147c..f97cb368e5a81 100644 ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -227,7 +227,7 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb) - skb->protocol = htons(ETH_P_IPV6); - skb->dev = dev; - -- if (unlikely(idev->cnf.disable_ipv6)) { -+ if (unlikely(!idev || READ_ONCE(idev->cnf.disable_ipv6))) { - IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); - kfree_skb_reason(skb, SKB_DROP_REASON_IPV6DISABLED); - return 0; -@@ -2003,7 +2003,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk, - u8 icmp6_type; - - if (sk->sk_socket->type == SOCK_RAW && -- !inet_test_bit(HDRINCL, sk)) -+ !(fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH)) - icmp6_type = fl6->fl6_icmp_type; - else - icmp6_type = icmp6_hdr(skb)->icmp6_type; -diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c -index a05c83cfdde97..124cf2bb2a6d7 100644 ---- a/net/ipv6/udp.c -+++ b/net/ipv6/udp.c -@@ -275,7 +275,8 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, - struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb, - __be16 sport, __be16 dport) - { -- const struct ipv6hdr *iph = ipv6_hdr(skb); -+ const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation]; -+ const struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + offset); - struct net *net = dev_net(skb->dev); - int iif, sdif; - -diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c -index 626d7b362dc7b..639a4b506f9b5 100644 ---- a/net/ipv6/udp_offload.c -+++ b/net/ipv6/udp_offload.c -@@ -164,7 +164,8 @@ struct sk_buff *udp6_gro_receive(struct list_head *head, struct sk_buff *skb) - - INDIRECT_CALLABLE_SCOPE int udp6_gro_complete(struct sk_buff *skb, int nhoff) - { -- const struct ipv6hdr *ipv6h = ipv6_hdr(skb); -+ const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation]; -+ const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + offset); - struct udphdr *uh = (struct udphdr *)(skb->data + nhoff); - - /* do fraglist only if there is no outer UDP encap (or we already processed it) */ -diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c -index 4156387248e40..8432b50d9ce4c 100644 ---- a/net/ipv6/xfrm6_input.c -+++ b/net/ipv6/xfrm6_input.c -@@ -56,7 +56,11 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async) - skb_postpush_rcsum(skb, skb_network_header(skb), nhlen); - - if (xo && (xo->flags & XFRM_GRO)) { -- skb_mac_header_rebuild(skb); -+ /* The full l2 header needs to be preserved so that re-injecting the packet at l2 -+ * works correctly in the presence of vlan tags. -+ */ -+ skb_mac_header_rebuild_full(skb, xo->orig_mac_len); -+ skb_reset_network_header(skb); - skb_reset_transport_header(skb); - return 0; - } -diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c -index f2ae03c404736..1f41d2f3b8c4e 100644 ---- a/net/l2tp/l2tp_eth.c -+++ b/net/l2tp/l2tp_eth.c -@@ -136,6 +136,9 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, - /* checksums verified by L2TP */ - skb->ip_summed = CHECKSUM_NONE; - -+ /* drop outer flow-hash */ -+ skb_clear_hash(skb); -+ - skb_dst_drop(skb); - nf_reset_ct(skb); - -diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h -index 07beb72ddd25a..fefaa9e902a2f 100644 ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -122,7 +122,7 @@ struct ieee80211_bss { - }; - - /** -- * enum ieee80211_corrupt_data_flags - BSS data corruption flags -+ * enum ieee80211_bss_corrupt_data_flags - BSS data corruption flags - * @IEEE80211_BSS_CORRUPT_BEACON: last beacon frame received was corrupted - * @IEEE80211_BSS_CORRUPT_PROBE_RESP: last probe response received was corrupted - * -@@ -135,7 +135,7 @@ enum ieee80211_bss_corrupt_data_flags { - }; - - /** -- * enum ieee80211_valid_data_flags - BSS valid data flags -+ * enum ieee80211_bss_valid_data_flags - BSS valid data flags - * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE - * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE - * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE -diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c -index 6e574e2adc22e..cf01f1f298a3b 100644 ---- a/net/mac80211/mlme.c -+++ b/net/mac80211/mlme.c -@@ -7080,7 +7080,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, - sdata_info(sdata, - "failed to insert STA entry for the AP (error %d)\n", - err); -- goto out_err; -+ goto out_release_chan; - } - } else - WARN_ON_ONCE(!ether_addr_equal(link->u.mgd.bssid, cbss->bssid)); -@@ -7091,8 +7091,9 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, - - return 0; - -+out_release_chan: -+ ieee80211_link_release_channel(link); - out_err: -- ieee80211_link_release_channel(&sdata->deflink); - ieee80211_vif_set_links(sdata, 0, 0); - return err; - } -diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c -index e72b518c5d026..de75df904a003 100644 ---- a/net/mptcp/ctrl.c -+++ b/net/mptcp/ctrl.c -@@ -87,6 +87,43 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet) - } - - #ifdef CONFIG_SYSCTL -+static int mptcp_set_scheduler(const struct net *net, const char *name) -+{ -+ struct mptcp_pernet *pernet = mptcp_get_pernet(net); -+ struct mptcp_sched_ops *sched; -+ int ret = 0; -+ -+ rcu_read_lock(); -+ sched = mptcp_sched_find(name); -+ if (sched) -+ strscpy(pernet->scheduler, name, MPTCP_SCHED_NAME_MAX); -+ else -+ ret = -ENOENT; -+ rcu_read_unlock(); -+ -+ return ret; -+} -+ -+static int proc_scheduler(struct ctl_table *ctl, int write, -+ void *buffer, size_t *lenp, loff_t *ppos) -+{ -+ const struct net *net = current->nsproxy->net_ns; -+ char val[MPTCP_SCHED_NAME_MAX]; -+ struct ctl_table tbl = { -+ .data = val, -+ .maxlen = MPTCP_SCHED_NAME_MAX, -+ }; -+ int ret; -+ -+ strscpy(val, mptcp_get_scheduler(net), MPTCP_SCHED_NAME_MAX); -+ -+ ret = proc_dostring(&tbl, write, buffer, lenp, ppos); -+ if (write && ret == 0) -+ ret = mptcp_set_scheduler(net, val); -+ -+ return ret; -+} -+ - static struct ctl_table mptcp_sysctl_table[] = { - { - .procname = "enabled", -@@ -139,7 +176,7 @@ static struct ctl_table mptcp_sysctl_table[] = { - .procname = "scheduler", - .maxlen = MPTCP_SCHED_NAME_MAX, - .mode = 0644, -- .proc_handler = proc_dostring, -+ .proc_handler = proc_scheduler, - }, - {} - }; -diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c -index 01ac690af7799..618d80112d1e2 100644 ---- a/net/mptcp/protocol.c -+++ b/net/mptcp/protocol.c -@@ -3698,6 +3698,9 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) - MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_TOKENFALLBACKINIT); - mptcp_subflow_early_fallback(msk, subflow); - } -+ -+ WRITE_ONCE(msk->write_seq, subflow->idsn); -+ WRITE_ONCE(msk->snd_nxt, subflow->idsn); - if (likely(!__mptcp_check_fallback(msk))) - MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVE); - -diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c -index 772ddb5824d9e..5d708af0fcfd3 100644 ---- a/net/nfc/nci/core.c -+++ b/net/nfc/nci/core.c -@@ -1518,6 +1518,7 @@ static void nci_rx_work(struct work_struct *work) - - if (!nci_plen(skb->data)) { - kfree_skb(skb); -+ kcov_remote_stop(); - break; - } - -diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c -index f4a38bd6a7e04..bfb7758063f31 100644 ---- a/net/nsh/nsh.c -+++ b/net/nsh/nsh.c -@@ -77,13 +77,15 @@ EXPORT_SYMBOL_GPL(nsh_pop); - static struct sk_buff *nsh_gso_segment(struct sk_buff *skb, - netdev_features_t features) - { -+ unsigned int outer_hlen, mac_len, nsh_len; - struct sk_buff *segs = ERR_PTR(-EINVAL); - u16 mac_offset = skb->mac_header; -- unsigned int nsh_len, mac_len; -- __be16 proto; -+ __be16 outer_proto, proto; - - skb_reset_network_header(skb); - -+ outer_proto = skb->protocol; -+ outer_hlen = skb_mac_header_len(skb); - mac_len = skb->mac_len; - - if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN))) -@@ -113,10 +115,10 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb, - } - - for (skb = segs; skb; skb = skb->next) { -- skb->protocol = htons(ETH_P_NSH); -- __skb_push(skb, nsh_len); -- skb->mac_header = mac_offset; -- skb->network_header = skb->mac_header + mac_len; -+ skb->protocol = outer_proto; -+ __skb_push(skb, nsh_len + outer_hlen); -+ skb_reset_mac_header(skb); -+ skb_set_network_header(skb, outer_hlen); - skb->mac_len = mac_len; - } - -diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c -index 59aebe2968907..dd4c7e9a634fb 100644 ---- a/net/phonet/pn_netlink.c -+++ b/net/phonet/pn_netlink.c -@@ -193,7 +193,7 @@ void rtm_phonet_notify(int event, struct net_device *dev, u8 dst) - struct sk_buff *skb; - int err = -ENOBUFS; - -- skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) + -+ skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct rtmsg)) + - nla_total_size(1) + nla_total_size(4), GFP_KERNEL); - if (skb == NULL) - goto errout; -diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h -index bda3f6690b321..d431376bb120a 100644 ---- a/net/rxrpc/ar-internal.h -+++ b/net/rxrpc/ar-internal.h -@@ -688,7 +688,7 @@ struct rxrpc_call { - * packets) rather than bytes. - */ - #define RXRPC_TX_SMSS RXRPC_JUMBO_DATALEN --#define RXRPC_MIN_CWND (RXRPC_TX_SMSS > 2190 ? 2 : RXRPC_TX_SMSS > 1095 ? 3 : 4) -+#define RXRPC_MIN_CWND 4 - u8 cong_cwnd; /* Congestion window size */ - u8 cong_extra; /* Extra to send for congestion management */ - u8 cong_ssthresh; /* Slow-start threshold */ -diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c -index 0a50341d920af..29385908099ef 100644 ---- a/net/rxrpc/call_object.c -+++ b/net/rxrpc/call_object.c -@@ -175,12 +175,7 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp, - call->rx_winsize = rxrpc_rx_window_size; - call->tx_winsize = 16; - -- if (RXRPC_TX_SMSS > 2190) -- call->cong_cwnd = 2; -- else if (RXRPC_TX_SMSS > 1095) -- call->cong_cwnd = 3; -- else -- call->cong_cwnd = 4; -+ call->cong_cwnd = RXRPC_MIN_CWND; - call->cong_ssthresh = RXRPC_TX_MAX_WINDOW; - - call->rxnet = rxnet; -diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c -index 1f251d758cb9d..598b4ee389fc1 100644 ---- a/net/rxrpc/conn_event.c -+++ b/net/rxrpc/conn_event.c -@@ -88,7 +88,7 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn, - struct rxrpc_ackpacket ack; - }; - } __attribute__((packed)) pkt; -- struct rxrpc_ackinfo ack_info; -+ struct rxrpc_acktrailer trailer; - size_t len; - int ret, ioc; - u32 serial, mtu, call_id, padding; -@@ -122,8 +122,8 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn, - iov[0].iov_len = sizeof(pkt.whdr); - iov[1].iov_base = &padding; - iov[1].iov_len = 3; -- iov[2].iov_base = &ack_info; -- iov[2].iov_len = sizeof(ack_info); -+ iov[2].iov_base = &trailer; -+ iov[2].iov_len = sizeof(trailer); - - serial = rxrpc_get_next_serial(conn); - -@@ -158,14 +158,14 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn, - pkt.ack.serial = htonl(skb ? sp->hdr.serial : 0); - pkt.ack.reason = skb ? RXRPC_ACK_DUPLICATE : RXRPC_ACK_IDLE; - pkt.ack.nAcks = 0; -- ack_info.rxMTU = htonl(rxrpc_rx_mtu); -- ack_info.maxMTU = htonl(mtu); -- ack_info.rwind = htonl(rxrpc_rx_window_size); -- ack_info.jumbo_max = htonl(rxrpc_rx_jumbo_max); -+ trailer.maxMTU = htonl(rxrpc_rx_mtu); -+ trailer.ifMTU = htonl(mtu); -+ trailer.rwind = htonl(rxrpc_rx_window_size); -+ trailer.jumbo_max = htonl(rxrpc_rx_jumbo_max); - pkt.whdr.flags |= RXRPC_SLOW_START_OK; - padding = 0; - iov[0].iov_len += sizeof(pkt.ack); -- len += sizeof(pkt.ack) + 3 + sizeof(ack_info); -+ len += sizeof(pkt.ack) + 3 + sizeof(trailer); - ioc = 3; - - trace_rxrpc_tx_ack(chan->call_debug_id, serial, -diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c -index df8a271948a1c..7aa58129ae455 100644 ---- a/net/rxrpc/conn_object.c -+++ b/net/rxrpc/conn_object.c -@@ -118,18 +118,13 @@ struct rxrpc_connection *rxrpc_find_client_connection_rcu(struct rxrpc_local *lo - switch (srx->transport.family) { - case AF_INET: - if (peer->srx.transport.sin.sin_port != -- srx->transport.sin.sin_port || -- peer->srx.transport.sin.sin_addr.s_addr != -- srx->transport.sin.sin_addr.s_addr) -+ srx->transport.sin.sin_port) - goto not_found; - break; - #ifdef CONFIG_AF_RXRPC_IPV6 - case AF_INET6: - if (peer->srx.transport.sin6.sin6_port != -- srx->transport.sin6.sin6_port || -- memcmp(&peer->srx.transport.sin6.sin6_addr, -- &srx->transport.sin6.sin6_addr, -- sizeof(struct in6_addr)) != 0) -+ srx->transport.sin6.sin6_port) - goto not_found; - break; - #endif -diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c -index 9691de00ade75..5dfda1ac51dda 100644 ---- a/net/rxrpc/input.c -+++ b/net/rxrpc/input.c -@@ -9,6 +9,17 @@ - - #include "ar-internal.h" - -+/* Override priority when generating ACKs for received DATA */ -+static const u8 rxrpc_ack_priority[RXRPC_ACK__INVALID] = { -+ [RXRPC_ACK_IDLE] = 1, -+ [RXRPC_ACK_DELAY] = 2, -+ [RXRPC_ACK_REQUESTED] = 3, -+ [RXRPC_ACK_DUPLICATE] = 4, -+ [RXRPC_ACK_EXCEEDS_WINDOW] = 5, -+ [RXRPC_ACK_NOSPACE] = 6, -+ [RXRPC_ACK_OUT_OF_SEQUENCE] = 7, -+}; -+ - static void rxrpc_proto_abort(struct rxrpc_call *call, rxrpc_seq_t seq, - enum rxrpc_abort_reason why) - { -@@ -366,7 +377,7 @@ static void rxrpc_input_queue_data(struct rxrpc_call *call, struct sk_buff *skb, - * Process a DATA packet. - */ - static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb, -- bool *_notify) -+ bool *_notify, rxrpc_serial_t *_ack_serial, int *_ack_reason) - { - struct rxrpc_skb_priv *sp = rxrpc_skb(skb); - struct sk_buff *oos; -@@ -419,8 +430,6 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb, - /* Send an immediate ACK if we fill in a hole */ - else if (!skb_queue_empty(&call->rx_oos_queue)) - ack_reason = RXRPC_ACK_DELAY; -- else -- call->ackr_nr_unacked++; - - window++; - if (after(window, wtop)) { -@@ -498,12 +507,16 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb, - } - - send_ack: -- if (ack_reason >= 0) -- rxrpc_send_ACK(call, ack_reason, serial, -- rxrpc_propose_ack_input_data); -- else -- rxrpc_propose_delay_ACK(call, serial, -- rxrpc_propose_ack_input_data); -+ if (ack_reason >= 0) { -+ if (rxrpc_ack_priority[ack_reason] > rxrpc_ack_priority[*_ack_reason]) { -+ *_ack_serial = serial; -+ *_ack_reason = ack_reason; -+ } else if (rxrpc_ack_priority[ack_reason] == rxrpc_ack_priority[*_ack_reason] && -+ ack_reason == RXRPC_ACK_REQUESTED) { -+ *_ack_serial = serial; -+ *_ack_reason = ack_reason; -+ } -+ } - } - - /* -@@ -514,9 +527,11 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb - struct rxrpc_jumbo_header jhdr; - struct rxrpc_skb_priv *sp = rxrpc_skb(skb), *jsp; - struct sk_buff *jskb; -+ rxrpc_serial_t ack_serial = 0; - unsigned int offset = sizeof(struct rxrpc_wire_header); - unsigned int len = skb->len - offset; - bool notify = false; -+ int ack_reason = 0; - - while (sp->hdr.flags & RXRPC_JUMBO_PACKET) { - if (len < RXRPC_JUMBO_SUBPKTLEN) -@@ -536,7 +551,7 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb - jsp = rxrpc_skb(jskb); - jsp->offset = offset; - jsp->len = RXRPC_JUMBO_DATALEN; -- rxrpc_input_data_one(call, jskb, ¬ify); -+ rxrpc_input_data_one(call, jskb, ¬ify, &ack_serial, &ack_reason); - rxrpc_free_skb(jskb, rxrpc_skb_put_jumbo_subpacket); - - sp->hdr.flags = jhdr.flags; -@@ -549,7 +564,16 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb - - sp->offset = offset; - sp->len = len; -- rxrpc_input_data_one(call, skb, ¬ify); -+ rxrpc_input_data_one(call, skb, ¬ify, &ack_serial, &ack_reason); -+ -+ if (ack_reason > 0) { -+ rxrpc_send_ACK(call, ack_reason, ack_serial, -+ rxrpc_propose_ack_input_data); -+ } else { -+ call->ackr_nr_unacked++; -+ rxrpc_propose_delay_ACK(call, sp->hdr.serial, -+ rxrpc_propose_ack_input_data); -+ } - if (notify) { - trace_rxrpc_notify_socket(call->debug_id, sp->hdr.serial); - rxrpc_notify_socket(call); -@@ -670,14 +694,14 @@ static void rxrpc_complete_rtt_probe(struct rxrpc_call *call, - /* - * Process the extra information that may be appended to an ACK packet - */ --static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb, -- struct rxrpc_ackinfo *ackinfo) -+static void rxrpc_input_ack_trailer(struct rxrpc_call *call, struct sk_buff *skb, -+ struct rxrpc_acktrailer *trailer) - { - struct rxrpc_skb_priv *sp = rxrpc_skb(skb); - struct rxrpc_peer *peer; - unsigned int mtu; - bool wake = false; -- u32 rwind = ntohl(ackinfo->rwind); -+ u32 rwind = ntohl(trailer->rwind); - - if (rwind > RXRPC_TX_MAX_WINDOW) - rwind = RXRPC_TX_MAX_WINDOW; -@@ -688,10 +712,7 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb, - call->tx_winsize = rwind; - } - -- if (call->cong_ssthresh > rwind) -- call->cong_ssthresh = rwind; -- -- mtu = min(ntohl(ackinfo->rxMTU), ntohl(ackinfo->maxMTU)); -+ mtu = min(ntohl(trailer->maxMTU), ntohl(trailer->ifMTU)); - - peer = call->peer; - if (mtu < peer->maxdata) { -@@ -837,7 +858,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) - struct rxrpc_ack_summary summary = { 0 }; - struct rxrpc_ackpacket ack; - struct rxrpc_skb_priv *sp = rxrpc_skb(skb); -- struct rxrpc_ackinfo info; -+ struct rxrpc_acktrailer trailer; - rxrpc_serial_t ack_serial, acked_serial; - rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt, since; - int nr_acks, offset, ioffset; -@@ -917,11 +938,11 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) - goto send_response; - } - -- info.rxMTU = 0; -+ trailer.maxMTU = 0; - ioffset = offset + nr_acks + 3; -- if (skb->len >= ioffset + sizeof(info) && -- skb_copy_bits(skb, ioffset, &info, sizeof(info)) < 0) -- return rxrpc_proto_abort(call, 0, rxrpc_badmsg_short_ack_info); -+ if (skb->len >= ioffset + sizeof(trailer) && -+ skb_copy_bits(skb, ioffset, &trailer, sizeof(trailer)) < 0) -+ return rxrpc_proto_abort(call, 0, rxrpc_badmsg_short_ack_trailer); - - if (nr_acks > 0) - skb_condense(skb); -@@ -950,8 +971,8 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) - } - - /* Parse rwind and mtu sizes if provided. */ -- if (info.rxMTU) -- rxrpc_input_ackinfo(call, skb, &info); -+ if (trailer.maxMTU) -+ rxrpc_input_ack_trailer(call, skb, &trailer); - - if (first_soft_ack == 0) - return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_zero); -diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c -index 4a292f860ae37..cad6a7d18e040 100644 ---- a/net/rxrpc/output.c -+++ b/net/rxrpc/output.c -@@ -83,7 +83,7 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn, - struct rxrpc_txbuf *txb, - u16 *_rwind) - { -- struct rxrpc_ackinfo ackinfo; -+ struct rxrpc_acktrailer trailer; - unsigned int qsize, sack, wrap, to; - rxrpc_seq_t window, wtop; - int rsize; -@@ -126,16 +126,16 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn, - qsize = (window - 1) - call->rx_consumed; - rsize = max_t(int, call->rx_winsize - qsize, 0); - *_rwind = rsize; -- ackinfo.rxMTU = htonl(rxrpc_rx_mtu); -- ackinfo.maxMTU = htonl(mtu); -- ackinfo.rwind = htonl(rsize); -- ackinfo.jumbo_max = htonl(jmax); -+ trailer.maxMTU = htonl(rxrpc_rx_mtu); -+ trailer.ifMTU = htonl(mtu); -+ trailer.rwind = htonl(rsize); -+ trailer.jumbo_max = htonl(jmax); - - *ackp++ = 0; - *ackp++ = 0; - *ackp++ = 0; -- memcpy(ackp, &ackinfo, sizeof(ackinfo)); -- return txb->ack.nAcks + 3 + sizeof(ackinfo); -+ memcpy(ackp, &trailer, sizeof(trailer)); -+ return txb->ack.nAcks + 3 + sizeof(trailer); - } - - /* -diff --git a/net/rxrpc/protocol.h b/net/rxrpc/protocol.h -index e8ee4af43ca89..4fe6b4d20ada9 100644 ---- a/net/rxrpc/protocol.h -+++ b/net/rxrpc/protocol.h -@@ -135,9 +135,9 @@ struct rxrpc_ackpacket { - /* - * ACK packets can have a further piece of information tagged on the end - */ --struct rxrpc_ackinfo { -- __be32 rxMTU; /* maximum Rx MTU size (bytes) [AFS 3.3] */ -- __be32 maxMTU; /* maximum interface MTU size (bytes) [AFS 3.3] */ -+struct rxrpc_acktrailer { -+ __be32 maxMTU; /* maximum Rx MTU size (bytes) [AFS 3.3] */ -+ __be32 ifMTU; /* maximum interface MTU size (bytes) [AFS 3.3] */ - __be32 rwind; /* Rx window size (packets) [AFS 3.4] */ - __be32 jumbo_max; /* max packets to stick into a jumbo packet [AFS 3.5] */ - }; -diff --git a/net/smc/smc_ib.c b/net/smc/smc_ib.c -index 89981dbe46c94..598ac9ead64b7 100644 ---- a/net/smc/smc_ib.c -+++ b/net/smc/smc_ib.c -@@ -209,13 +209,18 @@ int smc_ib_find_route(struct net *net, __be32 saddr, __be32 daddr, - if (IS_ERR(rt)) - goto out; - if (rt->rt_uses_gateway && rt->rt_gw_family != AF_INET) -- goto out; -- neigh = rt->dst.ops->neigh_lookup(&rt->dst, NULL, &fl4.daddr); -- if (neigh) { -- memcpy(nexthop_mac, neigh->ha, ETH_ALEN); -- *uses_gateway = rt->rt_uses_gateway; -- return 0; -- } -+ goto out_rt; -+ neigh = dst_neigh_lookup(&rt->dst, &fl4.daddr); -+ if (!neigh) -+ goto out_rt; -+ memcpy(nexthop_mac, neigh->ha, ETH_ALEN); -+ *uses_gateway = rt->rt_uses_gateway; -+ neigh_release(neigh); -+ ip_rt_put(rt); -+ return 0; -+ -+out_rt: -+ ip_rt_put(rt); - out: - return -ENOENT; - } -diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c -index 339dfc5b92246..f4d32cf2cd16a 100644 ---- a/net/sunrpc/clnt.c -+++ b/net/sunrpc/clnt.c -@@ -399,7 +399,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, - clnt->cl_maxproc = version->nrprocs; - clnt->cl_prog = args->prognumber ? : program->number; - clnt->cl_vers = version->number; -- clnt->cl_stats = program->stats; -+ clnt->cl_stats = args->stats ? : program->stats; - clnt->cl_metrics = rpc_alloc_iostats(clnt); - rpc_init_pipe_dir_head(&clnt->cl_pipedir_objects); - err = -ENOMEM; -@@ -685,6 +685,7 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt) - .version = clnt->cl_vers, - .authflavor = clnt->cl_auth->au_flavor, - .cred = clnt->cl_cred, -+ .stats = clnt->cl_stats, - }; - return __rpc_clone_client(&args, clnt); - } -@@ -707,6 +708,7 @@ rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor) - .version = clnt->cl_vers, - .authflavor = flavor, - .cred = clnt->cl_cred, -+ .stats = clnt->cl_stats, - }; - return __rpc_clone_client(&args, clnt); - } -@@ -1053,6 +1055,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, - .version = vers, - .authflavor = old->cl_auth->au_flavor, - .cred = old->cl_cred, -+ .stats = old->cl_stats, - }; - struct rpc_clnt *clnt; - int err; -diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c -index a15bf2ede89bf..c3007f3e16f8c 100644 ---- a/net/sunrpc/xprtsock.c -+++ b/net/sunrpc/xprtsock.c -@@ -2644,6 +2644,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work) - .xprtsec = { - .policy = RPC_XPRTSEC_NONE, - }, -+ .stats = upper_clnt->cl_stats, - }; - unsigned int pflags = current->flags; - struct rpc_clnt *lower_clnt; -diff --git a/net/tipc/msg.c b/net/tipc/msg.c -index 5c9fd4791c4ba..76284fc538ebd 100644 ---- a/net/tipc/msg.c -+++ b/net/tipc/msg.c -@@ -142,9 +142,9 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf) - if (fragid == FIRST_FRAGMENT) { - if (unlikely(head)) - goto err; -- *buf = NULL; - if (skb_has_frag_list(frag) && __skb_linearize(frag)) - goto err; -+ *buf = NULL; - frag = skb_unshare(frag, GFP_ATOMIC); - if (unlikely(!frag)) - goto err; -@@ -156,6 +156,11 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf) - if (!head) - goto err; - -+ /* Either the input skb ownership is transferred to headskb -+ * or the input skb is freed, clear the reference to avoid -+ * bad access on error path. -+ */ -+ *buf = NULL; - if (skb_try_coalesce(head, frag, &headstolen, &delta)) { - kfree_skb_partial(frag, headstolen); - } else { -@@ -179,7 +184,6 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf) - *headbuf = NULL; - return 1; - } -- *buf = NULL; - return 0; - err: - kfree_skb(*buf); -diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c -index 9f6d8bcecfebe..c4f08f7eb741d 100644 ---- a/net/wireless/nl80211.c -+++ b/net/wireless/nl80211.c -@@ -14052,6 +14052,8 @@ static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info) - error: - for (i = 0; i < new_coalesce.n_rules; i++) { - tmp_rule = &new_coalesce.rules[i]; -+ if (!tmp_rule) -+ continue; - for (j = 0; j < tmp_rule->n_patterns; j++) - kfree(tmp_rule->patterns[j].mask); - kfree(tmp_rule->patterns); -diff --git a/net/wireless/trace.h b/net/wireless/trace.h -index 617c0d0dfa963..e89443173c7b4 100644 ---- a/net/wireless/trace.h -+++ b/net/wireless/trace.h -@@ -1015,7 +1015,7 @@ TRACE_EVENT(rdev_get_mpp, - TRACE_EVENT(rdev_dump_mpp, - TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int _idx, - u8 *dst, u8 *mpp), -- TP_ARGS(wiphy, netdev, _idx, mpp, dst), -+ TP_ARGS(wiphy, netdev, _idx, dst, mpp), - TP_STRUCT__entry( - WIPHY_ENTRY - NETDEV_ENTRY -diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c -index d5ee96789d4bf..0c08bac3ed269 100644 ---- a/net/xfrm/xfrm_input.c -+++ b/net/xfrm/xfrm_input.c -@@ -388,11 +388,15 @@ static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) - */ - static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb) - { -+ struct xfrm_offload *xo = xfrm_offload(skb); - int ihl = skb->data - skb_transport_header(skb); - - if (skb->transport_header != skb->network_header) { - memmove(skb_transport_header(skb), - skb_network_header(skb), ihl); -+ if (xo) -+ xo->orig_mac_len = -+ skb_mac_header_was_set(skb) ? skb_mac_header_len(skb) : 0; - skb->network_header = skb->transport_header; - } - ip_hdr(skb)->tot_len = htons(skb->len + ihl); -@@ -403,11 +407,15 @@ static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb) - static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb) - { - #if IS_ENABLED(CONFIG_IPV6) -+ struct xfrm_offload *xo = xfrm_offload(skb); - int ihl = skb->data - skb_transport_header(skb); - - if (skb->transport_header != skb->network_header) { - memmove(skb_transport_header(skb), - skb_network_header(skb), ihl); -+ if (xo) -+ xo->orig_mac_len = -+ skb_mac_header_was_set(skb) ? skb_mac_header_len(skb) : 0; - skb->network_header = skb->transport_header; - } - ipv6_hdr(skb)->payload_len = htons(skb->len + ihl - -diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs -index e8811700239aa..de54d5fede6f8 100644 ---- a/rust/kernel/lib.rs -+++ b/rust/kernel/lib.rs -@@ -60,7 +60,7 @@ - /// The top level entrypoint to implementing a kernel module. - /// - /// For any teardown or cleanup operations, your type may implement [`Drop`]. --pub trait Module: Sized + Sync { -+pub trait Module: Sized + Sync + Send { - /// Called at module initialization time. - /// - /// Use this method to perform whatever setup or registration your module -diff --git a/rust/macros/module.rs b/rust/macros/module.rs -index d62d8710d77ab..acd0393b50957 100644 ---- a/rust/macros/module.rs -+++ b/rust/macros/module.rs -@@ -199,17 +199,6 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream { - /// Used by the printing macros, e.g. [`info!`]. - const __LOG_PREFIX: &[u8] = b\"{name}\\0\"; - -- /// The \"Rust loadable module\" mark. -- // -- // This may be best done another way later on, e.g. as a new modinfo -- // key or a new section. For the moment, keep it simple. -- #[cfg(MODULE)] -- #[doc(hidden)] -- #[used] -- static __IS_RUST_MODULE: () = (); -- -- static mut __MOD: Option<{type_}> = None; -- - // SAFETY: `__this_module` is constructed by the kernel at load time and will not be - // freed until the module is unloaded. - #[cfg(MODULE)] -@@ -221,76 +210,132 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream { - kernel::ThisModule::from_ptr(core::ptr::null_mut()) - }}; - -- // Loadable modules need to export the `{{init,cleanup}}_module` identifiers. -- #[cfg(MODULE)] -- #[doc(hidden)] -- #[no_mangle] -- pub extern \"C\" fn init_module() -> core::ffi::c_int {{ -- __init() -- }} -- -- #[cfg(MODULE)] -- #[doc(hidden)] -- #[no_mangle] -- pub extern \"C\" fn cleanup_module() {{ -- __exit() -- }} -+ // Double nested modules, since then nobody can access the public items inside. -+ mod __module_init {{ -+ mod __module_init {{ -+ use super::super::{type_}; -+ -+ /// The \"Rust loadable module\" mark. -+ // -+ // This may be best done another way later on, e.g. as a new modinfo -+ // key or a new section. For the moment, keep it simple. -+ #[cfg(MODULE)] -+ #[doc(hidden)] -+ #[used] -+ static __IS_RUST_MODULE: () = (); -+ -+ static mut __MOD: Option<{type_}> = None; -+ -+ // Loadable modules need to export the `{{init,cleanup}}_module` identifiers. -+ /// # Safety -+ /// -+ /// This function must not be called after module initialization, because it may be -+ /// freed after that completes. -+ #[cfg(MODULE)] -+ #[doc(hidden)] -+ #[no_mangle] -+ #[link_section = \".init.text\"] -+ pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{ -+ // SAFETY: This function is inaccessible to the outside due to the double -+ // module wrapping it. It is called exactly once by the C side via its -+ // unique name. -+ unsafe {{ __init() }} -+ }} - -- // Built-in modules are initialized through an initcall pointer -- // and the identifiers need to be unique. -- #[cfg(not(MODULE))] -- #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))] -- #[doc(hidden)] -- #[link_section = \"{initcall_section}\"] -- #[used] -- pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init; -+ #[cfg(MODULE)] -+ #[doc(hidden)] -+ #[no_mangle] -+ pub extern \"C\" fn cleanup_module() {{ -+ // SAFETY: -+ // - This function is inaccessible to the outside due to the double -+ // module wrapping it. It is called exactly once by the C side via its -+ // unique name, -+ // - furthermore it is only called after `init_module` has returned `0` -+ // (which delegates to `__init`). -+ unsafe {{ __exit() }} -+ }} - -- #[cfg(not(MODULE))] -- #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)] -- core::arch::global_asm!( -- r#\".section \"{initcall_section}\", \"a\" -- __{name}_initcall: -- .long __{name}_init - . -- .previous -- \"# -- ); -+ // Built-in modules are initialized through an initcall pointer -+ // and the identifiers need to be unique. -+ #[cfg(not(MODULE))] -+ #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))] -+ #[doc(hidden)] -+ #[link_section = \"{initcall_section}\"] -+ #[used] -+ pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init; -+ -+ #[cfg(not(MODULE))] -+ #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)] -+ core::arch::global_asm!( -+ r#\".section \"{initcall_section}\", \"a\" -+ __{name}_initcall: -+ .long __{name}_init - . -+ .previous -+ \"# -+ ); -+ -+ #[cfg(not(MODULE))] -+ #[doc(hidden)] -+ #[no_mangle] -+ pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{ -+ // SAFETY: This function is inaccessible to the outside due to the double -+ // module wrapping it. It is called exactly once by the C side via its -+ // placement above in the initcall section. -+ unsafe {{ __init() }} -+ }} - -- #[cfg(not(MODULE))] -- #[doc(hidden)] -- #[no_mangle] -- pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{ -- __init() -- }} -+ #[cfg(not(MODULE))] -+ #[doc(hidden)] -+ #[no_mangle] -+ pub extern \"C\" fn __{name}_exit() {{ -+ // SAFETY: -+ // - This function is inaccessible to the outside due to the double -+ // module wrapping it. It is called exactly once by the C side via its -+ // unique name, -+ // - furthermore it is only called after `__{name}_init` has returned `0` -+ // (which delegates to `__init`). -+ unsafe {{ __exit() }} -+ }} - -- #[cfg(not(MODULE))] -- #[doc(hidden)] -- #[no_mangle] -- pub extern \"C\" fn __{name}_exit() {{ -- __exit() -- }} -+ /// # Safety -+ /// -+ /// This function must only be called once. -+ unsafe fn __init() -> core::ffi::c_int {{ -+ match <{type_} as kernel::Module>::init(&super::super::THIS_MODULE) {{ -+ Ok(m) => {{ -+ // SAFETY: No data race, since `__MOD` can only be accessed by this -+ // module and there only `__init` and `__exit` access it. These -+ // functions are only called once and `__exit` cannot be called -+ // before or during `__init`. -+ unsafe {{ -+ __MOD = Some(m); -+ }} -+ return 0; -+ }} -+ Err(e) => {{ -+ return e.to_errno(); -+ }} -+ }} -+ }} - -- fn __init() -> core::ffi::c_int {{ -- match <{type_} as kernel::Module>::init(&THIS_MODULE) {{ -- Ok(m) => {{ -+ /// # Safety -+ /// -+ /// This function must -+ /// - only be called once, -+ /// - be called after `__init` has been called and returned `0`. -+ unsafe fn __exit() {{ -+ // SAFETY: No data race, since `__MOD` can only be accessed by this module -+ // and there only `__init` and `__exit` access it. These functions are only -+ // called once and `__init` was already called. - unsafe {{ -- __MOD = Some(m); -+ // Invokes `drop()` on `__MOD`, which should be used for cleanup. -+ __MOD = None; - }} -- return 0; -- }} -- Err(e) => {{ -- return e.to_errno(); - }} -- }} -- }} - -- fn __exit() {{ -- unsafe {{ -- // Invokes `drop()` on `__MOD`, which should be used for cleanup. -- __MOD = None; -+ {modinfo} - }} - }} -- -- {modinfo} - ", - type_ = info.type_, - name = info.name, -diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal -index b3a6aa8fbe8cb..1979913aff682 100644 ---- a/scripts/Makefile.modfinal -+++ b/scripts/Makefile.modfinal -@@ -23,7 +23,7 @@ modname = $(notdir $(@:.mod.o=)) - part-of-module = y - - quiet_cmd_cc_o_c = CC [M] $@ -- cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI) $(CFLAGS_GCOV), $(c_flags)) -c -o $@ $< -+ cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI) $(CFLAGS_GCOV) $(CFLAGS_KCSAN), $(c_flags)) -c -o $@ $< - - %.mod.o: %.mod.c FORCE - $(call if_changed_dep,cc_o_c) -diff --git a/security/keys/key.c b/security/keys/key.c -index 5f103b2713c64..35db23d05302e 100644 ---- a/security/keys/key.c -+++ b/security/keys/key.c -@@ -464,7 +464,8 @@ static int __key_instantiate_and_link(struct key *key, - if (authkey) - key_invalidate(authkey); - -- key_set_expiry(key, prep->expiry); -+ if (prep->expiry != TIME64_MAX) -+ key_set_expiry(key, prep->expiry); - } - } - -diff --git a/sound/hda/intel-sdw-acpi.c b/sound/hda/intel-sdw-acpi.c -index b57d72ea4503f..4e376994bf78b 100644 ---- a/sound/hda/intel-sdw-acpi.c -+++ b/sound/hda/intel-sdw-acpi.c -@@ -41,6 +41,8 @@ static bool is_link_enabled(struct fwnode_handle *fw_node, u8 idx) - "intel-quirk-mask", - &quirk_mask); - -+ fwnode_handle_put(link); -+ - if (quirk_mask & SDW_INTEL_QUIRK_MASK_BUS_DISABLE) - return false; - -diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c -index fe72e7d772412..dadeda7758cee 100644 ---- a/sound/pci/emu10k1/emu10k1.c -+++ b/sound/pci/emu10k1/emu10k1.c -@@ -189,8 +189,7 @@ static int snd_emu10k1_suspend(struct device *dev) - - emu->suspend = 1; - -- cancel_work_sync(&emu->emu1010.firmware_work); -- cancel_work_sync(&emu->emu1010.clock_work); -+ cancel_work_sync(&emu->emu1010.work); - - snd_ac97_suspend(emu->ac97); - -diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c -index de5c41e578e1f..ade90c7ecd922 100644 ---- a/sound/pci/emu10k1/emu10k1_main.c -+++ b/sound/pci/emu10k1/emu10k1_main.c -@@ -732,69 +732,67 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock, - return snd_emu1010_load_firmware_entry(emu, *fw); - } - --static void emu1010_firmware_work(struct work_struct *work) -+static void snd_emu1010_load_dock_firmware(struct snd_emu10k1 *emu) - { -- struct snd_emu10k1 *emu; -- u32 tmp, tmp2, reg; -+ u32 tmp, tmp2; - int err; - -- emu = container_of(work, struct snd_emu10k1, -- emu1010.firmware_work); -- if (emu->card->shutdown) -+ // The docking events clearly arrive prematurely - while the -+ // Dock's FPGA seems to be successfully programmed, the Dock -+ // fails to initialize subsequently if we don't give it some -+ // time to "warm up" here. -+ msleep(200); -+ -+ dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware\n"); -+ /* Return to Audio Dock programming mode */ -+ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, -+ EMU_HANA_FPGA_CONFIG_AUDIODOCK); -+ err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw); -+ if (err < 0) - return; --#ifdef CONFIG_PM_SLEEP -- if (emu->suspend) -+ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); -+ -+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp); -+ dev_dbg(emu->card->dev, "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp); -+ if ((tmp & 0x1f) != 0x15) { -+ /* FPGA failed to be programmed */ -+ dev_err(emu->card->dev, -+ "emu1010: Loading Audio Dock Firmware failed, reg = 0x%x\n", -+ tmp); - return; --#endif -+ } -+ dev_info(emu->card->dev, "emu1010: Audio Dock Firmware loaded\n"); -+ -+ snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); -+ snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); -+ dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2); -+ -+ /* Allow DLL to settle, to sync clocking between 1010 and Dock */ -+ msleep(10); -+} -+ -+static void emu1010_dock_event(struct snd_emu10k1 *emu) -+{ -+ u32 reg; -+ - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ - if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { - /* Audio Dock attached */ -- /* Return to Audio Dock programming mode */ -- dev_info(emu->card->dev, -- "emu1010: Loading Audio Dock Firmware\n"); -- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, -- EMU_HANA_FPGA_CONFIG_AUDIODOCK); -- err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw); -- if (err < 0) -- return; -- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); -- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp); -- dev_info(emu->card->dev, -- "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp); -- if ((tmp & 0x1f) != 0x15) { -- /* FPGA failed to be programmed */ -- dev_info(emu->card->dev, -- "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", -- tmp); -- return; -- } -- dev_info(emu->card->dev, -- "emu1010: Audio Dock Firmware loaded\n"); -- snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); -- snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); -- dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2); -- /* Sync clocking between 1010 and Dock */ -- /* Allow DLL to settle */ -- msleep(10); -+ snd_emu1010_load_dock_firmware(emu); - /* Unmute all. Default is muted after a firmware load */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); -+ } else if (!(reg & EMU_HANA_OPTION_DOCK_ONLINE)) { -+ /* Audio Dock removed */ -+ dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); -+ /* The hardware auto-mutes all, so we unmute again */ -+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); - } - } - --static void emu1010_clock_work(struct work_struct *work) -+static void emu1010_clock_event(struct snd_emu10k1 *emu) - { -- struct snd_emu10k1 *emu; - struct snd_ctl_elem_id id; - -- emu = container_of(work, struct snd_emu10k1, -- emu1010.clock_work); -- if (emu->card->shutdown) -- return; --#ifdef CONFIG_PM_SLEEP -- if (emu->suspend) -- return; --#endif -- - spin_lock_irq(&emu->reg_lock); - // This is the only thing that can actually happen. - emu->emu1010.clock_source = emu->emu1010.clock_fallback; -@@ -805,21 +803,40 @@ static void emu1010_clock_work(struct work_struct *work) - snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id); - } - --static void emu1010_interrupt(struct snd_emu10k1 *emu) -+static void emu1010_work(struct work_struct *work) - { -+ struct snd_emu10k1 *emu; - u32 sts; - -+ emu = container_of(work, struct snd_emu10k1, emu1010.work); -+ if (emu->card->shutdown) -+ return; -+#ifdef CONFIG_PM_SLEEP -+ if (emu->suspend) -+ return; -+#endif -+ - snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts); -- if (sts & EMU_HANA_IRQ_DOCK_LOST) { -- /* Audio Dock removed */ -- dev_info(emu->card->dev, "emu1010: Audio Dock detached\n"); -- /* The hardware auto-mutes all, so we unmute again */ -- snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); -- } else if (sts & EMU_HANA_IRQ_DOCK) { -- schedule_work(&emu->emu1010.firmware_work); -- } -+ -+ // The distinction of the IRQ status bits is unreliable, -+ // so we dispatch later based on option card status. -+ if (sts & (EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST)) -+ emu1010_dock_event(emu); -+ - if (sts & EMU_HANA_IRQ_WCLK_CHANGED) -- schedule_work(&emu->emu1010.clock_work); -+ emu1010_clock_event(emu); -+} -+ -+static void emu1010_interrupt(struct snd_emu10k1 *emu) -+{ -+ // We get an interrupt on each GPIO input pin change, but we -+ // care only about the ones triggered by the dedicated pin. -+ u16 sts = inw(emu->port + A_GPIO); -+ u16 bit = emu->card_capabilities->ca0108_chip ? 0x2000 : 0x8000; -+ if (!(sts & bit)) -+ return; -+ -+ schedule_work(&emu->emu1010.work); - } - - /* -@@ -889,7 +906,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg); - if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) -- schedule_work(&emu->emu1010.firmware_work); -+ snd_emu1010_load_dock_firmware(emu); - if (emu->card_capabilities->no_adat) { - emu->emu1010.optical_in = 0; /* IN_SPDIF */ - emu->emu1010.optical_out = 0; /* OUT_SPDIF */ -@@ -960,8 +977,7 @@ static void snd_emu10k1_free(struct snd_card *card) - /* Disable 48Volt power to Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); - } -- cancel_work_sync(&emu->emu1010.firmware_work); -- cancel_work_sync(&emu->emu1010.clock_work); -+ cancel_work_sync(&emu->emu1010.work); - release_firmware(emu->firmware); - release_firmware(emu->dock_fw); - snd_util_memhdr_free(emu->memhdr); -@@ -1540,8 +1556,7 @@ int snd_emu10k1_create(struct snd_card *card, - emu->irq = -1; - emu->synth = NULL; - emu->get_synth_voice = NULL; -- INIT_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work); -- INIT_WORK(&emu->emu1010.clock_work, emu1010_clock_work); -+ INIT_WORK(&emu->emu1010.work, emu1010_work); - /* read revision & serial */ - emu->revision = pci->revision; - pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); -diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c -index 057c207237cc2..47e404bde4241 100644 ---- a/sound/pci/hda/patch_realtek.c -+++ b/sound/pci/hda/patch_realtek.c -@@ -9826,6 +9826,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { - SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT), - SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT), - SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED), -+ SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), - SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO), - SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), - SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), -diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c -index 3c025dabaf7a4..1253695bebd86 100644 ---- a/sound/soc/codecs/wsa881x.c -+++ b/sound/soc/codecs/wsa881x.c -@@ -1155,6 +1155,7 @@ static int wsa881x_probe(struct sdw_slave *pdev, - pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0); - pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop; - pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; -+ pdev->prop.clk_stop_mode1 = true; - gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val); - - wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config); -diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c -index 45d0eb2a8e710..141255420c12b 100644 ---- a/sound/soc/intel/avs/topology.c -+++ b/sound/soc/intel/avs/topology.c -@@ -1412,6 +1412,8 @@ static int avs_widget_load(struct snd_soc_component *comp, int index, - if (!le32_to_cpu(dw->priv.size)) - return 0; - -+ w->no_wname_in_kcontrol_name = true; -+ - if (w->ignore_suspend && !AVS_S0IX_SUPPORTED) { - dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n"); - w->ignore_suspend = false; -diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig -index b93ea33739f29..6458d5dc4902f 100644 ---- a/sound/soc/meson/Kconfig -+++ b/sound/soc/meson/Kconfig -@@ -99,6 +99,7 @@ config SND_MESON_AXG_PDM - - config SND_MESON_CARD_UTILS - tristate -+ select SND_DYNAMIC_MINORS - - config SND_MESON_CODEC_GLUE - tristate -diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c -index f10c0c17863eb..b6f5b4572012d 100644 ---- a/sound/soc/meson/axg-card.c -+++ b/sound/soc/meson/axg-card.c -@@ -318,6 +318,7 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np, - - dai_link->cpus = cpu; - dai_link->num_cpus = 1; -+ dai_link->nonatomic = true; - - ret = meson_card_parse_dai(card, np, dai_link->cpus); - if (ret) -diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c -index bccfb770b3391..94b169a5493b5 100644 ---- a/sound/soc/meson/axg-fifo.c -+++ b/sound/soc/meson/axg-fifo.c -@@ -3,6 +3,7 @@ - // Copyright (c) 2018 BayLibre, SAS. - // Author: Jerome Brunet - -+#include - #include - #include - #include -@@ -145,8 +146,8 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component, - /* Enable irq if necessary */ - irq_en = runtime->no_period_wakeup ? 0 : FIFO_INT_COUNT_REPEAT; - regmap_update_bits(fifo->map, FIFO_CTRL0, -- CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), -- CTRL0_INT_EN(irq_en)); -+ CTRL0_INT_EN, -+ FIELD_PREP(CTRL0_INT_EN, irq_en)); - - return 0; - } -@@ -176,9 +177,9 @@ int axg_fifo_pcm_hw_free(struct snd_soc_component *component, - { - struct axg_fifo *fifo = axg_fifo_data(ss); - -- /* Disable the block count irq */ -+ /* Disable irqs */ - regmap_update_bits(fifo->map, FIFO_CTRL0, -- CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), 0); -+ CTRL0_INT_EN, 0); - - return 0; - } -@@ -187,13 +188,13 @@ EXPORT_SYMBOL_GPL(axg_fifo_pcm_hw_free); - static void axg_fifo_ack_irq(struct axg_fifo *fifo, u8 mask) - { - regmap_update_bits(fifo->map, FIFO_CTRL1, -- CTRL1_INT_CLR(FIFO_INT_MASK), -- CTRL1_INT_CLR(mask)); -+ CTRL1_INT_CLR, -+ FIELD_PREP(CTRL1_INT_CLR, mask)); - - /* Clear must also be cleared */ - regmap_update_bits(fifo->map, FIFO_CTRL1, -- CTRL1_INT_CLR(FIFO_INT_MASK), -- 0); -+ CTRL1_INT_CLR, -+ FIELD_PREP(CTRL1_INT_CLR, 0)); - } - - static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id) -@@ -203,18 +204,26 @@ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id) - unsigned int status; - - regmap_read(fifo->map, FIFO_STATUS1, &status); -+ status = FIELD_GET(STATUS1_INT_STS, status); -+ axg_fifo_ack_irq(fifo, status); - -- status = STATUS1_INT_STS(status) & FIFO_INT_MASK; -+ /* Use the thread to call period elapsed on nonatomic links */ - if (status & FIFO_INT_COUNT_REPEAT) -- snd_pcm_period_elapsed(ss); -- else -- dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n", -- status); -+ return IRQ_WAKE_THREAD; - -- /* Ack irqs */ -- axg_fifo_ack_irq(fifo, status); -+ dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n", -+ status); -+ -+ return IRQ_NONE; -+} -+ -+static irqreturn_t axg_fifo_pcm_irq_block_thread(int irq, void *dev_id) -+{ -+ struct snd_pcm_substream *ss = dev_id; -+ -+ snd_pcm_period_elapsed(ss); - -- return IRQ_RETVAL(status); -+ return IRQ_HANDLED; - } - - int axg_fifo_pcm_open(struct snd_soc_component *component, -@@ -242,8 +251,9 @@ int axg_fifo_pcm_open(struct snd_soc_component *component, - if (ret) - return ret; - -- ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0, -- dev_name(dev), ss); -+ ret = request_threaded_irq(fifo->irq, axg_fifo_pcm_irq_block, -+ axg_fifo_pcm_irq_block_thread, -+ IRQF_ONESHOT, dev_name(dev), ss); - if (ret) - return ret; - -@@ -254,15 +264,15 @@ int axg_fifo_pcm_open(struct snd_soc_component *component, - - /* Setup status2 so it reports the memory pointer */ - regmap_update_bits(fifo->map, FIFO_CTRL1, -- CTRL1_STATUS2_SEL_MASK, -- CTRL1_STATUS2_SEL(STATUS2_SEL_DDR_READ)); -+ CTRL1_STATUS2_SEL, -+ FIELD_PREP(CTRL1_STATUS2_SEL, STATUS2_SEL_DDR_READ)); - - /* Make sure the dma is initially disabled */ - __dma_enable(fifo, false); - - /* Disable irqs until params are ready */ - regmap_update_bits(fifo->map, FIFO_CTRL0, -- CTRL0_INT_EN(FIFO_INT_MASK), 0); -+ CTRL0_INT_EN, 0); - - /* Clear any pending interrupt */ - axg_fifo_ack_irq(fifo, FIFO_INT_MASK); -diff --git a/sound/soc/meson/axg-fifo.h b/sound/soc/meson/axg-fifo.h -index b63acd723c870..5b7d32c37991b 100644 ---- a/sound/soc/meson/axg-fifo.h -+++ b/sound/soc/meson/axg-fifo.h -@@ -42,21 +42,19 @@ struct snd_soc_pcm_runtime; - - #define FIFO_CTRL0 0x00 - #define CTRL0_DMA_EN BIT(31) --#define CTRL0_INT_EN(x) ((x) << 16) -+#define CTRL0_INT_EN GENMASK(23, 16) - #define CTRL0_SEL_MASK GENMASK(2, 0) - #define CTRL0_SEL_SHIFT 0 - #define FIFO_CTRL1 0x04 --#define CTRL1_INT_CLR(x) ((x) << 0) --#define CTRL1_STATUS2_SEL_MASK GENMASK(11, 8) --#define CTRL1_STATUS2_SEL(x) ((x) << 8) -+#define CTRL1_INT_CLR GENMASK(7, 0) -+#define CTRL1_STATUS2_SEL GENMASK(11, 8) - #define STATUS2_SEL_DDR_READ 0 --#define CTRL1_FRDDR_DEPTH_MASK GENMASK(31, 24) --#define CTRL1_FRDDR_DEPTH(x) ((x) << 24) -+#define CTRL1_FRDDR_DEPTH GENMASK(31, 24) - #define FIFO_START_ADDR 0x08 - #define FIFO_FINISH_ADDR 0x0c - #define FIFO_INT_ADDR 0x10 - #define FIFO_STATUS1 0x14 --#define STATUS1_INT_STS(x) ((x) << 0) -+#define STATUS1_INT_STS GENMASK(7, 0) - #define FIFO_STATUS2 0x18 - #define FIFO_INIT_ADDR 0x24 - #define FIFO_CTRL2 0x28 -diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c -index 8c166a5f338ce..747a900c0bb22 100644 ---- a/sound/soc/meson/axg-frddr.c -+++ b/sound/soc/meson/axg-frddr.c -@@ -7,6 +7,7 @@ - * This driver implements the frontend playback DAI of AXG and G12A based SoCs - */ - -+#include - #include - #include - #include -@@ -59,8 +60,8 @@ static int axg_frddr_dai_hw_params(struct snd_pcm_substream *substream, - /* Trim the FIFO depth if the period is small to improve latency */ - depth = min(period, fifo->depth); - val = (depth / AXG_FIFO_BURST) - 1; -- regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_FRDDR_DEPTH_MASK, -- CTRL1_FRDDR_DEPTH(val)); -+ regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_FRDDR_DEPTH, -+ FIELD_PREP(CTRL1_FRDDR_DEPTH, val)); - - return 0; - } -diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c -index 2cedbce738373..a71790908e178 100644 ---- a/sound/soc/meson/axg-tdm-interface.c -+++ b/sound/soc/meson/axg-tdm-interface.c -@@ -349,26 +349,31 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream, - return 0; - } - --static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream, -+static int axg_tdm_iface_trigger(struct snd_pcm_substream *substream, -+ int cmd, - struct snd_soc_dai *dai) - { -- struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream); -+ struct axg_tdm_stream *ts = -+ snd_soc_dai_get_dma_data(dai, substream); - -- /* Stop all attached formatters */ -- axg_tdm_stream_stop(ts); -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ axg_tdm_stream_start(ts); -+ break; -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ case SNDRV_PCM_TRIGGER_STOP: -+ axg_tdm_stream_stop(ts); -+ break; -+ default: -+ return -EINVAL; -+ } - - return 0; - } - --static int axg_tdm_iface_prepare(struct snd_pcm_substream *substream, -- struct snd_soc_dai *dai) --{ -- struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream); -- -- /* Force all attached formatters to update */ -- return axg_tdm_stream_reset(ts); --} -- - static int axg_tdm_iface_remove_dai(struct snd_soc_dai *dai) - { - int stream; -@@ -412,8 +417,7 @@ static const struct snd_soc_dai_ops axg_tdm_iface_ops = { - .set_fmt = axg_tdm_iface_set_fmt, - .startup = axg_tdm_iface_startup, - .hw_params = axg_tdm_iface_hw_params, -- .prepare = axg_tdm_iface_prepare, -- .hw_free = axg_tdm_iface_hw_free, -+ .trigger = axg_tdm_iface_trigger, - }; - - /* TDM Backend DAIs */ -diff --git a/sound/soc/meson/axg-toddr.c b/sound/soc/meson/axg-toddr.c -index 1a0be177b8fe7..972ad99f31be2 100644 ---- a/sound/soc/meson/axg-toddr.c -+++ b/sound/soc/meson/axg-toddr.c -@@ -5,6 +5,7 @@ - - /* This driver implements the frontend capture DAI of AXG based SoCs */ - -+#include - #include - #include - #include -@@ -19,12 +20,9 @@ - #define CTRL0_TODDR_EXT_SIGNED BIT(29) - #define CTRL0_TODDR_PP_MODE BIT(28) - #define CTRL0_TODDR_SYNC_CH BIT(27) --#define CTRL0_TODDR_TYPE_MASK GENMASK(15, 13) --#define CTRL0_TODDR_TYPE(x) ((x) << 13) --#define CTRL0_TODDR_MSB_POS_MASK GENMASK(12, 8) --#define CTRL0_TODDR_MSB_POS(x) ((x) << 8) --#define CTRL0_TODDR_LSB_POS_MASK GENMASK(7, 3) --#define CTRL0_TODDR_LSB_POS(x) ((x) << 3) -+#define CTRL0_TODDR_TYPE GENMASK(15, 13) -+#define CTRL0_TODDR_MSB_POS GENMASK(12, 8) -+#define CTRL0_TODDR_LSB_POS GENMASK(7, 3) - #define CTRL1_TODDR_FORCE_FINISH BIT(25) - #define CTRL1_SEL_SHIFT 28 - -@@ -76,12 +74,12 @@ static int axg_toddr_dai_hw_params(struct snd_pcm_substream *substream, - width = params_width(params); - - regmap_update_bits(fifo->map, FIFO_CTRL0, -- CTRL0_TODDR_TYPE_MASK | -- CTRL0_TODDR_MSB_POS_MASK | -- CTRL0_TODDR_LSB_POS_MASK, -- CTRL0_TODDR_TYPE(type) | -- CTRL0_TODDR_MSB_POS(TODDR_MSB_POS) | -- CTRL0_TODDR_LSB_POS(TODDR_MSB_POS - (width - 1))); -+ CTRL0_TODDR_TYPE | -+ CTRL0_TODDR_MSB_POS | -+ CTRL0_TODDR_LSB_POS, -+ FIELD_PREP(CTRL0_TODDR_TYPE, type) | -+ FIELD_PREP(CTRL0_TODDR_MSB_POS, TODDR_MSB_POS) | -+ FIELD_PREP(CTRL0_TODDR_LSB_POS, TODDR_MSB_POS - (width - 1))); - - return 0; - } -diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c -index 44f39a520bb39..e80a2a5ec56a1 100644 ---- a/sound/soc/sof/intel/hda-dsp.c -+++ b/sound/soc/sof/intel/hda-dsp.c -@@ -681,17 +681,27 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend) - struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; - const struct sof_intel_dsp_desc *chip = hda->desc; - struct hdac_bus *bus = sof_to_bus(sdev); -+ bool imr_lost = false; - int ret, j; - - /* -- * The memory used for IMR boot loses its content in deeper than S3 state -- * We must not try IMR boot on next power up (as it will fail). -- * -+ * The memory used for IMR boot loses its content in deeper than S3 -+ * state on CAVS platforms. -+ * On ACE platforms due to the system architecture the IMR content is -+ * lost at S3 state already, they are tailored for s2idle use. -+ * We must not try IMR boot on next power up in these cases as it will -+ * fail. -+ */ -+ if (sdev->system_suspend_target > SOF_SUSPEND_S3 || -+ (chip->hw_ip_version >= SOF_INTEL_ACE_1_0 && -+ sdev->system_suspend_target == SOF_SUSPEND_S3)) -+ imr_lost = true; -+ -+ /* - * In case of firmware crash or boot failure set the skip_imr_boot to true - * as well in order to try to re-load the firmware to do a 'cold' boot. - */ -- if (sdev->system_suspend_target > SOF_SUSPEND_S3 || -- sdev->fw_state == SOF_FW_CRASHED || -+ if (imr_lost || sdev->fw_state == SOF_FW_CRASHED || - sdev->fw_state == SOF_FW_BOOT_FAILED) - hda->skip_imr_boot = true; - -diff --git a/sound/soc/sof/intel/pci-lnl.c b/sound/soc/sof/intel/pci-lnl.c -index 1b12c280edb46..7ad7aa3c3461b 100644 ---- a/sound/soc/sof/intel/pci-lnl.c -+++ b/sound/soc/sof/intel/pci-lnl.c -@@ -35,6 +35,9 @@ static const struct sof_dev_desc lnl_desc = { - .default_fw_path = { - [SOF_INTEL_IPC4] = "intel/sof-ipc4/lnl", - }, -+ .default_lib_path = { -+ [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/lnl", -+ }, - .default_tplg_path = { - [SOF_INTEL_IPC4] = "intel/sof-ace-tplg", - }, -diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c -index a0ce7eb11de96..95bff466e8bdb 100644 ---- a/sound/soc/tegra/tegra186_dspk.c -+++ b/sound/soc/tegra/tegra186_dspk.c -@@ -1,8 +1,7 @@ - // SPDX-License-Identifier: GPL-2.0-only -+// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. - // - // tegra186_dspk.c - Tegra186 DSPK driver --// --// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. - - #include - #include -@@ -241,14 +240,14 @@ static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream, - return -EINVAL; - } - -- cif_conf.client_bits = TEGRA_ACIF_BITS_24; -- - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - cif_conf.audio_bits = TEGRA_ACIF_BITS_16; -+ cif_conf.client_bits = TEGRA_ACIF_BITS_16; - break; - case SNDRV_PCM_FORMAT_S32_LE: - cif_conf.audio_bits = TEGRA_ACIF_BITS_32; -+ cif_conf.client_bits = TEGRA_ACIF_BITS_24; - break; - default: - dev_err(dev, "unsupported format!\n"); -diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c -index 7e7d665a5504a..a5c2cca38d01a 100644 ---- a/sound/soc/ti/davinci-mcasp.c -+++ b/sound/soc/ti/davinci-mcasp.c -@@ -2418,12 +2418,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev) - - mcasp_reparent_fck(pdev); - -- ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, -- &davinci_mcasp_dai[mcasp->op_mode], 1); -- -- if (ret != 0) -- goto err; -- - ret = davinci_mcasp_get_dma_type(mcasp); - switch (ret) { - case PCM_EDMA: -@@ -2450,6 +2444,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev) - goto err; - } - -+ ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, -+ &davinci_mcasp_dai[mcasp->op_mode], 1); -+ -+ if (ret != 0) -+ goto err; -+ - no_audio: - ret = davinci_mcasp_init_gpiochip(mcasp); - if (ret) { -diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c -index b67617b68e509..f4437015d43a7 100644 ---- a/sound/usb/line6/driver.c -+++ b/sound/usb/line6/driver.c -@@ -202,7 +202,7 @@ int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer, - struct urb *urb; - - /* create message: */ -- msg = kmalloc(sizeof(struct message), GFP_ATOMIC); -+ msg = kzalloc(sizeof(struct message), GFP_ATOMIC); - if (msg == NULL) - return -ENOMEM; - -@@ -688,7 +688,7 @@ static int line6_init_cap_control(struct usb_line6 *line6) - int ret; - - /* initialize USB buffers: */ -- line6->buffer_listen = kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL); -+ line6->buffer_listen = kzalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL); - if (!line6->buffer_listen) - return -ENOMEM; - -@@ -697,7 +697,7 @@ static int line6_init_cap_control(struct usb_line6 *line6) - return -ENOMEM; - - if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { -- line6->buffer_message = kmalloc(LINE6_MIDI_MESSAGE_MAXLEN, GFP_KERNEL); -+ line6->buffer_message = kzalloc(LINE6_MIDI_MESSAGE_MAXLEN, GFP_KERNEL); - if (!line6->buffer_message) - return -ENOMEM; - -diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h -index 4b0673bf52c2e..07cfad817d539 100644 ---- a/tools/include/linux/kernel.h -+++ b/tools/include/linux/kernel.h -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - #include - -diff --git a/tools/include/linux/mm.h b/tools/include/linux/mm.h -index f3c82ab5b14cd..7d73da0980473 100644 ---- a/tools/include/linux/mm.h -+++ b/tools/include/linux/mm.h -@@ -37,4 +37,9 @@ static inline void totalram_pages_add(long count) - { - } - -+static inline int early_pfn_to_nid(unsigned long pfn) -+{ -+ return 0; -+} -+ - #endif -diff --git a/tools/include/linux/panic.h b/tools/include/linux/panic.h -new file mode 100644 -index 0000000000000..9c8f17a41ce8e ---- /dev/null -+++ b/tools/include/linux/panic.h -@@ -0,0 +1,19 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef _TOOLS_LINUX_PANIC_H -+#define _TOOLS_LINUX_PANIC_H -+ -+#include -+#include -+#include -+ -+static inline void panic(const char *fmt, ...) -+{ -+ va_list argp; -+ -+ va_start(argp, fmt); -+ vfprintf(stderr, fmt, argp); -+ va_end(argp); -+ exit(-1); -+} -+ -+#endif -diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 -index 8f08c3fd498d5..1ba6340d3b3da 100644 ---- a/tools/power/x86/turbostat/turbostat.8 -+++ b/tools/power/x86/turbostat/turbostat.8 -@@ -370,7 +370,7 @@ below the processor's base frequency. - - Busy% = MPERF_delta/TSC_delta - --Bzy_MHz = TSC_delta/APERF_delta/MPERF_delta/measurement_interval -+Bzy_MHz = TSC_delta*APERF_delta/MPERF_delta/measurement_interval - - Note that these calculations depend on TSC_delta, so they - are not reliable during intervals when TSC_MHz is not running at the base frequency. -diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c -index 785de89077de0..ffa964ddbacef 100644 ---- a/tools/power/x86/turbostat/turbostat.c -+++ b/tools/power/x86/turbostat/turbostat.c -@@ -53,6 +53,8 @@ - #define NAME_BYTES 20 - #define PATH_BYTES 128 - -+#define MAX_NOFILE 0x8000 -+ - enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE }; - enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC }; - enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT }; -@@ -1811,9 +1813,10 @@ int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) - average.packages.rapl_dram_perf_status += p->rapl_dram_perf_status; - - for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { -- if (mp->format == FORMAT_RAW) -- continue; -- average.packages.counter[i] += p->counter[i]; -+ if ((mp->format == FORMAT_RAW) && (topo.num_packages == 0)) -+ average.packages.counter[i] = p->counter[i]; -+ else -+ average.packages.counter[i] += p->counter[i]; - } - return 0; - } -@@ -1966,7 +1969,7 @@ unsigned long long get_uncore_mhz(int package, int die) - { - char path[128]; - -- sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/current_freq_khz", package, -+ sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/current_freq_khz", package, - die); - - return (snapshot_sysfs_counter(path) / 1000); -@@ -5476,7 +5479,8 @@ void print_dev_latency(void) - - fd = open(path, O_RDONLY); - if (fd < 0) { -- warnx("capget(CAP_SYS_ADMIN) failed, try \"# setcap cap_sys_admin=ep %s\"", progname); -+ if (debug) -+ warnx("Read %s failed", path); - return; - } - -@@ -5515,6 +5519,7 @@ void process_cpuid() - unsigned int eax, ebx, ecx, edx; - unsigned int fms, family, model, stepping, ecx_flags, edx_flags; - unsigned long long ucode_patch = 0; -+ bool ucode_patch_valid = false; - - eax = ebx = ecx = edx = 0; - -@@ -5544,6 +5549,8 @@ void process_cpuid() - - if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) - warnx("get_msr(UCODE)"); -+ else -+ ucode_patch_valid = true; - - /* - * check max extended function levels of CPUID. -@@ -5554,9 +5561,12 @@ void process_cpuid() - __cpuid(0x80000000, max_extended_level, ebx, ecx, edx); - - if (!quiet) { -- fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d) microcode 0x%x\n", -- family, model, stepping, family, model, stepping, -- (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF)); -+ fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d)", -+ family, model, stepping, family, model, stepping); -+ if (ucode_patch_valid) -+ fprintf(outf, " microcode 0x%x", (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF)); -+ fputc('\n', outf); -+ - fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level); - fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n", - ecx_flags & (1 << 0) ? "SSE3" : "-", -@@ -6718,6 +6728,22 @@ void cmdline(int argc, char **argv) - } - } - -+void set_rlimit(void) -+{ -+ struct rlimit limit; -+ -+ if (getrlimit(RLIMIT_NOFILE, &limit) < 0) -+ err(1, "Failed to get rlimit"); -+ -+ if (limit.rlim_max < MAX_NOFILE) -+ limit.rlim_max = MAX_NOFILE; -+ if (limit.rlim_cur < MAX_NOFILE) -+ limit.rlim_cur = MAX_NOFILE; -+ -+ if (setrlimit(RLIMIT_NOFILE, &limit) < 0) -+ err(1, "Failed to set rlimit"); -+} -+ - int main(int argc, char **argv) - { - outf = stderr; -@@ -6730,6 +6756,9 @@ int main(int argc, char **argv) - - probe_sysfs(); - -+ if (!getuid()) -+ set_rlimit(); -+ - turbostat_init(); - - msr_sum_record(); -diff --git a/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c b/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c -index d2d9e965eba59..f79815b7e951b 100644 ---- a/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c -+++ b/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c -@@ -2,6 +2,7 @@ - /* Copyright (c) 2021 Facebook */ - - #include -+#include - #include - #include "bloom_filter_map.skel.h" - -@@ -21,6 +22,11 @@ static void test_fail_cases(void) - if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid value size 0")) - close(fd); - -+ /* Invalid value size: too big */ -+ fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, INT32_MAX, 100, NULL); -+ if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid value too large")) -+ close(fd); -+ - /* Invalid max entries size */ - fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(value), 0, NULL); - if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid max entries size")) -diff --git a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c -index dbe06aeaa2b27..af3c31f82a8ae 100644 ---- a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c -+++ b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c -@@ -24,7 +24,6 @@ - - #include "test_progs.h" - #include "network_helpers.h" --#include "netlink_helpers.h" - #include "test_tc_neigh_fib.skel.h" - #include "test_tc_neigh.skel.h" - #include "test_tc_peer.skel.h" -@@ -113,7 +112,6 @@ static void netns_setup_namespaces_nofail(const char *verb) - - enum dev_mode { - MODE_VETH, -- MODE_NETKIT, - }; - - struct netns_setup_result { -@@ -144,52 +142,11 @@ static int get_ifaddr(const char *name, char *ifaddr) - return 0; - } - --static int create_netkit(int mode, char *prim, char *peer) --{ -- struct rtattr *linkinfo, *data, *peer_info; -- struct rtnl_handle rth = { .fd = -1 }; -- const char *type = "netkit"; -- struct { -- struct nlmsghdr n; -- struct ifinfomsg i; -- char buf[1024]; -- } req = {}; -- int err; -- -- err = rtnl_open(&rth, 0); -- if (!ASSERT_OK(err, "open_rtnetlink")) -- return err; -- -- memset(&req, 0, sizeof(req)); -- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); -- req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; -- req.n.nlmsg_type = RTM_NEWLINK; -- req.i.ifi_family = AF_UNSPEC; -- -- addattr_l(&req.n, sizeof(req), IFLA_IFNAME, prim, strlen(prim)); -- linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO); -- addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type, strlen(type)); -- data = addattr_nest(&req.n, sizeof(req), IFLA_INFO_DATA); -- addattr32(&req.n, sizeof(req), IFLA_NETKIT_MODE, mode); -- peer_info = addattr_nest(&req.n, sizeof(req), IFLA_NETKIT_PEER_INFO); -- req.n.nlmsg_len += sizeof(struct ifinfomsg); -- addattr_l(&req.n, sizeof(req), IFLA_IFNAME, peer, strlen(peer)); -- addattr_nest_end(&req.n, peer_info); -- addattr_nest_end(&req.n, data); -- addattr_nest_end(&req.n, linkinfo); -- -- err = rtnl_talk(&rth, &req.n, NULL); -- ASSERT_OK(err, "talk_rtnetlink"); -- rtnl_close(&rth); -- return err; --} -- - static int netns_setup_links_and_routes(struct netns_setup_result *result) - { - struct nstoken *nstoken = NULL; - char src_fwd_addr[IFADDR_STR_LEN+1] = {}; - char src_addr[IFADDR_STR_LEN + 1] = {}; -- int err; - - if (result->dev_mode == MODE_VETH) { - SYS(fail, "ip link add src type veth peer name src_fwd"); -@@ -197,13 +154,6 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result) - - SYS(fail, "ip link set dst_fwd address " MAC_DST_FWD); - SYS(fail, "ip link set dst address " MAC_DST); -- } else if (result->dev_mode == MODE_NETKIT) { -- err = create_netkit(NETKIT_L3, "src", "src_fwd"); -- if (!ASSERT_OK(err, "create_ifindex_src")) -- goto fail; -- err = create_netkit(NETKIT_L3, "dst", "dst_fwd"); -- if (!ASSERT_OK(err, "create_ifindex_dst")) -- goto fail; - } - - if (get_ifaddr("src_fwd", src_fwd_addr)) -@@ -1266,9 +1216,7 @@ static void *test_tc_redirect_run_tests(void *arg) - netns_setup_namespaces_nofail("delete"); - - RUN_TEST(tc_redirect_peer, MODE_VETH); -- RUN_TEST(tc_redirect_peer, MODE_NETKIT); - RUN_TEST(tc_redirect_peer_l3, MODE_VETH); -- RUN_TEST(tc_redirect_peer_l3, MODE_NETKIT); - RUN_TEST(tc_redirect_neigh, MODE_VETH); - RUN_TEST(tc_redirect_neigh_fib, MODE_VETH); - RUN_TEST(tc_redirect_dtime, MODE_VETH); -diff --git a/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc b/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc -index 2de7c61d1ae30..3f74c09c56b62 100644 ---- a/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc -+++ b/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc -@@ -24,7 +24,7 @@ echo 0 > events/enable - echo "Get the most frequently calling function" - sample_events - --target_func=`cut -d: -f3 trace | sed 's/call_site=\([^+]*\)+0x.*/\1/' | sort | uniq -c | sort | tail -n 1 | sed 's/^[ 0-9]*//'` -+target_func=`cat trace | grep -o 'call_site=\([^+]*\)' | sed 's/call_site=//' | sort | uniq -c | sort | tail -n 1 | sed 's/^[ 0-9]*//'` - if [ -z "$target_func" ]; then - exit_fail - fi -diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile -index 6a9fc5693145f..292359a542429 100644 ---- a/tools/testing/selftests/mm/Makefile -+++ b/tools/testing/selftests/mm/Makefile -@@ -12,7 +12,7 @@ uname_M := $(shell uname -m 2>/dev/null || echo not) - else - uname_M := $(shell echo $(CROSS_COMPILE) | grep -o '^[a-z0-9]\+') - endif --ARCH ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/' -e 's/ppc64.*/ppc64/') -+ARCH ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/' -e 's/ppc64.*/powerpc/') - endif - - # Without this, failed build products remain, with up-to-date timestamps, -@@ -95,13 +95,13 @@ TEST_GEN_FILES += $(BINARIES_64) - endif - else - --ifneq (,$(findstring $(ARCH),ppc64)) -+ifneq (,$(findstring $(ARCH),powerpc)) - TEST_GEN_FILES += protection_keys - endif - - endif - --ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 ppc64 riscv64 s390x sparc64 x86_64)) -+ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 powerpc riscv64 s390x sparc64 x86_64)) - TEST_GEN_FILES += va_high_addr_switch - TEST_GEN_FILES += virtual_address_range - TEST_GEN_FILES += write_to_hugetlbfs -diff --git a/tools/testing/selftests/net/test_bridge_neigh_suppress.sh b/tools/testing/selftests/net/test_bridge_neigh_suppress.sh -index d80f2cd87614c..02b986c9c247d 100755 ---- a/tools/testing/selftests/net/test_bridge_neigh_suppress.sh -+++ b/tools/testing/selftests/net/test_bridge_neigh_suppress.sh -@@ -45,9 +45,8 @@ - # | sw1 | | sw2 | - # +------------------------------------+ +------------------------------------+ - -+source lib.sh - ret=0 --# Kselftest framework requirement - SKIP code is 4. --ksft_skip=4 - - # All tests in this script. Can be overridden with -t option. - TESTS=" -@@ -140,9 +139,6 @@ setup_topo_ns() - { - local ns=$1; shift - -- ip netns add $ns -- ip -n $ns link set dev lo up -- - ip netns exec $ns sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1 - ip netns exec $ns sysctl -qw net.ipv6.conf.default.ignore_routes_with_linkdown=1 - ip netns exec $ns sysctl -qw net.ipv6.conf.all.accept_dad=0 -@@ -153,21 +149,14 @@ setup_topo() - { - local ns - -- for ns in h1 h2 sw1 sw2; do -+ setup_ns h1 h2 sw1 sw2 -+ for ns in $h1 $h2 $sw1 $sw2; do - setup_topo_ns $ns - done - -- ip link add name veth0 type veth peer name veth1 -- ip link set dev veth0 netns h1 name eth0 -- ip link set dev veth1 netns sw1 name swp1 -- -- ip link add name veth0 type veth peer name veth1 -- ip link set dev veth0 netns sw1 name veth0 -- ip link set dev veth1 netns sw2 name veth0 -- -- ip link add name veth0 type veth peer name veth1 -- ip link set dev veth0 netns h2 name eth0 -- ip link set dev veth1 netns sw2 name swp1 -+ ip -n $h1 link add name eth0 type veth peer name swp1 netns $sw1 -+ ip -n $sw1 link add name veth0 type veth peer name veth0 netns $sw2 -+ ip -n $h2 link add name eth0 type veth peer name swp1 netns $sw2 - } - - setup_host_common() -@@ -190,7 +179,7 @@ setup_host_common() - - setup_h1() - { -- local ns=h1 -+ local ns=$h1 - local v4addr1=192.0.2.1/28 - local v4addr2=192.0.2.17/28 - local v6addr1=2001:db8:1::1/64 -@@ -201,7 +190,7 @@ setup_h1() - - setup_h2() - { -- local ns=h2 -+ local ns=$h2 - local v4addr1=192.0.2.2/28 - local v4addr2=192.0.2.18/28 - local v6addr1=2001:db8:1::2/64 -@@ -254,7 +243,7 @@ setup_sw_common() - - setup_sw1() - { -- local ns=sw1 -+ local ns=$sw1 - local local_addr=192.0.2.33 - local remote_addr=192.0.2.34 - local veth_addr=192.0.2.49 -@@ -265,7 +254,7 @@ setup_sw1() - - setup_sw2() - { -- local ns=sw2 -+ local ns=$sw2 - local local_addr=192.0.2.34 - local remote_addr=192.0.2.33 - local veth_addr=192.0.2.50 -@@ -291,11 +280,7 @@ setup() - - cleanup() - { -- local ns -- -- for ns in h1 h2 sw1 sw2; do -- ip netns del $ns &> /dev/null -- done -+ cleanup_ns $h1 $h2 $sw1 $sw2 - } - - ################################################################################ -@@ -312,80 +297,80 @@ neigh_suppress_arp_common() - echo "Per-port ARP suppression - VLAN $vid" - echo "----------------------------------" - -- run_cmd "tc -n sw1 qdisc replace dev vx0 clsact" -- run_cmd "tc -n sw1 filter replace dev vx0 egress pref 1 handle 101 proto 0x0806 flower indev swp1 arp_tip $tip arp_sip $sip arp_op request action pass" -+ run_cmd "tc -n $sw1 qdisc replace dev vx0 clsact" -+ run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 101 proto 0x0806 flower indev swp1 arp_tip $tip arp_sip $sip arp_op request action pass" - - # Initial state - check that ARP requests are not suppressed and that - # ARP replies are received. -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" - log_test $? 0 "arping" -- tc_check_packets sw1 "dev vx0 egress" 101 1 -+ tc_check_packets $sw1 "dev vx0 egress" 101 1 - log_test $? 0 "ARP suppression" - - # Enable neighbor suppression and check that nothing changes compared - # to the initial state. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_suppress on" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" - log_test $? 0 "\"neigh_suppress\" is on" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" - log_test $? 0 "arping" -- tc_check_packets sw1 "dev vx0 egress" 101 2 -+ tc_check_packets $sw1 "dev vx0 egress" 101 2 - log_test $? 0 "ARP suppression" - - # Install an FDB entry for the remote host and check that nothing - # changes compared to the initial state. -- h2_mac=$(ip -n h2 -j -p link show eth0.$vid | jq -r '.[]["address"]') -- run_cmd "bridge -n sw1 fdb replace $h2_mac dev vx0 master static vlan $vid" -+ h2_mac=$(ip -n $h2 -j -p link show eth0.$vid | jq -r '.[]["address"]') -+ run_cmd "bridge -n $sw1 fdb replace $h2_mac dev vx0 master static vlan $vid" - log_test $? 0 "FDB entry installation" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" - log_test $? 0 "arping" -- tc_check_packets sw1 "dev vx0 egress" 101 3 -+ tc_check_packets $sw1 "dev vx0 egress" 101 3 - log_test $? 0 "ARP suppression" - - # Install a neighbor on the matching SVI interface and check that ARP - # requests are suppressed. -- run_cmd "ip -n sw1 neigh replace $tip lladdr $h2_mac nud permanent dev br0.$vid" -+ run_cmd "ip -n $sw1 neigh replace $tip lladdr $h2_mac nud permanent dev br0.$vid" - log_test $? 0 "Neighbor entry installation" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" - log_test $? 0 "arping" -- tc_check_packets sw1 "dev vx0 egress" 101 3 -+ tc_check_packets $sw1 "dev vx0 egress" 101 3 - log_test $? 0 "ARP suppression" - - # Take the second host down and check that ARP requests are suppressed - # and that ARP replies are received. -- run_cmd "ip -n h2 link set dev eth0.$vid down" -+ run_cmd "ip -n $h2 link set dev eth0.$vid down" - log_test $? 0 "H2 down" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" - log_test $? 0 "arping" -- tc_check_packets sw1 "dev vx0 egress" 101 3 -+ tc_check_packets $sw1 "dev vx0 egress" 101 3 - log_test $? 0 "ARP suppression" - -- run_cmd "ip -n h2 link set dev eth0.$vid up" -+ run_cmd "ip -n $h2 link set dev eth0.$vid up" - log_test $? 0 "H2 up" - - # Disable neighbor suppression and check that ARP requests are no - # longer suppressed. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_suppress off" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_suppress off\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress off" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress off\"" - log_test $? 0 "\"neigh_suppress\" is off" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" - log_test $? 0 "arping" -- tc_check_packets sw1 "dev vx0 egress" 101 4 -+ tc_check_packets $sw1 "dev vx0 egress" 101 4 - log_test $? 0 "ARP suppression" - - # Take the second host down and check that ARP requests are not - # suppressed and that ARP replies are not received. -- run_cmd "ip -n h2 link set dev eth0.$vid down" -+ run_cmd "ip -n $h2 link set dev eth0.$vid down" - log_test $? 0 "H2 down" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip -I eth0.$vid $tip" - log_test $? 1 "arping" -- tc_check_packets sw1 "dev vx0 egress" 101 5 -+ tc_check_packets $sw1 "dev vx0 egress" 101 5 - log_test $? 0 "ARP suppression" - } - -@@ -415,80 +400,80 @@ neigh_suppress_ns_common() - echo "Per-port NS suppression - VLAN $vid" - echo "---------------------------------" - -- run_cmd "tc -n sw1 qdisc replace dev vx0 clsact" -- run_cmd "tc -n sw1 filter replace dev vx0 egress pref 1 handle 101 proto ipv6 flower indev swp1 ip_proto icmpv6 dst_ip $maddr src_ip $saddr type 135 code 0 action pass" -+ run_cmd "tc -n $sw1 qdisc replace dev vx0 clsact" -+ run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 101 proto ipv6 flower indev swp1 ip_proto icmpv6 dst_ip $maddr src_ip $saddr type 135 code 0 action pass" - - # Initial state - check that NS messages are not suppressed and that ND - # messages are received. -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" - log_test $? 0 "ndisc6" -- tc_check_packets sw1 "dev vx0 egress" 101 1 -+ tc_check_packets $sw1 "dev vx0 egress" 101 1 - log_test $? 0 "NS suppression" - - # Enable neighbor suppression and check that nothing changes compared - # to the initial state. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_suppress on" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" - log_test $? 0 "\"neigh_suppress\" is on" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" - log_test $? 0 "ndisc6" -- tc_check_packets sw1 "dev vx0 egress" 101 2 -+ tc_check_packets $sw1 "dev vx0 egress" 101 2 - log_test $? 0 "NS suppression" - - # Install an FDB entry for the remote host and check that nothing - # changes compared to the initial state. -- h2_mac=$(ip -n h2 -j -p link show eth0.$vid | jq -r '.[]["address"]') -- run_cmd "bridge -n sw1 fdb replace $h2_mac dev vx0 master static vlan $vid" -+ h2_mac=$(ip -n $h2 -j -p link show eth0.$vid | jq -r '.[]["address"]') -+ run_cmd "bridge -n $sw1 fdb replace $h2_mac dev vx0 master static vlan $vid" - log_test $? 0 "FDB entry installation" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" - log_test $? 0 "ndisc6" -- tc_check_packets sw1 "dev vx0 egress" 101 3 -+ tc_check_packets $sw1 "dev vx0 egress" 101 3 - log_test $? 0 "NS suppression" - - # Install a neighbor on the matching SVI interface and check that NS - # messages are suppressed. -- run_cmd "ip -n sw1 neigh replace $daddr lladdr $h2_mac nud permanent dev br0.$vid" -+ run_cmd "ip -n $sw1 neigh replace $daddr lladdr $h2_mac nud permanent dev br0.$vid" - log_test $? 0 "Neighbor entry installation" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" - log_test $? 0 "ndisc6" -- tc_check_packets sw1 "dev vx0 egress" 101 3 -+ tc_check_packets $sw1 "dev vx0 egress" 101 3 - log_test $? 0 "NS suppression" - - # Take the second host down and check that NS messages are suppressed - # and that ND messages are received. -- run_cmd "ip -n h2 link set dev eth0.$vid down" -+ run_cmd "ip -n $h2 link set dev eth0.$vid down" - log_test $? 0 "H2 down" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" - log_test $? 0 "ndisc6" -- tc_check_packets sw1 "dev vx0 egress" 101 3 -+ tc_check_packets $sw1 "dev vx0 egress" 101 3 - log_test $? 0 "NS suppression" - -- run_cmd "ip -n h2 link set dev eth0.$vid up" -+ run_cmd "ip -n $h2 link set dev eth0.$vid up" - log_test $? 0 "H2 up" - - # Disable neighbor suppression and check that NS messages are no longer - # suppressed. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_suppress off" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_suppress off\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress off" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress off\"" - log_test $? 0 "\"neigh_suppress\" is off" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" - log_test $? 0 "ndisc6" -- tc_check_packets sw1 "dev vx0 egress" 101 4 -+ tc_check_packets $sw1 "dev vx0 egress" 101 4 - log_test $? 0 "NS suppression" - - # Take the second host down and check that NS messages are not - # suppressed and that ND messages are not received. -- run_cmd "ip -n h2 link set dev eth0.$vid down" -+ run_cmd "ip -n $h2 link set dev eth0.$vid down" - log_test $? 0 "H2 down" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr -w 5000 $daddr eth0.$vid" - log_test $? 2 "ndisc6" -- tc_check_packets sw1 "dev vx0 egress" 101 5 -+ tc_check_packets $sw1 "dev vx0 egress" 101 5 - log_test $? 0 "NS suppression" - } - -@@ -524,118 +509,118 @@ neigh_vlan_suppress_arp() - echo "Per-{Port, VLAN} ARP suppression" - echo "--------------------------------" - -- run_cmd "tc -n sw1 qdisc replace dev vx0 clsact" -- run_cmd "tc -n sw1 filter replace dev vx0 egress pref 1 handle 101 proto 0x0806 flower indev swp1 arp_tip $tip1 arp_sip $sip1 arp_op request action pass" -- run_cmd "tc -n sw1 filter replace dev vx0 egress pref 1 handle 102 proto 0x0806 flower indev swp1 arp_tip $tip2 arp_sip $sip2 arp_op request action pass" -+ run_cmd "tc -n $sw1 qdisc replace dev vx0 clsact" -+ run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 101 proto 0x0806 flower indev swp1 arp_tip $tip1 arp_sip $sip1 arp_op request action pass" -+ run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 102 proto 0x0806 flower indev swp1 arp_tip $tip2 arp_sip $sip2 arp_op request action pass" - -- h2_mac1=$(ip -n h2 -j -p link show eth0.$vid1 | jq -r '.[]["address"]') -- h2_mac2=$(ip -n h2 -j -p link show eth0.$vid2 | jq -r '.[]["address"]') -- run_cmd "bridge -n sw1 fdb replace $h2_mac1 dev vx0 master static vlan $vid1" -- run_cmd "bridge -n sw1 fdb replace $h2_mac2 dev vx0 master static vlan $vid2" -- run_cmd "ip -n sw1 neigh replace $tip1 lladdr $h2_mac1 nud permanent dev br0.$vid1" -- run_cmd "ip -n sw1 neigh replace $tip2 lladdr $h2_mac2 nud permanent dev br0.$vid2" -+ h2_mac1=$(ip -n $h2 -j -p link show eth0.$vid1 | jq -r '.[]["address"]') -+ h2_mac2=$(ip -n $h2 -j -p link show eth0.$vid2 | jq -r '.[]["address"]') -+ run_cmd "bridge -n $sw1 fdb replace $h2_mac1 dev vx0 master static vlan $vid1" -+ run_cmd "bridge -n $sw1 fdb replace $h2_mac2 dev vx0 master static vlan $vid2" -+ run_cmd "ip -n $sw1 neigh replace $tip1 lladdr $h2_mac1 nud permanent dev br0.$vid1" -+ run_cmd "ip -n $sw1 neigh replace $tip2 lladdr $h2_mac2 nud permanent dev br0.$vid2" - - # Enable per-{Port, VLAN} neighbor suppression and check that ARP - # requests are not suppressed and that ARP replies are received. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_vlan_suppress on" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress on\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_vlan_suppress on" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress on\"" - log_test $? 0 "\"neigh_vlan_suppress\" is on" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" - log_test $? 0 "arping (VLAN $vid1)" -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" - log_test $? 0 "arping (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 1 -+ tc_check_packets $sw1 "dev vx0 egress" 101 1 - log_test $? 0 "ARP suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 1 -+ tc_check_packets $sw1 "dev vx0 egress" 102 1 - log_test $? 0 "ARP suppression (VLAN $vid2)" - - # Enable neighbor suppression on VLAN 10 and check that only on this - # VLAN ARP requests are suppressed. -- run_cmd "bridge -n sw1 vlan set vid $vid1 dev vx0 neigh_suppress on" -- run_cmd "bridge -n sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress on\"" -+ run_cmd "bridge -n $sw1 vlan set vid $vid1 dev vx0 neigh_suppress on" -+ run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress on\"" - log_test $? 0 "\"neigh_suppress\" is on (VLAN $vid1)" -- run_cmd "bridge -n sw1 -d vlan show dev vx0 vid $vid2 | grep \"neigh_suppress off\"" -+ run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid2 | grep \"neigh_suppress off\"" - log_test $? 0 "\"neigh_suppress\" is off (VLAN $vid2)" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" - log_test $? 0 "arping (VLAN $vid1)" -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" - log_test $? 0 "arping (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 1 -+ tc_check_packets $sw1 "dev vx0 egress" 101 1 - log_test $? 0 "ARP suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 2 -+ tc_check_packets $sw1 "dev vx0 egress" 102 2 - log_test $? 0 "ARP suppression (VLAN $vid2)" - - # Enable neighbor suppression on the port and check that it has no - # effect compared to previous state. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_suppress on" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" - log_test $? 0 "\"neigh_suppress\" is on" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" - log_test $? 0 "arping (VLAN $vid1)" -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" - log_test $? 0 "arping (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 1 -+ tc_check_packets $sw1 "dev vx0 egress" 101 1 - log_test $? 0 "ARP suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 3 -+ tc_check_packets $sw1 "dev vx0 egress" 102 3 - log_test $? 0 "ARP suppression (VLAN $vid2)" - - # Disable neighbor suppression on the port and check that it has no - # effect compared to previous state. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_suppress off" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_suppress off\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress off" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress off\"" - log_test $? 0 "\"neigh_suppress\" is off" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" - log_test $? 0 "arping (VLAN $vid1)" -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" - log_test $? 0 "arping (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 1 -+ tc_check_packets $sw1 "dev vx0 egress" 101 1 - log_test $? 0 "ARP suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 4 -+ tc_check_packets $sw1 "dev vx0 egress" 102 4 - log_test $? 0 "ARP suppression (VLAN $vid2)" - - # Disable neighbor suppression on VLAN 10 and check that ARP requests - # are no longer suppressed on this VLAN. -- run_cmd "bridge -n sw1 vlan set vid $vid1 dev vx0 neigh_suppress off" -- run_cmd "bridge -n sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress off\"" -+ run_cmd "bridge -n $sw1 vlan set vid $vid1 dev vx0 neigh_suppress off" -+ run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress off\"" - log_test $? 0 "\"neigh_suppress\" is off (VLAN $vid1)" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" - log_test $? 0 "arping (VLAN $vid1)" -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" - log_test $? 0 "arping (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 2 -+ tc_check_packets $sw1 "dev vx0 egress" 101 2 - log_test $? 0 "ARP suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 5 -+ tc_check_packets $sw1 "dev vx0 egress" 102 5 - log_test $? 0 "ARP suppression (VLAN $vid2)" - - # Disable per-{Port, VLAN} neighbor suppression, enable neighbor - # suppression on the port and check that on both VLANs ARP requests are - # suppressed. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_vlan_suppress off" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress off\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_vlan_suppress off" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress off\"" - log_test $? 0 "\"neigh_vlan_suppress\" is off" - -- run_cmd "bridge -n sw1 link set dev vx0 neigh_suppress on" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" - log_test $? 0 "\"neigh_suppress\" is on" - -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip1 -I eth0.$vid1 $tip1" - log_test $? 0 "arping (VLAN $vid1)" -- run_cmd "ip netns exec h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" -+ run_cmd "ip netns exec $h1 arping -q -b -c 1 -w 5 -s $sip2 -I eth0.$vid2 $tip2" - log_test $? 0 "arping (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 2 -+ tc_check_packets $sw1 "dev vx0 egress" 101 2 - log_test $? 0 "ARP suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 5 -+ tc_check_packets $sw1 "dev vx0 egress" 102 5 - log_test $? 0 "ARP suppression (VLAN $vid2)" - } - -@@ -655,118 +640,118 @@ neigh_vlan_suppress_ns() - echo "Per-{Port, VLAN} NS suppression" - echo "-------------------------------" - -- run_cmd "tc -n sw1 qdisc replace dev vx0 clsact" -- run_cmd "tc -n sw1 filter replace dev vx0 egress pref 1 handle 101 proto ipv6 flower indev swp1 ip_proto icmpv6 dst_ip $maddr src_ip $saddr1 type 135 code 0 action pass" -- run_cmd "tc -n sw1 filter replace dev vx0 egress pref 1 handle 102 proto ipv6 flower indev swp1 ip_proto icmpv6 dst_ip $maddr src_ip $saddr2 type 135 code 0 action pass" -+ run_cmd "tc -n $sw1 qdisc replace dev vx0 clsact" -+ run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 101 proto ipv6 flower indev swp1 ip_proto icmpv6 dst_ip $maddr src_ip $saddr1 type 135 code 0 action pass" -+ run_cmd "tc -n $sw1 filter replace dev vx0 egress pref 1 handle 102 proto ipv6 flower indev swp1 ip_proto icmpv6 dst_ip $maddr src_ip $saddr2 type 135 code 0 action pass" - -- h2_mac1=$(ip -n h2 -j -p link show eth0.$vid1 | jq -r '.[]["address"]') -- h2_mac2=$(ip -n h2 -j -p link show eth0.$vid2 | jq -r '.[]["address"]') -- run_cmd "bridge -n sw1 fdb replace $h2_mac1 dev vx0 master static vlan $vid1" -- run_cmd "bridge -n sw1 fdb replace $h2_mac2 dev vx0 master static vlan $vid2" -- run_cmd "ip -n sw1 neigh replace $daddr1 lladdr $h2_mac1 nud permanent dev br0.$vid1" -- run_cmd "ip -n sw1 neigh replace $daddr2 lladdr $h2_mac2 nud permanent dev br0.$vid2" -+ h2_mac1=$(ip -n $h2 -j -p link show eth0.$vid1 | jq -r '.[]["address"]') -+ h2_mac2=$(ip -n $h2 -j -p link show eth0.$vid2 | jq -r '.[]["address"]') -+ run_cmd "bridge -n $sw1 fdb replace $h2_mac1 dev vx0 master static vlan $vid1" -+ run_cmd "bridge -n $sw1 fdb replace $h2_mac2 dev vx0 master static vlan $vid2" -+ run_cmd "ip -n $sw1 neigh replace $daddr1 lladdr $h2_mac1 nud permanent dev br0.$vid1" -+ run_cmd "ip -n $sw1 neigh replace $daddr2 lladdr $h2_mac2 nud permanent dev br0.$vid2" - - # Enable per-{Port, VLAN} neighbor suppression and check that NS - # messages are not suppressed and that ND messages are received. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_vlan_suppress on" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress on\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_vlan_suppress on" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress on\"" - log_test $? 0 "\"neigh_vlan_suppress\" is on" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" - log_test $? 0 "ndisc6 (VLAN $vid1)" -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" - log_test $? 0 "ndisc6 (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 1 -+ tc_check_packets $sw1 "dev vx0 egress" 101 1 - log_test $? 0 "NS suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 1 -+ tc_check_packets $sw1 "dev vx0 egress" 102 1 - log_test $? 0 "NS suppression (VLAN $vid2)" - - # Enable neighbor suppression on VLAN 10 and check that only on this - # VLAN NS messages are suppressed. -- run_cmd "bridge -n sw1 vlan set vid $vid1 dev vx0 neigh_suppress on" -- run_cmd "bridge -n sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress on\"" -+ run_cmd "bridge -n $sw1 vlan set vid $vid1 dev vx0 neigh_suppress on" -+ run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress on\"" - log_test $? 0 "\"neigh_suppress\" is on (VLAN $vid1)" -- run_cmd "bridge -n sw1 -d vlan show dev vx0 vid $vid2 | grep \"neigh_suppress off\"" -+ run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid2 | grep \"neigh_suppress off\"" - log_test $? 0 "\"neigh_suppress\" is off (VLAN $vid2)" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" - log_test $? 0 "ndisc6 (VLAN $vid1)" -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" - log_test $? 0 "ndisc6 (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 1 -+ tc_check_packets $sw1 "dev vx0 egress" 101 1 - log_test $? 0 "NS suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 2 -+ tc_check_packets $sw1 "dev vx0 egress" 102 2 - log_test $? 0 "NS suppression (VLAN $vid2)" - - # Enable neighbor suppression on the port and check that it has no - # effect compared to previous state. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_suppress on" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" - log_test $? 0 "\"neigh_suppress\" is on" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" - log_test $? 0 "ndisc6 (VLAN $vid1)" -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" - log_test $? 0 "ndisc6 (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 1 -+ tc_check_packets $sw1 "dev vx0 egress" 101 1 - log_test $? 0 "NS suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 3 -+ tc_check_packets $sw1 "dev vx0 egress" 102 3 - log_test $? 0 "NS suppression (VLAN $vid2)" - - # Disable neighbor suppression on the port and check that it has no - # effect compared to previous state. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_suppress off" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_suppress off\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress off" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress off\"" - log_test $? 0 "\"neigh_suppress\" is off" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" - log_test $? 0 "ndisc6 (VLAN $vid1)" -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" - log_test $? 0 "ndisc6 (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 1 -+ tc_check_packets $sw1 "dev vx0 egress" 101 1 - log_test $? 0 "NS suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 4 -+ tc_check_packets $sw1 "dev vx0 egress" 102 4 - log_test $? 0 "NS suppression (VLAN $vid2)" - - # Disable neighbor suppression on VLAN 10 and check that NS messages - # are no longer suppressed on this VLAN. -- run_cmd "bridge -n sw1 vlan set vid $vid1 dev vx0 neigh_suppress off" -- run_cmd "bridge -n sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress off\"" -+ run_cmd "bridge -n $sw1 vlan set vid $vid1 dev vx0 neigh_suppress off" -+ run_cmd "bridge -n $sw1 -d vlan show dev vx0 vid $vid1 | grep \"neigh_suppress off\"" - log_test $? 0 "\"neigh_suppress\" is off (VLAN $vid1)" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" - log_test $? 0 "ndisc6 (VLAN $vid1)" -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" - log_test $? 0 "ndisc6 (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 2 -+ tc_check_packets $sw1 "dev vx0 egress" 101 2 - log_test $? 0 "NS suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 5 -+ tc_check_packets $sw1 "dev vx0 egress" 102 5 - log_test $? 0 "NS suppression (VLAN $vid2)" - - # Disable per-{Port, VLAN} neighbor suppression, enable neighbor - # suppression on the port and check that on both VLANs NS messages are - # suppressed. -- run_cmd "bridge -n sw1 link set dev vx0 neigh_vlan_suppress off" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress off\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_vlan_suppress off" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_vlan_suppress off\"" - log_test $? 0 "\"neigh_vlan_suppress\" is off" - -- run_cmd "bridge -n sw1 link set dev vx0 neigh_suppress on" -- run_cmd "bridge -n sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" -+ run_cmd "bridge -n $sw1 link set dev vx0 neigh_suppress on" -+ run_cmd "bridge -n $sw1 -d link show dev vx0 | grep \"neigh_suppress on\"" - log_test $? 0 "\"neigh_suppress\" is on" - -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr1 -w 5000 $daddr1 eth0.$vid1" - log_test $? 0 "ndisc6 (VLAN $vid1)" -- run_cmd "ip netns exec h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" -+ run_cmd "ip netns exec $h1 ndisc6 -q -r 1 -s $saddr2 -w 5000 $daddr2 eth0.$vid2" - log_test $? 0 "ndisc6 (VLAN $vid2)" - -- tc_check_packets sw1 "dev vx0 egress" 101 2 -+ tc_check_packets $sw1 "dev vx0 egress" 101 2 - log_test $? 0 "NS suppression (VLAN $vid1)" -- tc_check_packets sw1 "dev vx0 egress" 102 5 -+ tc_check_packets $sw1 "dev vx0 egress" 102 5 - log_test $? 0 "NS suppression (VLAN $vid2)" - } - -diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c -index 48b9a803235a8..d13ebde203221 100644 ---- a/tools/testing/selftests/timers/valid-adjtimex.c -+++ b/tools/testing/selftests/timers/valid-adjtimex.c -@@ -21,9 +21,6 @@ - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -- -- -- - #include - #include - #include -@@ -62,45 +59,47 @@ int clear_time_state(void) - #define NUM_FREQ_OUTOFRANGE 4 - #define NUM_FREQ_INVALID 2 - -+#define SHIFTED_PPM (1 << 16) -+ - long valid_freq[NUM_FREQ_VALID] = { -- -499<<16, -- -450<<16, -- -400<<16, -- -350<<16, -- -300<<16, -- -250<<16, -- -200<<16, -- -150<<16, -- -100<<16, -- -75<<16, -- -50<<16, -- -25<<16, -- -10<<16, -- -5<<16, -- -1<<16, -+ -499 * SHIFTED_PPM, -+ -450 * SHIFTED_PPM, -+ -400 * SHIFTED_PPM, -+ -350 * SHIFTED_PPM, -+ -300 * SHIFTED_PPM, -+ -250 * SHIFTED_PPM, -+ -200 * SHIFTED_PPM, -+ -150 * SHIFTED_PPM, -+ -100 * SHIFTED_PPM, -+ -75 * SHIFTED_PPM, -+ -50 * SHIFTED_PPM, -+ -25 * SHIFTED_PPM, -+ -10 * SHIFTED_PPM, -+ -5 * SHIFTED_PPM, -+ -1 * SHIFTED_PPM, - -1000, -- 1<<16, -- 5<<16, -- 10<<16, -- 25<<16, -- 50<<16, -- 75<<16, -- 100<<16, -- 150<<16, -- 200<<16, -- 250<<16, -- 300<<16, -- 350<<16, -- 400<<16, -- 450<<16, -- 499<<16, -+ 1 * SHIFTED_PPM, -+ 5 * SHIFTED_PPM, -+ 10 * SHIFTED_PPM, -+ 25 * SHIFTED_PPM, -+ 50 * SHIFTED_PPM, -+ 75 * SHIFTED_PPM, -+ 100 * SHIFTED_PPM, -+ 150 * SHIFTED_PPM, -+ 200 * SHIFTED_PPM, -+ 250 * SHIFTED_PPM, -+ 300 * SHIFTED_PPM, -+ 350 * SHIFTED_PPM, -+ 400 * SHIFTED_PPM, -+ 450 * SHIFTED_PPM, -+ 499 * SHIFTED_PPM, - }; - - long outofrange_freq[NUM_FREQ_OUTOFRANGE] = { -- -1000<<16, -- -550<<16, -- 550<<16, -- 1000<<16, -+ -1000 * SHIFTED_PPM, -+ -550 * SHIFTED_PPM, -+ 550 * SHIFTED_PPM, -+ 1000 * SHIFTED_PPM, - }; - - #define LONG_MAX (~0UL>>1) diff --git a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.31-32.patch b/patch/kernel/archive/odroidxu4-6.6/patch-6.6.31-32.patch deleted file mode 100644 index 70eab8f17aee..000000000000 --- a/patch/kernel/archive/odroidxu4-6.6/patch-6.6.31-32.patch +++ /dev/null @@ -1,10264 +0,0 @@ -diff --git a/Documentation/ABI/stable/sysfs-block b/Documentation/ABI/stable/sysfs-block -index 1fe9a553c37b7..f0025d1c3d5ac 100644 ---- a/Documentation/ABI/stable/sysfs-block -+++ b/Documentation/ABI/stable/sysfs-block -@@ -101,6 +101,16 @@ Description: - devices that support receiving integrity metadata. - - -+What: /sys/block//partscan -+Date: May 2024 -+Contact: Christoph Hellwig -+Description: -+ The /sys/block//partscan files reports if partition -+ scanning is enabled for the disk. It returns "1" if partition -+ scanning is enabled, or "0" if not. The value type is a 32-bit -+ unsigned integer, but only "0" and "1" are valid values. -+ -+ - What: /sys/block///alignment_offset - Date: April 2009 - Contact: Martin K. Petersen -diff --git a/Documentation/admin-guide/hw-vuln/core-scheduling.rst b/Documentation/admin-guide/hw-vuln/core-scheduling.rst -index cf1eeefdfc32f..a92e10ec402e7 100644 ---- a/Documentation/admin-guide/hw-vuln/core-scheduling.rst -+++ b/Documentation/admin-guide/hw-vuln/core-scheduling.rst -@@ -67,8 +67,8 @@ arg4: - will be performed for all tasks in the task group of ``pid``. - - arg5: -- userspace pointer to an unsigned long for storing the cookie returned by -- ``PR_SCHED_CORE_GET`` command. Should be 0 for all other commands. -+ userspace pointer to an unsigned long long for storing the cookie returned -+ by ``PR_SCHED_CORE_GET`` command. Should be 0 for all other commands. - - In order for a process to push a cookie to, or pull a cookie from a process, it - is required to have the ptrace access mode: `PTRACE_MODE_READ_REALCREDS` to the -diff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst -index 8da1b72818273..9285f69f4f735 100644 ---- a/Documentation/admin-guide/mm/damon/usage.rst -+++ b/Documentation/admin-guide/mm/damon/usage.rst -@@ -389,7 +389,7 @@ pages of all memory cgroups except ``/having_care_already``.:: - # # further filter out all cgroups except one at '/having_care_already' - echo memcg > 1/type - echo /having_care_already > 1/memcg_path -- echo N > 1/matching -+ echo Y > 1/matching - - Note that ``anon`` and ``memcg`` filters are currently supported only when - ``paddr`` `implementation ` is being used. -diff --git a/Documentation/sphinx/kernel_include.py b/Documentation/sphinx/kernel_include.py -index abe7680883771..6387624423363 100755 ---- a/Documentation/sphinx/kernel_include.py -+++ b/Documentation/sphinx/kernel_include.py -@@ -97,7 +97,6 @@ class KernelInclude(Include): - # HINT: this is the only line I had to change / commented out: - #path = utils.relative_path(None, path) - -- path = nodes.reprunicode(path) - encoding = self.options.get( - 'encoding', self.state.document.settings.input_encoding) - e_handler=self.state.document.settings.input_encoding_error_handler -diff --git a/Makefile b/Makefile -index f66238b5d9315..c3b324ed985e6 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,7 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - VERSION = 6 - PATCHLEVEL = 6 --SUBLEVEL = 31 -+SUBLEVEL = 32 - EXTRAVERSION = - NAME = Hurr durr I'ma ninja sloth - -diff --git a/block/genhd.c b/block/genhd.c -index f9b81be6c7610..2ef1e08d70ecd 100644 ---- a/block/genhd.c -+++ b/block/genhd.c -@@ -345,9 +345,7 @@ int disk_scan_partitions(struct gendisk *disk, blk_mode_t mode) - struct block_device *bdev; - int ret = 0; - -- if (disk->flags & (GENHD_FL_NO_PART | GENHD_FL_HIDDEN)) -- return -EINVAL; -- if (test_bit(GD_SUPPRESS_PART_SCAN, &disk->state)) -+ if (!disk_has_partscan(disk)) - return -EINVAL; - if (disk->open_partitions) - return -EBUSY; -@@ -503,8 +501,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk, - goto out_unregister_bdi; - - /* Make sure the first partition scan will be proceed */ -- if (get_capacity(disk) && !(disk->flags & GENHD_FL_NO_PART) && -- !test_bit(GD_SUPPRESS_PART_SCAN, &disk->state)) -+ if (get_capacity(disk) && disk_has_partscan(disk)) - set_bit(GD_NEED_PART_SCAN, &disk->state); - - bdev_add(disk->part0, ddev->devt); -@@ -1040,6 +1037,12 @@ static ssize_t diskseq_show(struct device *dev, - return sprintf(buf, "%llu\n", disk->diskseq); - } - -+static ssize_t partscan_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ return sprintf(buf, "%u\n", disk_has_partscan(dev_to_disk(dev))); -+} -+ - static DEVICE_ATTR(range, 0444, disk_range_show, NULL); - static DEVICE_ATTR(ext_range, 0444, disk_ext_range_show, NULL); - static DEVICE_ATTR(removable, 0444, disk_removable_show, NULL); -@@ -1053,6 +1056,7 @@ static DEVICE_ATTR(stat, 0444, part_stat_show, NULL); - static DEVICE_ATTR(inflight, 0444, part_inflight_show, NULL); - static DEVICE_ATTR(badblocks, 0644, disk_badblocks_show, disk_badblocks_store); - static DEVICE_ATTR(diskseq, 0444, diskseq_show, NULL); -+static DEVICE_ATTR(partscan, 0444, partscan_show, NULL); - - #ifdef CONFIG_FAIL_MAKE_REQUEST - ssize_t part_fail_show(struct device *dev, -@@ -1099,6 +1103,7 @@ static struct attribute *disk_attrs[] = { - &dev_attr_events_async.attr, - &dev_attr_events_poll_msecs.attr, - &dev_attr_diskseq.attr, -+ &dev_attr_partscan.attr, - #ifdef CONFIG_FAIL_MAKE_REQUEST - &dev_attr_fail.attr, - #endif -diff --git a/block/partitions/core.c b/block/partitions/core.c -index e58c8b50350bd..962e4b57d64ab 100644 ---- a/block/partitions/core.c -+++ b/block/partitions/core.c -@@ -592,10 +592,7 @@ static int blk_add_partitions(struct gendisk *disk) - struct parsed_partitions *state; - int ret = -EAGAIN, p; - -- if (disk->flags & GENHD_FL_NO_PART) -- return 0; -- -- if (test_bit(GD_SUPPRESS_PART_SCAN, &disk->state)) -+ if (!disk_has_partscan(disk)) - return 0; - - state = check_partition(disk); -diff --git a/drivers/android/binder.c b/drivers/android/binder.c -index 64f4573656c6d..e67a91120385d 100644 ---- a/drivers/android/binder.c -+++ b/drivers/android/binder.c -@@ -5368,7 +5368,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) - goto err; - break; - case BINDER_SET_MAX_THREADS: { -- int max_threads; -+ u32 max_threads; - - if (copy_from_user(&max_threads, ubuf, - sizeof(max_threads))) { -diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h -index 7270d4d222070..5b7c80b99ae86 100644 ---- a/drivers/android/binder_internal.h -+++ b/drivers/android/binder_internal.h -@@ -421,7 +421,7 @@ struct binder_proc { - struct list_head todo; - struct binder_stats stats; - struct list_head delivered_death; -- int max_threads; -+ u32 max_threads; - int requested_threads; - int requested_threads_started; - int tmp_ref; -diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c -index 6f6341f702789..67b75ff0f7c37 100644 ---- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c -+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c -@@ -1025,6 +1025,9 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, - if (!obj) - return -EINVAL; - -+ if (!info || info->head.block == AMDGPU_RAS_BLOCK_COUNT) -+ return -EINVAL; -+ - if (info->head.block == AMDGPU_RAS_BLOCK__UMC) { - amdgpu_ras_get_ecc_info(adev, &err_data); - } else { -diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c -index 3966845c76945..230be292ff35b 100644 ---- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c -+++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c -@@ -1033,7 +1033,12 @@ static bool setup_dsc_config( - if (!is_dsc_possible) - goto done; - -- dsc_cfg->num_slices_v = pic_height/slice_height; -+ if (slice_height > 0) { -+ dsc_cfg->num_slices_v = pic_height / slice_height; -+ } else { -+ is_dsc_possible = false; -+ goto done; -+ } - - if (target_bandwidth_kbps > 0) { - is_dsc_possible = decide_dsc_target_bpp_x16( -diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c -index 3a927452a6501..7e39017e440fb 100644 ---- a/drivers/mmc/core/mmc.c -+++ b/drivers/mmc/core/mmc.c -@@ -1819,8 +1819,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, - - if (err) - goto free_card; -- -- } else if (!mmc_card_hs400es(card)) { -+ } else if (mmc_card_hs400es(card)) { -+ if (host->ops->execute_hs400_tuning) { -+ err = host->ops->execute_hs400_tuning(host, card); -+ if (err) -+ goto free_card; -+ } -+ } else { - /* Select the desired bus width optionally */ - err = mmc_select_bus_width(card); - if (err > 0 && mmc_card_hs(card)) { -diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c -index d8509e86214ef..6c6f267dcccc3 100644 ---- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c -+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c -@@ -547,17 +547,15 @@ bool ice_vc_isvalid_vsi_id(struct ice_vf *vf, u16 vsi_id) - - /** - * ice_vc_isvalid_q_id -- * @vf: pointer to the VF info -- * @vsi_id: VSI ID -+ * @vsi: VSI to check queue ID against - * @qid: VSI relative queue ID - * - * check for the valid queue ID - */ --static bool ice_vc_isvalid_q_id(struct ice_vf *vf, u16 vsi_id, u8 qid) -+static bool ice_vc_isvalid_q_id(struct ice_vsi *vsi, u8 qid) - { -- struct ice_vsi *vsi = ice_find_vsi(vf->pf, vsi_id); - /* allocated Tx and Rx queues should be always equal for VF VSI */ -- return (vsi && (qid < vsi->alloc_txq)); -+ return qid < vsi->alloc_txq; - } - - /** -@@ -1257,7 +1255,7 @@ static int ice_vc_ena_qs_msg(struct ice_vf *vf, u8 *msg) - */ - q_map = vqs->rx_queues; - for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) { -- if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) { -+ if (!ice_vc_isvalid_q_id(vsi, vf_q_id)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto error_param; - } -@@ -1279,7 +1277,7 @@ static int ice_vc_ena_qs_msg(struct ice_vf *vf, u8 *msg) - - q_map = vqs->tx_queues; - for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) { -- if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) { -+ if (!ice_vc_isvalid_q_id(vsi, vf_q_id)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto error_param; - } -@@ -1384,7 +1382,7 @@ static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg) - q_map = vqs->tx_queues; - - for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) { -- if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) { -+ if (!ice_vc_isvalid_q_id(vsi, vf_q_id)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto error_param; - } -@@ -1410,7 +1408,7 @@ static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg) - bitmap_zero(vf->rxq_ena, ICE_MAX_RSS_QS_PER_VF); - } else if (q_map) { - for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) { -- if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) { -+ if (!ice_vc_isvalid_q_id(vsi, vf_q_id)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto error_param; - } -@@ -1466,7 +1464,7 @@ ice_cfg_interrupt(struct ice_vf *vf, struct ice_vsi *vsi, u16 vector_id, - for_each_set_bit(vsi_q_id_idx, &qmap, ICE_MAX_RSS_QS_PER_VF) { - vsi_q_id = vsi_q_id_idx; - -- if (!ice_vc_isvalid_q_id(vf, vsi->vsi_num, vsi_q_id)) -+ if (!ice_vc_isvalid_q_id(vsi, vsi_q_id)) - return VIRTCHNL_STATUS_ERR_PARAM; - - q_vector->num_ring_rx++; -@@ -1480,7 +1478,7 @@ ice_cfg_interrupt(struct ice_vf *vf, struct ice_vsi *vsi, u16 vector_id, - for_each_set_bit(vsi_q_id_idx, &qmap, ICE_MAX_RSS_QS_PER_VF) { - vsi_q_id = vsi_q_id_idx; - -- if (!ice_vc_isvalid_q_id(vf, vsi->vsi_num, vsi_q_id)) -+ if (!ice_vc_isvalid_q_id(vsi, vsi_q_id)) - return VIRTCHNL_STATUS_ERR_PARAM; - - q_vector->num_ring_tx++; -@@ -1629,7 +1627,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) - qpi->txq.headwb_enabled || - !ice_vc_isvalid_ring_len(qpi->txq.ring_len) || - !ice_vc_isvalid_ring_len(qpi->rxq.ring_len) || -- !ice_vc_isvalid_q_id(vf, qci->vsi_id, qpi->txq.queue_id)) { -+ !ice_vc_isvalid_q_id(vsi, qpi->txq.queue_id)) { - goto error_param; - } - -diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c -index daa6a1e894cfc..6fdbd73804d16 100644 ---- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c -+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c -@@ -107,9 +107,6 @@ ice_vc_fdir_param_check(struct ice_vf *vf, u16 vsi_id) - if (!(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_FDIR_PF)) - return -EINVAL; - -- if (vsi_id != vf->lan_vsi_num) -- return -EINVAL; -- - if (!ice_vc_isvalid_vsi_id(vf, vsi_id)) - return -EINVAL; - -diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c -index 502518cdb4618..6453c92f0fa7c 100644 ---- a/drivers/net/ethernet/micrel/ks8851_common.c -+++ b/drivers/net/ethernet/micrel/ks8851_common.c -@@ -328,7 +328,6 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) - { - struct ks8851_net *ks = _ks; - struct sk_buff_head rxq; -- unsigned handled = 0; - unsigned long flags; - unsigned int status; - struct sk_buff *skb; -@@ -336,24 +335,17 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) - ks8851_lock(ks, &flags); - - status = ks8851_rdreg16(ks, KS_ISR); -+ ks8851_wrreg16(ks, KS_ISR, status); - - netif_dbg(ks, intr, ks->netdev, - "%s: status 0x%04x\n", __func__, status); - -- if (status & IRQ_LCI) -- handled |= IRQ_LCI; -- - if (status & IRQ_LDI) { - u16 pmecr = ks8851_rdreg16(ks, KS_PMECR); - pmecr &= ~PMECR_WKEVT_MASK; - ks8851_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK); -- -- handled |= IRQ_LDI; - } - -- if (status & IRQ_RXPSI) -- handled |= IRQ_RXPSI; -- - if (status & IRQ_TXI) { - unsigned short tx_space = ks8851_rdreg16(ks, KS_TXMIR); - -@@ -365,20 +357,12 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) - if (netif_queue_stopped(ks->netdev)) - netif_wake_queue(ks->netdev); - spin_unlock(&ks->statelock); -- -- handled |= IRQ_TXI; - } - -- if (status & IRQ_RXI) -- handled |= IRQ_RXI; -- - if (status & IRQ_SPIBEI) { - netdev_err(ks->netdev, "%s: spi bus error\n", __func__); -- handled |= IRQ_SPIBEI; - } - -- ks8851_wrreg16(ks, KS_ISR, handled); -- - if (status & IRQ_RXI) { - /* the datasheet says to disable the rx interrupt during - * packet read-out, however we're masking the interrupt -diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c -index 21b6c4d94a632..6d31061818e93 100644 ---- a/drivers/net/usb/ax88179_178a.c -+++ b/drivers/net/usb/ax88179_178a.c -@@ -174,6 +174,7 @@ struct ax88179_data { - u32 wol_supported; - u32 wolopts; - u8 disconnecting; -+ u8 initialized; - }; - - struct ax88179_int_data { -@@ -1673,6 +1674,18 @@ static int ax88179_reset(struct usbnet *dev) - return 0; - } - -+static int ax88179_net_reset(struct usbnet *dev) -+{ -+ struct ax88179_data *ax179_data = dev->driver_priv; -+ -+ if (ax179_data->initialized) -+ ax88179_reset(dev); -+ else -+ ax179_data->initialized = 1; -+ -+ return 0; -+} -+ - static int ax88179_stop(struct usbnet *dev) - { - u16 tmp16; -@@ -1692,6 +1705,7 @@ static const struct driver_info ax88179_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1704,6 +1718,7 @@ static const struct driver_info ax88178a_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1716,7 +1731,7 @@ static const struct driver_info cypress_GX3_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -- .reset = ax88179_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1729,7 +1744,7 @@ static const struct driver_info dlink_dub1312_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -- .reset = ax88179_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1742,7 +1757,7 @@ static const struct driver_info sitecom_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -- .reset = ax88179_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1755,7 +1770,7 @@ static const struct driver_info samsung_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -- .reset = ax88179_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1768,7 +1783,7 @@ static const struct driver_info lenovo_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -- .reset = ax88179_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1781,7 +1796,7 @@ static const struct driver_info belkin_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -- .reset = ax88179_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1794,7 +1809,7 @@ static const struct driver_info toshiba_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -- .reset = ax88179_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1807,7 +1822,7 @@ static const struct driver_info mct_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -- .reset = ax88179_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1820,7 +1835,7 @@ static const struct driver_info at_umc2000_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -- .reset = ax88179_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1833,7 +1848,7 @@ static const struct driver_info at_umc200_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -- .reset = ax88179_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -@@ -1846,7 +1861,7 @@ static const struct driver_info at_umc2000sp_info = { - .unbind = ax88179_unbind, - .status = ax88179_status, - .link_reset = ax88179_link_reset, -- .reset = ax88179_reset, -+ .reset = ax88179_net_reset, - .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88179_rx_fixup, -diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c -index dcc94ee2458d8..c4c535b011812 100644 ---- a/drivers/remoteproc/mtk_scp.c -+++ b/drivers/remoteproc/mtk_scp.c -@@ -126,7 +126,7 @@ static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp, - static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw) - { - int ret; -- size_t offset; -+ size_t buf_sz, offset; - - /* read the ipi buf addr from FW itself first */ - ret = scp_elf_read_ipi_buf_addr(scp, fw, &offset); -@@ -138,6 +138,14 @@ static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw) - } - dev_info(scp->dev, "IPI buf addr %#010zx\n", offset); - -+ /* Make sure IPI buffer fits in the L2TCM range assigned to this core */ -+ buf_sz = sizeof(*scp->recv_buf) + sizeof(*scp->send_buf); -+ -+ if (scp->sram_size < buf_sz + offset) { -+ dev_err(scp->dev, "IPI buffer does not fit in SRAM.\n"); -+ return -EOVERFLOW; -+ } -+ - scp->recv_buf = (struct mtk_share_obj __iomem *) - (scp->sram_base + offset); - scp->send_buf = (struct mtk_share_obj __iomem *) -diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c -index 7ce7bb1640054..58ea1e1391cee 100644 ---- a/drivers/tty/serial/kgdboc.c -+++ b/drivers/tty/serial/kgdboc.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -48,6 +49,25 @@ static struct kgdb_io kgdboc_earlycon_io_ops; - static int (*earlycon_orig_exit)(struct console *con); - #endif /* IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */ - -+/* -+ * When we leave the debug trap handler we need to reset the keyboard status -+ * (since the original keyboard state gets partially clobbered by kdb use of -+ * the keyboard). -+ * -+ * The path to deliver the reset is somewhat circuitous. -+ * -+ * To deliver the reset we register an input handler, reset the keyboard and -+ * then deregister the input handler. However, to get this done right, we do -+ * have to carefully manage the calling context because we can only register -+ * input handlers from task context. -+ * -+ * In particular we need to trigger the action from the debug trap handler with -+ * all its NMI and/or NMI-like oddities. To solve this the kgdboc trap exit code -+ * (the "post_exception" callback) uses irq_work_queue(), which is NMI-safe, to -+ * schedule a callback from a hardirq context. From there we have to defer the -+ * work again, this time using schedule_work(), to get a callback using the -+ * system workqueue, which runs in task context. -+ */ - #ifdef CONFIG_KDB_KEYBOARD - static int kgdboc_reset_connect(struct input_handler *handler, - struct input_dev *dev, -@@ -99,10 +119,17 @@ static void kgdboc_restore_input_helper(struct work_struct *dummy) - - static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper); - -+static void kgdboc_queue_restore_input_helper(struct irq_work *unused) -+{ -+ schedule_work(&kgdboc_restore_input_work); -+} -+ -+static DEFINE_IRQ_WORK(kgdboc_restore_input_irq_work, kgdboc_queue_restore_input_helper); -+ - static void kgdboc_restore_input(void) - { - if (likely(system_state == SYSTEM_RUNNING)) -- schedule_work(&kgdboc_restore_input_work); -+ irq_work_queue(&kgdboc_restore_input_irq_work); - } - - static int kgdboc_register_kbd(char **cptr) -@@ -133,6 +160,7 @@ static void kgdboc_unregister_kbd(void) - i--; - } - } -+ irq_work_sync(&kgdboc_restore_input_irq_work); - flush_work(&kgdboc_restore_input_work); - } - #else /* ! CONFIG_KDB_KEYBOARD */ -diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c -index 4062a486b9e63..579d90efc281a 100644 ---- a/drivers/usb/dwc3/gadget.c -+++ b/drivers/usb/dwc3/gadget.c -@@ -1718,7 +1718,6 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc) - */ - static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt) - { -- struct dwc3 *dwc = dep->dwc; - struct dwc3_gadget_ep_cmd_params params; - u32 cmd; - int ret; -@@ -1743,8 +1742,7 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int - dep->resource_index = 0; - - if (!interrupt) { -- if (!DWC3_IP_IS(DWC3) || DWC3_VER_IS_PRIOR(DWC3, 310A)) -- mdelay(1); -+ mdelay(1); - dep->flags &= ~DWC3_EP_TRANSFER_STARTED; - } else if (!ret) { - dep->flags |= DWC3_EP_END_TRANSFER_PENDING; -diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c -index 37b56ce75f39d..125269f39f83a 100644 ---- a/drivers/usb/typec/tipd/core.c -+++ b/drivers/usb/typec/tipd/core.c -@@ -26,6 +26,7 @@ - #define TPS_REG_MODE 0x03 - #define TPS_REG_CMD1 0x08 - #define TPS_REG_DATA1 0x09 -+#define TPS_REG_VERSION 0x0F - #define TPS_REG_INT_EVENT1 0x14 - #define TPS_REG_INT_EVENT2 0x15 - #define TPS_REG_INT_MASK1 0x16 -@@ -515,49 +516,67 @@ static irqreturn_t cd321x_interrupt(int irq, void *data) - - static irqreturn_t tps6598x_interrupt(int irq, void *data) - { -+ int intev_len = TPS_65981_2_6_INTEVENT_LEN; - struct tps6598x *tps = data; -- u64 event1 = 0; -- u64 event2 = 0; -+ u64 event1[2] = { }; -+ u64 event2[2] = { }; -+ u32 version; - u32 status; - int ret; - - mutex_lock(&tps->lock); - -- ret = tps6598x_read64(tps, TPS_REG_INT_EVENT1, &event1); -- ret |= tps6598x_read64(tps, TPS_REG_INT_EVENT2, &event2); -+ ret = tps6598x_read32(tps, TPS_REG_VERSION, &version); -+ if (ret) -+ dev_warn(tps->dev, "%s: failed to read version (%d)\n", -+ __func__, ret); -+ -+ if (TPS_VERSION_HW_VERSION(version) == TPS_VERSION_HW_65987_8_DH || -+ TPS_VERSION_HW_VERSION(version) == TPS_VERSION_HW_65987_8_DK) -+ intev_len = TPS_65987_8_INTEVENT_LEN; -+ -+ ret = tps6598x_block_read(tps, TPS_REG_INT_EVENT1, event1, intev_len); -+ -+ ret = tps6598x_block_read(tps, TPS_REG_INT_EVENT1, event1, intev_len); - if (ret) { -- dev_err(tps->dev, "%s: failed to read events\n", __func__); -+ dev_err(tps->dev, "%s: failed to read event1\n", __func__); - goto err_unlock; - } -- trace_tps6598x_irq(event1, event2); -+ ret = tps6598x_block_read(tps, TPS_REG_INT_EVENT2, event2, intev_len); -+ if (ret) { -+ dev_err(tps->dev, "%s: failed to read event2\n", __func__); -+ goto err_unlock; -+ } -+ trace_tps6598x_irq(event1[0], event2[0]); - -- if (!(event1 | event2)) -+ if (!(event1[0] | event1[1] | event2[0] | event2[1])) - goto err_unlock; - - if (!tps6598x_read_status(tps, &status)) - goto err_clear_ints; - -- if ((event1 | event2) & TPS_REG_INT_POWER_STATUS_UPDATE) -+ if ((event1[0] | event2[0]) & TPS_REG_INT_POWER_STATUS_UPDATE) - if (!tps6598x_read_power_status(tps)) - goto err_clear_ints; - -- if ((event1 | event2) & TPS_REG_INT_DATA_STATUS_UPDATE) -+ if ((event1[0] | event2[0]) & TPS_REG_INT_DATA_STATUS_UPDATE) - if (!tps6598x_read_data_status(tps)) - goto err_clear_ints; - - /* Handle plug insert or removal */ -- if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT) -+ if ((event1[0] | event2[0]) & TPS_REG_INT_PLUG_EVENT) - tps6598x_handle_plug_event(tps, status); - - err_clear_ints: -- tps6598x_write64(tps, TPS_REG_INT_CLEAR1, event1); -- tps6598x_write64(tps, TPS_REG_INT_CLEAR2, event2); -+ tps6598x_block_write(tps, TPS_REG_INT_CLEAR1, event1, intev_len); -+ tps6598x_block_write(tps, TPS_REG_INT_CLEAR2, event2, intev_len); - - err_unlock: - mutex_unlock(&tps->lock); - -- if (event1 | event2) -+ if (event1[0] | event1[1] | event2[0] | event2[1]) - return IRQ_HANDLED; -+ - return IRQ_NONE; - } - -diff --git a/drivers/usb/typec/tipd/tps6598x.h b/drivers/usb/typec/tipd/tps6598x.h -index 527857549d699..1fc3cc8ad199a 100644 ---- a/drivers/usb/typec/tipd/tps6598x.h -+++ b/drivers/usb/typec/tipd/tps6598x.h -@@ -199,4 +199,15 @@ - #define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_A BIT(2) - #define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_B (BIT(2) | BIT(1)) - -+/* Version Register */ -+#define TPS_VERSION_HW_VERSION_MASK GENMASK(31, 24) -+#define TPS_VERSION_HW_VERSION(x) TPS_FIELD_GET(TPS_VERSION_HW_VERSION_MASK, (x)) -+#define TPS_VERSION_HW_65981_2_6 0x00 -+#define TPS_VERSION_HW_65987_8_DH 0xF7 -+#define TPS_VERSION_HW_65987_8_DK 0xF9 -+ -+/* Int Event Register length */ -+#define TPS_65981_2_6_INTEVENT_LEN 8 -+#define TPS_65987_8_INTEVENT_LEN 11 -+ - #endif /* __TPS6598X_H__ */ -diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c -index 73cd5bf350472..2431febc46151 100644 ---- a/drivers/usb/typec/ucsi/displayport.c -+++ b/drivers/usb/typec/ucsi/displayport.c -@@ -275,8 +275,6 @@ static void ucsi_displayport_work(struct work_struct *work) - struct ucsi_dp *dp = container_of(work, struct ucsi_dp, work); - int ret; - -- mutex_lock(&dp->con->lock); -- - ret = typec_altmode_vdm(dp->alt, dp->header, - dp->vdo_data, dp->vdo_size); - if (ret) -@@ -285,8 +283,6 @@ static void ucsi_displayport_work(struct work_struct *work) - dp->vdo_data = NULL; - dp->vdo_size = 0; - dp->header = 0; -- -- mutex_unlock(&dp->con->lock); - } - - void ucsi_displayport_remove_partner(struct typec_altmode *alt) -diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h -index 1a4fe9f60295c..787cc9ff90294 100644 ---- a/fs/erofs/internal.h -+++ b/fs/erofs/internal.h -@@ -82,13 +82,6 @@ struct erofs_dev_context { - bool flatdev; - }; - --struct erofs_fs_context { -- struct erofs_mount_opts opt; -- struct erofs_dev_context *devs; -- char *fsid; -- char *domain_id; --}; -- - /* all filesystem-wide lz4 configurations */ - struct erofs_sb_lz4_info { - /* # of pages needed for EROFS lz4 rolling decompression */ -diff --git a/fs/erofs/super.c b/fs/erofs/super.c -index c9f9a43197db6..113414e6f35b9 100644 ---- a/fs/erofs/super.c -+++ b/fs/erofs/super.c -@@ -367,18 +367,18 @@ static int erofs_read_superblock(struct super_block *sb) - return ret; - } - --static void erofs_default_options(struct erofs_fs_context *ctx) -+static void erofs_default_options(struct erofs_sb_info *sbi) - { - #ifdef CONFIG_EROFS_FS_ZIP -- ctx->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND; -- ctx->opt.max_sync_decompress_pages = 3; -- ctx->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO; -+ sbi->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND; -+ sbi->opt.max_sync_decompress_pages = 3; -+ sbi->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO; - #endif - #ifdef CONFIG_EROFS_FS_XATTR -- set_opt(&ctx->opt, XATTR_USER); -+ set_opt(&sbi->opt, XATTR_USER); - #endif - #ifdef CONFIG_EROFS_FS_POSIX_ACL -- set_opt(&ctx->opt, POSIX_ACL); -+ set_opt(&sbi->opt, POSIX_ACL); - #endif - } - -@@ -423,17 +423,17 @@ static const struct fs_parameter_spec erofs_fs_parameters[] = { - static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode) - { - #ifdef CONFIG_FS_DAX -- struct erofs_fs_context *ctx = fc->fs_private; -+ struct erofs_sb_info *sbi = fc->s_fs_info; - - switch (mode) { - case EROFS_MOUNT_DAX_ALWAYS: - warnfc(fc, "DAX enabled. Warning: EXPERIMENTAL, use at your own risk"); -- set_opt(&ctx->opt, DAX_ALWAYS); -- clear_opt(&ctx->opt, DAX_NEVER); -+ set_opt(&sbi->opt, DAX_ALWAYS); -+ clear_opt(&sbi->opt, DAX_NEVER); - return true; - case EROFS_MOUNT_DAX_NEVER: -- set_opt(&ctx->opt, DAX_NEVER); -- clear_opt(&ctx->opt, DAX_ALWAYS); -+ set_opt(&sbi->opt, DAX_NEVER); -+ clear_opt(&sbi->opt, DAX_ALWAYS); - return true; - default: - DBG_BUGON(1); -@@ -448,7 +448,7 @@ static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode) - static int erofs_fc_parse_param(struct fs_context *fc, - struct fs_parameter *param) - { -- struct erofs_fs_context *ctx = fc->fs_private; -+ struct erofs_sb_info *sbi = fc->s_fs_info; - struct fs_parse_result result; - struct erofs_device_info *dif; - int opt, ret; -@@ -461,9 +461,9 @@ static int erofs_fc_parse_param(struct fs_context *fc, - case Opt_user_xattr: - #ifdef CONFIG_EROFS_FS_XATTR - if (result.boolean) -- set_opt(&ctx->opt, XATTR_USER); -+ set_opt(&sbi->opt, XATTR_USER); - else -- clear_opt(&ctx->opt, XATTR_USER); -+ clear_opt(&sbi->opt, XATTR_USER); - #else - errorfc(fc, "{,no}user_xattr options not supported"); - #endif -@@ -471,16 +471,16 @@ static int erofs_fc_parse_param(struct fs_context *fc, - case Opt_acl: - #ifdef CONFIG_EROFS_FS_POSIX_ACL - if (result.boolean) -- set_opt(&ctx->opt, POSIX_ACL); -+ set_opt(&sbi->opt, POSIX_ACL); - else -- clear_opt(&ctx->opt, POSIX_ACL); -+ clear_opt(&sbi->opt, POSIX_ACL); - #else - errorfc(fc, "{,no}acl options not supported"); - #endif - break; - case Opt_cache_strategy: - #ifdef CONFIG_EROFS_FS_ZIP -- ctx->opt.cache_strategy = result.uint_32; -+ sbi->opt.cache_strategy = result.uint_32; - #else - errorfc(fc, "compression not supported, cache_strategy ignored"); - #endif -@@ -502,27 +502,27 @@ static int erofs_fc_parse_param(struct fs_context *fc, - kfree(dif); - return -ENOMEM; - } -- down_write(&ctx->devs->rwsem); -- ret = idr_alloc(&ctx->devs->tree, dif, 0, 0, GFP_KERNEL); -- up_write(&ctx->devs->rwsem); -+ down_write(&sbi->devs->rwsem); -+ ret = idr_alloc(&sbi->devs->tree, dif, 0, 0, GFP_KERNEL); -+ up_write(&sbi->devs->rwsem); - if (ret < 0) { - kfree(dif->path); - kfree(dif); - return ret; - } -- ++ctx->devs->extra_devices; -+ ++sbi->devs->extra_devices; - break; - #ifdef CONFIG_EROFS_FS_ONDEMAND - case Opt_fsid: -- kfree(ctx->fsid); -- ctx->fsid = kstrdup(param->string, GFP_KERNEL); -- if (!ctx->fsid) -+ kfree(sbi->fsid); -+ sbi->fsid = kstrdup(param->string, GFP_KERNEL); -+ if (!sbi->fsid) - return -ENOMEM; - break; - case Opt_domain_id: -- kfree(ctx->domain_id); -- ctx->domain_id = kstrdup(param->string, GFP_KERNEL); -- if (!ctx->domain_id) -+ kfree(sbi->domain_id); -+ sbi->domain_id = kstrdup(param->string, GFP_KERNEL); -+ if (!sbi->domain_id) - return -ENOMEM; - break; - #else -@@ -578,8 +578,7 @@ static const struct export_operations erofs_export_ops = { - static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) - { - struct inode *inode; -- struct erofs_sb_info *sbi; -- struct erofs_fs_context *ctx = fc->fs_private; -+ struct erofs_sb_info *sbi = EROFS_SB(sb); - int err; - - sb->s_magic = EROFS_SUPER_MAGIC; -@@ -587,19 +586,6 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) - sb->s_maxbytes = MAX_LFS_FILESIZE; - sb->s_op = &erofs_sops; - -- sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); -- if (!sbi) -- return -ENOMEM; -- -- sb->s_fs_info = sbi; -- sbi->opt = ctx->opt; -- sbi->devs = ctx->devs; -- ctx->devs = NULL; -- sbi->fsid = ctx->fsid; -- ctx->fsid = NULL; -- sbi->domain_id = ctx->domain_id; -- ctx->domain_id = NULL; -- - sbi->blkszbits = PAGE_SHIFT; - if (erofs_is_fscache_mode(sb)) { - sb->s_blocksize = PAGE_SIZE; -@@ -703,9 +689,9 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) - - static int erofs_fc_get_tree(struct fs_context *fc) - { -- struct erofs_fs_context *ctx = fc->fs_private; -+ struct erofs_sb_info *sbi = fc->s_fs_info; - -- if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && ctx->fsid) -+ if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid) - return get_tree_nodev(fc, erofs_fc_fill_super); - - return get_tree_bdev(fc, erofs_fc_fill_super); -@@ -715,19 +701,19 @@ static int erofs_fc_reconfigure(struct fs_context *fc) - { - struct super_block *sb = fc->root->d_sb; - struct erofs_sb_info *sbi = EROFS_SB(sb); -- struct erofs_fs_context *ctx = fc->fs_private; -+ struct erofs_sb_info *new_sbi = fc->s_fs_info; - - DBG_BUGON(!sb_rdonly(sb)); - -- if (ctx->fsid || ctx->domain_id) -+ if (new_sbi->fsid || new_sbi->domain_id) - erofs_info(sb, "ignoring reconfiguration for fsid|domain_id."); - -- if (test_opt(&ctx->opt, POSIX_ACL)) -+ if (test_opt(&new_sbi->opt, POSIX_ACL)) - fc->sb_flags |= SB_POSIXACL; - else - fc->sb_flags &= ~SB_POSIXACL; - -- sbi->opt = ctx->opt; -+ sbi->opt = new_sbi->opt; - - fc->sb_flags |= SB_RDONLY; - return 0; -@@ -758,12 +744,15 @@ static void erofs_free_dev_context(struct erofs_dev_context *devs) - - static void erofs_fc_free(struct fs_context *fc) - { -- struct erofs_fs_context *ctx = fc->fs_private; -+ struct erofs_sb_info *sbi = fc->s_fs_info; - -- erofs_free_dev_context(ctx->devs); -- kfree(ctx->fsid); -- kfree(ctx->domain_id); -- kfree(ctx); -+ if (!sbi) -+ return; -+ -+ erofs_free_dev_context(sbi->devs); -+ kfree(sbi->fsid); -+ kfree(sbi->domain_id); -+ kfree(sbi); - } - - static const struct fs_context_operations erofs_context_ops = { -@@ -775,38 +764,35 @@ static const struct fs_context_operations erofs_context_ops = { - - static int erofs_init_fs_context(struct fs_context *fc) - { -- struct erofs_fs_context *ctx; -+ struct erofs_sb_info *sbi; - -- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); -- if (!ctx) -+ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); -+ if (!sbi) - return -ENOMEM; -- ctx->devs = kzalloc(sizeof(struct erofs_dev_context), GFP_KERNEL); -- if (!ctx->devs) { -- kfree(ctx); -+ -+ sbi->devs = kzalloc(sizeof(struct erofs_dev_context), GFP_KERNEL); -+ if (!sbi->devs) { -+ kfree(sbi); - return -ENOMEM; - } -- fc->fs_private = ctx; -+ fc->s_fs_info = sbi; - -- idr_init(&ctx->devs->tree); -- init_rwsem(&ctx->devs->rwsem); -- erofs_default_options(ctx); -+ idr_init(&sbi->devs->tree); -+ init_rwsem(&sbi->devs->rwsem); -+ erofs_default_options(sbi); - fc->ops = &erofs_context_ops; - return 0; - } - - static void erofs_kill_sb(struct super_block *sb) - { -- struct erofs_sb_info *sbi; -+ struct erofs_sb_info *sbi = EROFS_SB(sb); - -- if (erofs_is_fscache_mode(sb)) -+ if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid) - kill_anon_super(sb); - else - kill_block_super(sb); - -- sbi = EROFS_SB(sb); -- if (!sbi) -- return; -- - erofs_free_dev_context(sbi->devs); - fs_put_dax(sbi->dax_dev, NULL); - erofs_fscache_unregister_fs(sb); -diff --git a/fs/smb/client/Makefile b/fs/smb/client/Makefile -index 0b07eb94c93b3..e11985f2460b2 100644 ---- a/fs/smb/client/Makefile -+++ b/fs/smb/client/Makefile -@@ -12,7 +12,7 @@ cifs-y := trace.o cifsfs.o cifs_debug.o connect.o dir.o file.o \ - smb2ops.o smb2maperror.o smb2transport.o \ - smb2misc.o smb2pdu.o smb2inode.o smb2file.o cifsacl.o fs_context.o \ - dns_resolve.o cifs_spnego_negtokeninit.asn1.o asn1.o \ -- namespace.o -+ namespace.o reparse.o - - $(obj)/asn1.o: $(obj)/cifs_spnego_negtokeninit.asn1.h - -diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c -index 567f718362c52..0ff2491c311d8 100644 ---- a/fs/smb/client/cached_dir.c -+++ b/fs/smb/client/cached_dir.c -@@ -145,21 +145,27 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, - struct cached_fid *cfid; - struct cached_fids *cfids; - const char *npath; -+ int retries = 0, cur_sleep = 1; - - if (tcon == NULL || tcon->cfids == NULL || tcon->nohandlecache || - is_smb1_server(tcon->ses->server) || (dir_cache_timeout == 0)) - return -EOPNOTSUPP; - - ses = tcon->ses; -- server = cifs_pick_channel(ses); - cfids = tcon->cfids; - -- if (!server->ops->new_lease_key) -- return -EIO; -- - if (cifs_sb->root == NULL) - return -ENOENT; - -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ oplock = SMB2_OPLOCK_LEVEL_II; -+ server = cifs_pick_channel(ses); -+ -+ if (!server->ops->new_lease_key) -+ return -EIO; -+ - utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); - if (!utf16_path) - return -ENOMEM; -@@ -237,6 +243,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, - FILE_READ_EA, - .disposition = FILE_OPEN, - .fid = pfid, -+ .replay = !!(retries), - }; - - rc = SMB2_open_init(tcon, server, -@@ -269,6 +276,11 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, - */ - cfid->has_lease = true; - -+ if (retries) { -+ smb2_set_replay(server, &rqst[0]); -+ smb2_set_replay(server, &rqst[1]); -+ } -+ - rc = compound_send_recv(xid, ses, server, - flags, 2, rqst, - resp_buftype, rsp_iov); -@@ -369,6 +381,10 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, - } - kfree(utf16_path); - -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c -index c53d516459fc4..c71ae5c043060 100644 ---- a/fs/smb/client/cifs_debug.c -+++ b/fs/smb/client/cifs_debug.c -@@ -280,6 +280,24 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v) - return 0; - } - -+static __always_inline const char *compression_alg_str(__le16 alg) -+{ -+ switch (alg) { -+ case SMB3_COMPRESS_NONE: -+ return "NONE"; -+ case SMB3_COMPRESS_LZNT1: -+ return "LZNT1"; -+ case SMB3_COMPRESS_LZ77: -+ return "LZ77"; -+ case SMB3_COMPRESS_LZ77_HUFF: -+ return "LZ77-Huffman"; -+ case SMB3_COMPRESS_PATTERN: -+ return "Pattern_V1"; -+ default: -+ return "invalid"; -+ } -+} -+ - static int cifs_debug_data_proc_show(struct seq_file *m, void *v) - { - struct mid_q_entry *mid_entry; -@@ -425,12 +443,6 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) - server->echo_credits, - server->oplock_credits, - server->dialect); -- if (server->compress_algorithm == SMB3_COMPRESS_LZNT1) -- seq_printf(m, " COMPRESS_LZNT1"); -- else if (server->compress_algorithm == SMB3_COMPRESS_LZ77) -- seq_printf(m, " COMPRESS_LZ77"); -- else if (server->compress_algorithm == SMB3_COMPRESS_LZ77_HUFF) -- seq_printf(m, " COMPRESS_LZ77_HUFF"); - if (server->sign) - seq_printf(m, " signed"); - if (server->posix_ext_supported) -@@ -438,6 +450,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) - if (server->nosharesock) - seq_printf(m, " nosharesock"); - -+ seq_printf(m, "\nServer capabilities: 0x%x", server->capabilities); -+ - if (server->rdma) - seq_printf(m, "\nRDMA "); - seq_printf(m, "\nTCP status: %d Instance: %d" -@@ -460,6 +474,14 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) - server->leaf_fullpath); - } - -+ seq_puts(m, "\nCompression: "); -+ if (!server->compression.requested) -+ seq_puts(m, "disabled on mount"); -+ else if (server->compression.enabled) -+ seq_printf(m, "enabled (%s)", compression_alg_str(server->compression.alg)); -+ else -+ seq_puts(m, "disabled (not supported by this server)"); -+ - seq_printf(m, "\n\n\tSessions: "); - i = 0; - list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { -@@ -777,14 +799,14 @@ static ssize_t name##_write(struct file *file, const char __user *buffer, \ - size_t count, loff_t *ppos) \ - { \ - int rc; \ -- rc = kstrtoint_from_user(buffer, count, 10, & name); \ -+ rc = kstrtoint_from_user(buffer, count, 10, &name); \ - if (rc) \ - return rc; \ - return count; \ - } \ - static int name##_proc_show(struct seq_file *m, void *v) \ - { \ -- seq_printf(m, "%d\n", name ); \ -+ seq_printf(m, "%d\n", name); \ - return 0; \ - } \ - static int name##_open(struct inode *inode, struct file *file) \ -diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c -index 44e2cc37a8b63..f1dcb86ab9894 100644 ---- a/fs/smb/client/cifsfs.c -+++ b/fs/smb/client/cifsfs.c -@@ -150,10 +150,6 @@ MODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be " - "vers=1.0 (CIFS/SMB1) and vers=2.0 are weaker" - " and less secure. Default: n/N/0"); - --extern mempool_t *cifs_sm_req_poolp; --extern mempool_t *cifs_req_poolp; --extern mempool_t *cifs_mid_poolp; -- - struct workqueue_struct *cifsiod_wq; - struct workqueue_struct *decrypt_wq; - struct workqueue_struct *fileinfo_put_wq; -@@ -674,6 +670,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) - seq_printf(s, ",backupgid=%u", - from_kgid_munged(&init_user_ns, - cifs_sb->ctx->backupgid)); -+ seq_show_option(s, "reparse", -+ cifs_reparse_type_str(cifs_sb->ctx->reparse_type)); - - seq_printf(s, ",rsize=%u", cifs_sb->ctx->rsize); - seq_printf(s, ",wsize=%u", cifs_sb->ctx->wsize); -@@ -682,6 +680,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) - seq_printf(s, ",rasize=%u", cifs_sb->ctx->rasize); - if (tcon->ses->server->min_offload) - seq_printf(s, ",esize=%u", tcon->ses->server->min_offload); -+ if (tcon->ses->server->retrans) -+ seq_printf(s, ",retrans=%u", tcon->ses->server->retrans); - seq_printf(s, ",echo_interval=%lu", - tcon->ses->server->echo_interval / HZ); - -@@ -739,6 +739,8 @@ static void cifs_umount_begin(struct super_block *sb) - - spin_lock(&cifs_tcp_ses_lock); - spin_lock(&tcon->tc_lock); -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, -+ netfs_trace_tcon_ref_see_umount); - if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) { - /* we have other mounts to same share or we have - already tried to umount this and woken up -diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h -index b598c7ed497bb..c146f83eba9b4 100644 ---- a/fs/smb/client/cifsglob.h -+++ b/fs/smb/client/cifsglob.h -@@ -49,6 +49,11 @@ - */ - #define CIFS_DEF_ACTIMEO (1 * HZ) - -+/* -+ * max sleep time before retry to server -+ */ -+#define CIFS_MAX_SLEEP 2000 -+ - /* - * max attribute cache timeout (jiffies) - 2^30 - */ -@@ -148,6 +153,24 @@ enum securityEnum { - Kerberos, /* Kerberos via SPNEGO */ - }; - -+enum cifs_reparse_type { -+ CIFS_REPARSE_TYPE_NFS, -+ CIFS_REPARSE_TYPE_WSL, -+ CIFS_REPARSE_TYPE_DEFAULT = CIFS_REPARSE_TYPE_NFS, -+}; -+ -+static inline const char *cifs_reparse_type_str(enum cifs_reparse_type type) -+{ -+ switch (type) { -+ case CIFS_REPARSE_TYPE_NFS: -+ return "nfs"; -+ case CIFS_REPARSE_TYPE_WSL: -+ return "wsl"; -+ default: -+ return "unknown"; -+ } -+} -+ - struct session_key { - unsigned int len; - char *response; -@@ -192,37 +215,30 @@ struct cifs_open_info_data { - bool symlink; - }; - struct { -+ /* ioctl response buffer */ -+ struct { -+ int buftype; -+ struct kvec iov; -+ } io; - __u32 tag; - union { - struct reparse_data_buffer *buf; - struct reparse_posix_data *posix; - }; - } reparse; -+ struct { -+ __u8 eas[SMB2_WSL_MAX_QUERY_EA_RESP_SIZE]; -+ unsigned int eas_len; -+ } wsl; - char *symlink_target; -+ struct cifs_sid posix_owner; -+ struct cifs_sid posix_group; - union { - struct smb2_file_all_info fi; - struct smb311_posix_qinfo posix_fi; - }; - }; - --static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data) --{ -- struct smb2_file_all_info *fi = &data->fi; -- u32 attrs = le32_to_cpu(fi->Attributes); -- bool ret; -- -- ret = data->reparse_point || (attrs & ATTR_REPARSE); -- if (ret) -- attrs |= ATTR_REPARSE; -- fi->Attributes = cpu_to_le32(attrs); -- return ret; --} -- --static inline void cifs_free_open_info(struct cifs_open_info_data *data) --{ -- kfree(data->symlink_target); --} -- - /* - ***************************************************************** - * Except the CIFS PDUs themselves all the -@@ -367,7 +383,8 @@ struct smb_version_operations { - struct cifs_open_info_data *data); - /* set size by path */ - int (*set_path_size)(const unsigned int, struct cifs_tcon *, -- const char *, __u64, struct cifs_sb_info *, bool); -+ const char *, __u64, struct cifs_sb_info *, bool, -+ struct dentry *); - /* set size by file handle */ - int (*set_file_size)(const unsigned int, struct cifs_tcon *, - struct cifsFileInfo *, __u64, bool); -@@ -397,7 +414,7 @@ struct smb_version_operations { - struct cifs_sb_info *); - /* unlink file */ - int (*unlink)(const unsigned int, struct cifs_tcon *, const char *, -- struct cifs_sb_info *); -+ struct cifs_sb_info *, struct dentry *); - /* open, rename and delete file */ - int (*rename_pending_delete)(const char *, struct dentry *, - const unsigned int); -@@ -577,6 +594,12 @@ struct smb_version_operations { - int (*parse_reparse_point)(struct cifs_sb_info *cifs_sb, - struct kvec *rsp_iov, - struct cifs_open_info_data *data); -+ int (*create_reparse_symlink)(const unsigned int xid, -+ struct inode *inode, -+ struct dentry *dentry, -+ struct cifs_tcon *tcon, -+ const char *full_path, -+ const char *symname); - }; - - struct smb_version_values { -@@ -748,7 +771,12 @@ struct TCP_Server_Info { - unsigned int max_read; - unsigned int max_write; - unsigned int min_offload; -- __le16 compress_algorithm; -+ unsigned int retrans; -+ struct { -+ bool requested; /* "compress" mount option set*/ -+ bool enabled; /* actually negotiated with server */ -+ __le16 alg; /* preferred alg negotiated with server */ -+ } compression; - __u16 signing_algorithm; - __le16 cipher_type; - /* save initital negprot hash */ -@@ -1162,6 +1190,7 @@ struct cifs_fattr { - */ - struct cifs_tcon { - struct list_head tcon_list; -+ int debug_id; /* Debugging for tracing */ - int tc_count; - struct list_head rlist; /* reconnect list */ - spinlock_t tc_lock; /* protect anything here that is not protected */ -@@ -1370,6 +1399,8 @@ struct cifs_open_parms { - struct cifs_fid *fid; - umode_t mode; - bool reconnect:1; -+ bool replay:1; /* indicates that this open is for a replay */ -+ struct kvec *ea_cctx; - }; - - struct cifs_fid { -@@ -1411,6 +1442,7 @@ struct cifsFileInfo { - bool invalidHandle:1; /* file closed via session abend */ - bool swapfile:1; - bool oplock_break_cancelled:1; -+ bool status_file_deleted:1; /* file has been deleted */ - bool offload:1; /* offload final part of _put to a wq */ - unsigned int oplock_epoch; /* epoch from the lease break */ - __u32 oplock_level; /* oplock/lease level from the lease break */ -@@ -1503,6 +1535,7 @@ struct cifs_writedata { - struct smbd_mr *mr; - #endif - struct cifs_credits credits; -+ bool replay; - }; - - /* -@@ -2080,6 +2113,8 @@ extern struct workqueue_struct *deferredclose_wq; - extern struct workqueue_struct *serverclose_wq; - extern __u32 cifs_lock_secret; - -+extern mempool_t *cifs_sm_req_poolp; -+extern mempool_t *cifs_req_poolp; - extern mempool_t *cifs_mid_poolp; - - /* Operations for different SMB versions */ -@@ -2270,10 +2305,21 @@ static inline void cifs_sg_set_buf(struct sg_table *sgtable, - } - } - -+#define CIFS_OPARMS(_cifs_sb, _tcon, _path, _da, _cd, _co, _mode) \ -+ ((struct cifs_open_parms) { \ -+ .tcon = _tcon, \ -+ .path = _path, \ -+ .desired_access = (_da), \ -+ .disposition = (_cd), \ -+ .create_options = cifs_create_options(_cifs_sb, (_co)), \ -+ .mode = (_mode), \ -+ .cifs_sb = _cifs_sb, \ -+ }) -+ - struct smb2_compound_vars { - struct cifs_open_parms oparms; -- struct kvec rsp_iov[3]; -- struct smb_rqst rqst[3]; -+ struct kvec rsp_iov[MAX_COMPOUND]; -+ struct smb_rqst rqst[MAX_COMPOUND]; - struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; - struct kvec qi_iov; - struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; -@@ -2281,6 +2327,7 @@ struct smb2_compound_vars { - struct kvec close_iov; - struct smb2_file_rename_info rename_info; - struct smb2_file_link_info link_info; -+ struct kvec ea_iov; - }; - - static inline bool cifs_ses_exiting(struct cifs_ses *ses) -diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h -index 1bdad33580b57..fbc358c09da3b 100644 ---- a/fs/smb/client/cifsproto.h -+++ b/fs/smb/client/cifsproto.h -@@ -210,11 +210,11 @@ extern struct inode *cifs_iget(struct super_block *sb, - int cifs_get_inode_info(struct inode **inode, const char *full_path, - struct cifs_open_info_data *data, struct super_block *sb, int xid, - const struct cifs_fid *fid); --bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, -- struct cifs_fattr *fattr, -- struct cifs_open_info_data *data); --extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path, -- struct super_block *sb, unsigned int xid); -+extern int smb311_posix_get_inode_info(struct inode **inode, -+ const char *full_path, -+ struct cifs_open_info_data *data, -+ struct super_block *sb, -+ const unsigned int xid); - extern int cifs_get_inode_info_unix(struct inode **pinode, - const unsigned char *search_path, - struct super_block *sb, unsigned int xid); -@@ -294,12 +294,16 @@ extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon); - - extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon, - const char *path); -+ -+extern void cifs_mark_open_handles_for_deleted_file(struct inode *inode, -+ const char *path); -+ - extern struct TCP_Server_Info * - cifs_get_tcp_session(struct smb3_fs_context *ctx, - struct TCP_Server_Info *primary_server); - extern void cifs_put_tcp_session(struct TCP_Server_Info *server, - int from_reconnect); --extern void cifs_put_tcon(struct cifs_tcon *tcon); -+extern void cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace); - - extern void cifs_release_automount_timer(void); - -@@ -400,7 +404,8 @@ extern int CIFSSMBSetFileDisposition(const unsigned int xid, - __u32 pid_of_opener); - extern int CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, - const char *file_name, __u64 size, -- struct cifs_sb_info *cifs_sb, bool set_allocation); -+ struct cifs_sb_info *cifs_sb, bool set_allocation, -+ struct dentry *dentry); - extern int CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, - struct cifsFileInfo *cfile, __u64 size, - bool set_allocation); -@@ -436,7 +441,8 @@ extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon, - const struct nls_table *nls_codepage, - int remap_special_chars); - extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, -- const char *name, struct cifs_sb_info *cifs_sb); -+ const char *name, struct cifs_sb_info *cifs_sb, -+ struct dentry *dentry); - int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, - struct dentry *source_dentry, - const char *from_name, const char *to_name, -@@ -524,8 +530,9 @@ extern int CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses); - - extern struct cifs_ses *sesInfoAlloc(void); - extern void sesInfoFree(struct cifs_ses *); --extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled); --extern void tconInfoFree(struct cifs_tcon *); -+extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled, -+ enum smb3_tcon_ref_trace trace); -+extern void tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace); - - extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server, - __u32 *pexpected_response_sequence_number); -@@ -673,6 +680,9 @@ char *extract_sharename(const char *unc); - int parse_reparse_point(struct reparse_data_buffer *buf, - u32 plen, struct cifs_sb_info *cifs_sb, - bool unicode, struct cifs_open_info_data *data); -+int cifs_sfu_make_node(unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, umode_t mode, dev_t dev); - - #ifdef CONFIG_CIFS_DFS_UPCALL - static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, -@@ -712,8 +722,6 @@ static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options) - return options; - } - --struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon); --void cifs_put_tcon_super(struct super_block *sb); - int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry); - - /* Put references of @ses and its children */ -@@ -762,4 +770,11 @@ static inline void release_mid(struct mid_q_entry *mid) - kref_put(&mid->refcount, __release_mid); - } - -+static inline void cifs_free_open_info(struct cifs_open_info_data *data) -+{ -+ kfree(data->symlink_target); -+ free_rsp_buf(data->reparse.io.buftype, data->reparse.io.iov.iov_base); -+ memset(data, 0, sizeof(*data)); -+} -+ - #endif /* _CIFSPROTO_H */ -diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c -index e9e33b0b3ac47..301189ee1335b 100644 ---- a/fs/smb/client/cifssmb.c -+++ b/fs/smb/client/cifssmb.c -@@ -738,7 +738,7 @@ CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon, - - int - CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name, -- struct cifs_sb_info *cifs_sb) -+ struct cifs_sb_info *cifs_sb, struct dentry *dentry) - { - DELETE_FILE_REQ *pSMB = NULL; - DELETE_FILE_RSP *pSMBr = NULL; -@@ -2700,11 +2700,12 @@ int cifs_query_reparse_point(const unsigned int xid, - u32 *tag, struct kvec *rsp, - int *rsp_buftype) - { -+ struct reparse_data_buffer *buf; - struct cifs_open_parms oparms; - TRANSACT_IOCTL_REQ *io_req = NULL; - TRANSACT_IOCTL_RSP *io_rsp = NULL; - struct cifs_fid fid; -- __u32 data_offset, data_count; -+ __u32 data_offset, data_count, len; - __u8 *start, *end; - int io_rsp_len; - int oplock = 0; -@@ -2774,7 +2775,16 @@ int cifs_query_reparse_point(const unsigned int xid, - goto error; - } - -- *tag = le32_to_cpu(((struct reparse_data_buffer *)start)->ReparseTag); -+ data_count = le16_to_cpu(io_rsp->ByteCount); -+ buf = (struct reparse_data_buffer *)start; -+ len = sizeof(*buf); -+ if (data_count < len || -+ data_count < le16_to_cpu(buf->ReparseDataLength) + len) { -+ rc = -EIO; -+ goto error; -+ } -+ -+ *tag = le32_to_cpu(buf->ReparseTag); - rsp->iov_base = io_rsp; - rsp->iov_len = io_rsp_len; - *rsp_buftype = CIFS_LARGE_BUFFER; -@@ -4983,7 +4993,7 @@ CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon, - int - CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, - const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb, -- bool set_allocation) -+ bool set_allocation, struct dentry *dentry) - { - struct smb_com_transaction2_spi_req *pSMB = NULL; - struct smb_com_transaction2_spi_rsp *pSMBr = NULL; -diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c -index cb3bed8364e07..7a16e12f5da87 100644 ---- a/fs/smb/client/connect.c -+++ b/fs/smb/client/connect.c -@@ -52,9 +52,6 @@ - #include "fs_context.h" - #include "cifs_swn.h" - --extern mempool_t *cifs_req_poolp; --extern bool disable_legacy_dialects; -- - /* FIXME: should these be tunable? */ - #define TLINK_ERROR_EXPIRE (1 * HZ) - #define TLINK_IDLE_EXPIRE (600 * HZ) -@@ -501,6 +498,7 @@ static int reconnect_target_unlocked(struct TCP_Server_Info *server, struct dfs_ - static int reconnect_dfs_server(struct TCP_Server_Info *server) - { - struct dfs_cache_tgt_iterator *target_hint = NULL; -+ - DFS_CACHE_TGT_LIST(tl); - int num_targets = 0; - int rc = 0; -@@ -763,6 +761,7 @@ cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, - { - struct msghdr smb_msg = {}; - struct kvec iov = {.iov_base = buf, .iov_len = to_read}; -+ - iov_iter_kvec(&smb_msg.msg_iter, ITER_DEST, &iov, 1, to_read); - - return cifs_readv_from_socket(server, &smb_msg); -@@ -1418,11 +1417,13 @@ cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs) - case AF_INET: { - struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr; - struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs; -+ - return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr); - } - case AF_INET6: { - struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr; - struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs; -+ - return (ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr) - && saddr6->sin6_scope_id == vaddr6->sin6_scope_id); - } -@@ -1588,6 +1589,9 @@ static int match_server(struct TCP_Server_Info *server, - if (server->min_offload != ctx->min_offload) - return 0; - -+ if (server->retrans != ctx->retrans) -+ return 0; -+ - return 1; - } - -@@ -1741,7 +1745,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, - tcp_ses->channel_sequence_num = 0; /* only tracked for primary channel */ - tcp_ses->reconnect_instance = 1; - tcp_ses->lstrp = jiffies; -- tcp_ses->compress_algorithm = cpu_to_le16(ctx->compression); -+ tcp_ses->compression.requested = ctx->compress; - spin_lock_init(&tcp_ses->req_lock); - spin_lock_init(&tcp_ses->srv_lock); - spin_lock_init(&tcp_ses->mid_lock); -@@ -1812,6 +1816,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, - goto out_err_crypto_release; - } - tcp_ses->min_offload = ctx->min_offload; -+ tcp_ses->retrans = ctx->retrans; - /* - * at this point we are the only ones with the pointer - * to the struct since the kernel thread not created yet -@@ -1938,7 +1943,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx) - } - - /* no need to setup directory caching on IPC share, so pass in false */ -- tcon = tcon_info_alloc(false); -+ tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_ipc); - if (tcon == NULL) - return -ENOMEM; - -@@ -1955,7 +1960,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx) - - if (rc) { - cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc); -- tconInfoFree(tcon); -+ tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc_fail); - goto out; - } - -@@ -2038,7 +2043,7 @@ void __cifs_put_smb_ses(struct cifs_ses *ses) - * files on session close, as specified in MS-SMB2 3.3.5.6 Receiving an - * SMB2 LOGOFF Request. - */ -- tconInfoFree(tcon); -+ tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc); - if (do_logoff) { - xid = get_xid(); - rc = server->ops->logoff(xid, ses); -@@ -2427,6 +2432,8 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) - continue; - } - ++tcon->tc_count; -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, -+ netfs_trace_tcon_ref_get_find); - spin_unlock(&tcon->tc_lock); - spin_unlock(&cifs_tcp_ses_lock); - return tcon; -@@ -2436,7 +2443,7 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) - } - - void --cifs_put_tcon(struct cifs_tcon *tcon) -+cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace) - { - unsigned int xid; - struct cifs_ses *ses; -@@ -2452,6 +2459,7 @@ cifs_put_tcon(struct cifs_tcon *tcon) - cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count); - spin_lock(&cifs_tcp_ses_lock); - spin_lock(&tcon->tc_lock); -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count - 1, trace); - if (--tcon->tc_count > 0) { - spin_unlock(&tcon->tc_lock); - spin_unlock(&cifs_tcp_ses_lock); -@@ -2488,7 +2496,7 @@ cifs_put_tcon(struct cifs_tcon *tcon) - _free_xid(xid); - - cifs_fscache_release_super_cookie(tcon); -- tconInfoFree(tcon); -+ tconInfoFree(tcon, netfs_trace_tcon_ref_free); - cifs_put_smb_ses(ses); - } - -@@ -2542,7 +2550,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) - nohandlecache = ctx->nohandlecache; - else - nohandlecache = true; -- tcon = tcon_info_alloc(!nohandlecache); -+ tcon = tcon_info_alloc(!nohandlecache, netfs_trace_tcon_ref_new); - if (tcon == NULL) { - rc = -ENOMEM; - goto out_fail; -@@ -2607,8 +2615,8 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) - rc = -EOPNOTSUPP; - goto out_fail; - } else { -- cifs_dbg(VFS, "Check vers= mount option. SMB3.11 " -- "disabled but required for POSIX extensions\n"); -+ cifs_dbg(VFS, -+ "Check vers= mount option. SMB3.11 disabled but required for POSIX extensions\n"); - rc = -EOPNOTSUPP; - goto out_fail; - } -@@ -2732,7 +2740,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) - return tcon; - - out_fail: -- tconInfoFree(tcon); -+ tconInfoFree(tcon, netfs_trace_tcon_ref_free_fail); - return ERR_PTR(rc); - } - -@@ -2749,9 +2757,8 @@ cifs_put_tlink(struct tcon_link *tlink) - } - - if (!IS_ERR(tlink_tcon(tlink))) -- cifs_put_tcon(tlink_tcon(tlink)); -+ cifs_put_tcon(tlink_tcon(tlink), netfs_trace_tcon_ref_put_tlink); - kfree(tlink); -- return; - } - - static int -@@ -2798,6 +2805,8 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) - return 0; - if (old->ctx->closetimeo != new->ctx->closetimeo) - return 0; -+ if (old->ctx->reparse_type != new->ctx->reparse_type) -+ return 0; - - return 1; - } -@@ -2892,6 +2901,7 @@ static inline void - cifs_reclassify_socket4(struct socket *sock) - { - struct sock *sk = sock->sk; -+ - BUG_ON(!sock_allow_reclassification(sk)); - sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS", - &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]); -@@ -2901,6 +2911,7 @@ static inline void - cifs_reclassify_socket6(struct socket *sock) - { - struct sock *sk = sock->sk; -+ - BUG_ON(!sock_allow_reclassification(sk)); - sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS", - &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]); -@@ -2935,15 +2946,18 @@ static int - bind_socket(struct TCP_Server_Info *server) - { - int rc = 0; -+ - if (server->srcaddr.ss_family != AF_UNSPEC) { - /* Bind to the specified local IP address */ - struct socket *socket = server->ssocket; -+ - rc = kernel_bind(socket, - (struct sockaddr *) &server->srcaddr, - sizeof(server->srcaddr)); - if (rc < 0) { - struct sockaddr_in *saddr4; - struct sockaddr_in6 *saddr6; -+ - saddr4 = (struct sockaddr_in *)&server->srcaddr; - saddr6 = (struct sockaddr_in6 *)&server->srcaddr; - if (saddr6->sin6_family == AF_INET6) -@@ -3173,6 +3187,7 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon, - - if (!CIFSSMBQFSUnixInfo(xid, tcon)) { - __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability); -+ - cifs_dbg(FYI, "unix caps which server supports %lld\n", cap); - /* - * check for reconnect case in which we do not -@@ -3307,7 +3322,7 @@ void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx) - int rc = 0; - - if (mnt_ctx->tcon) -- cifs_put_tcon(mnt_ctx->tcon); -+ cifs_put_tcon(mnt_ctx->tcon, netfs_trace_tcon_ref_put_mnt_ctx); - else if (mnt_ctx->ses) - cifs_put_smb_ses(mnt_ctx->ses); - else if (mnt_ctx->server) -@@ -3698,7 +3713,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, - smb_buffer_response = smb_buffer; - - header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, -- NULL /*no tid */ , 4 /*wct */ ); -+ NULL /*no tid */, 4 /*wct */); - - smb_buffer->Mid = get_next_mid(ses->server); - smb_buffer->Uid = ses->Suid; -@@ -3717,12 +3732,12 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, - if (ses->server->sign) - smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - -- if (ses->capabilities & CAP_STATUS32) { -+ if (ses->capabilities & CAP_STATUS32) - smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; -- } -- if (ses->capabilities & CAP_DFS) { -+ -+ if (ses->capabilities & CAP_DFS) - smb_buffer->Flags2 |= SMBFLG2_DFS; -- } -+ - if (ses->capabilities & CAP_UNICODE) { - smb_buffer->Flags2 |= SMBFLG2_UNICODE; - length = -diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c -index 855468a32904e..864b194dbaa0a 100644 ---- a/fs/smb/client/dir.c -+++ b/fs/smb/client/dir.c -@@ -627,11 +627,18 @@ int cifs_mknod(struct mnt_idmap *idmap, struct inode *inode, - goto mknod_out; - } - -+ trace_smb3_mknod_enter(xid, tcon->ses->Suid, tcon->tid, full_path); -+ - rc = tcon->ses->server->ops->make_node(xid, inode, direntry, tcon, - full_path, mode, - device_number); - - mknod_out: -+ if (rc) -+ trace_smb3_mknod_err(xid, tcon->ses->Suid, tcon->tid, rc); -+ else -+ trace_smb3_mknod_done(xid, tcon->ses->Suid, tcon->tid); -+ - free_dentry_path(page); - free_xid(xid); - cifs_put_tlink(tlink); -@@ -695,9 +702,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, - full_path, d_inode(direntry)); - - again: -- if (pTcon->posix_extensions) -- rc = smb311_posix_get_inode_info(&newInode, full_path, parent_dir_inode->i_sb, xid); -- else if (pTcon->unix_ext) { -+ if (pTcon->posix_extensions) { -+ rc = smb311_posix_get_inode_info(&newInode, full_path, NULL, -+ parent_dir_inode->i_sb, xid); -+ } else if (pTcon->unix_ext) { - rc = cifs_get_inode_info_unix(&newInode, full_path, - parent_dir_inode->i_sb, xid); - } else { -diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c -index 53a8c633221b9..7ea8c3cf70f6c 100644 ---- a/fs/smb/client/file.c -+++ b/fs/smb/client/file.c -@@ -1102,14 +1102,16 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) - if (!is_interrupt_error(rc)) - mapping_set_error(inode->i_mapping, rc); - -- if (tcon->posix_extensions) -- rc = smb311_posix_get_inode_info(&inode, full_path, inode->i_sb, xid); -- else if (tcon->unix_ext) -+ if (tcon->posix_extensions) { -+ rc = smb311_posix_get_inode_info(&inode, full_path, -+ NULL, inode->i_sb, xid); -+ } else if (tcon->unix_ext) { - rc = cifs_get_inode_info_unix(&inode, full_path, - inode->i_sb, xid); -- else -+ } else { - rc = cifs_get_inode_info(&inode, full_path, NULL, - inode->i_sb, xid, NULL); -+ } - } - /* - * Else we are writing out data to server already and could deadlock if -@@ -1149,6 +1151,19 @@ void smb2_deferred_work_close(struct work_struct *work) - _cifsFileInfo_put(cfile, true, false); - } - -+static bool -+smb2_can_defer_close(struct inode *inode, struct cifs_deferred_close *dclose) -+{ -+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); -+ struct cifsInodeInfo *cinode = CIFS_I(inode); -+ -+ return (cifs_sb->ctx->closetimeo && cinode->lease_granted && dclose && -+ (cinode->oplock == CIFS_CACHE_RHW_FLG || -+ cinode->oplock == CIFS_CACHE_RH_FLG) && -+ !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags)); -+ -+} -+ - int cifs_close(struct inode *inode, struct file *file) - { - struct cifsFileInfo *cfile; -@@ -1162,10 +1177,8 @@ int cifs_close(struct inode *inode, struct file *file) - cfile = file->private_data; - file->private_data = NULL; - dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL); -- if ((cifs_sb->ctx->closetimeo && cinode->oplock == CIFS_CACHE_RHW_FLG) -- && cinode->lease_granted && -- !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) && -- dclose) { -+ if ((cfile->status_file_deleted == false) && -+ (smb2_can_defer_close(inode, dclose))) { - if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) { - inode_set_mtime_to_ts(inode, - inode_set_ctime_current(inode)); -@@ -3202,8 +3215,15 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, - if (rc > 0) { - spin_lock(&inode->i_lock); - if (pos > inode->i_size) { -+ loff_t additional_blocks = (512 - 1 + copied) >> 9; -+ - i_size_write(inode, pos); -- inode->i_blocks = (512 - 1 + pos) >> 9; -+ /* -+ * Estimate new allocation size based on the amount written. -+ * This will be updated from server on close (and on queryinfo) -+ */ -+ inode->i_blocks = min_t(blkcnt_t, (512 - 1 + pos) >> 9, -+ inode->i_blocks + additional_blocks); - } - spin_unlock(&inode->i_lock); - } -@@ -3411,6 +3431,7 @@ cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list, - if (wdata->cfile->invalidHandle) - rc = -EAGAIN; - else { -+ wdata->replay = true; - #ifdef CONFIG_CIFS_SMB_DIRECT - if (wdata->mr) { - wdata->mr->need_invalidate = true; -diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c -index 4d9e57be84dbc..3bbac925d0766 100644 ---- a/fs/smb/client/fs_context.c -+++ b/fs/smb/client/fs_context.c -@@ -139,6 +139,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { - fsparam_u32("dir_mode", Opt_dirmode), - fsparam_u32("port", Opt_port), - fsparam_u32("min_enc_offload", Opt_min_enc_offload), -+ fsparam_u32("retrans", Opt_retrans), - fsparam_u32("esize", Opt_min_enc_offload), - fsparam_u32("bsize", Opt_blocksize), - fsparam_u32("rasize", Opt_rasize), -@@ -174,6 +175,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { - fsparam_string("vers", Opt_vers), - fsparam_string("sec", Opt_sec), - fsparam_string("cache", Opt_cache), -+ fsparam_string("reparse", Opt_reparse), - - /* Arguments that should be ignored */ - fsparam_flag("guest", Opt_ignore), -@@ -296,6 +298,35 @@ cifs_parse_cache_flavor(struct fs_context *fc, char *value, struct smb3_fs_conte - return 0; - } - -+static const match_table_t reparse_flavor_tokens = { -+ { Opt_reparse_default, "default" }, -+ { Opt_reparse_nfs, "nfs" }, -+ { Opt_reparse_wsl, "wsl" }, -+ { Opt_reparse_err, NULL }, -+}; -+ -+static int parse_reparse_flavor(struct fs_context *fc, char *value, -+ struct smb3_fs_context *ctx) -+{ -+ substring_t args[MAX_OPT_ARGS]; -+ -+ switch (match_token(value, reparse_flavor_tokens, args)) { -+ case Opt_reparse_default: -+ ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT; -+ break; -+ case Opt_reparse_nfs: -+ ctx->reparse_type = CIFS_REPARSE_TYPE_NFS; -+ break; -+ case Opt_reparse_wsl: -+ ctx->reparse_type = CIFS_REPARSE_TYPE_WSL; -+ break; -+ default: -+ cifs_errorf(fc, "bad reparse= option: %s\n", value); -+ return 1; -+ } -+ return 0; -+} -+ - #define DUP_CTX_STR(field) \ - do { \ - if (ctx->field) { \ -@@ -947,7 +978,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, - - switch (opt) { - case Opt_compress: -- ctx->compression = UNKNOWN_TYPE; -+ ctx->compress = true; - cifs_dbg(VFS, - "SMB3 compression support is experimental\n"); - break; -@@ -1098,6 +1129,9 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, - case Opt_min_enc_offload: - ctx->min_offload = result.uint_32; - break; -+ case Opt_retrans: -+ ctx->retrans = result.uint_32; -+ break; - case Opt_blocksize: - /* - * inode blocksize realistically should never need to be -@@ -1591,6 +1625,10 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, - case Opt_rdma: - ctx->rdma = true; - break; -+ case Opt_reparse: -+ if (parse_reparse_flavor(fc, param->string, ctx)) -+ goto cifs_parse_mount_err; -+ break; - } - /* case Opt_ignore: - is ignored as expected ... */ - -@@ -1678,6 +1716,9 @@ int smb3_init_fs_context(struct fs_context *fc) - ctx->backupuid_specified = false; /* no backup intent for a user */ - ctx->backupgid_specified = false; /* no backup intent for a group */ - -+ ctx->retrans = 1; -+ ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT; -+ - /* - * short int override_uid = -1; - * short int override_gid = -1; -diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h -index d7c090dbe75db..cf577ec0dd0ac 100644 ---- a/fs/smb/client/fs_context.h -+++ b/fs/smb/client/fs_context.h -@@ -41,6 +41,13 @@ enum { - Opt_cache_err - }; - -+enum cifs_reparse_parm { -+ Opt_reparse_default, -+ Opt_reparse_nfs, -+ Opt_reparse_wsl, -+ Opt_reparse_err -+}; -+ - enum cifs_sec_param { - Opt_sec_krb5, - Opt_sec_krb5i, -@@ -118,6 +125,7 @@ enum cifs_param { - Opt_file_mode, - Opt_dirmode, - Opt_min_enc_offload, -+ Opt_retrans, - Opt_blocksize, - Opt_rasize, - Opt_rsize, -@@ -148,6 +156,7 @@ enum cifs_param { - Opt_vers, - Opt_sec, - Opt_cache, -+ Opt_reparse, - - /* Mount options to be ignored */ - Opt_ignore, -@@ -249,6 +258,7 @@ struct smb3_fs_context { - unsigned int rsize; - unsigned int wsize; - unsigned int min_offload; -+ unsigned int retrans; - bool sockopt_tcp_nodelay:1; - /* attribute cache timemout for files and directories in jiffies */ - unsigned long acregmax; -@@ -267,12 +277,13 @@ struct smb3_fs_context { - unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */ - unsigned int max_channels; - unsigned int max_cached_dirs; -- __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */ -+ bool compress; /* enable SMB2 messages (READ/WRITE) de/compression */ - bool rootfs:1; /* if it's a SMB root file system */ - bool witness:1; /* use witness protocol */ - char *leaf_fullpath; - struct cifs_ses *dfs_root_ses; - bool dfs_automount:1; /* set for dfs automount only */ -+ enum cifs_reparse_type reparse_type; - }; - - extern const struct fs_parameter_spec smb3_fs_parameters[]; -diff --git a/fs/smb/client/fscache.c b/fs/smb/client/fscache.c -index ecabc4b400535..98c5eebdc7b2f 100644 ---- a/fs/smb/client/fscache.c -+++ b/fs/smb/client/fscache.c -@@ -94,6 +94,11 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) - } - pr_err("Cache volume key already in use (%s)\n", key); - vcookie = NULL; -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, -+ netfs_trace_tcon_ref_see_fscache_collision); -+ } else { -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, -+ netfs_trace_tcon_ref_see_fscache_okay); - } - - tcon->fscache = vcookie; -@@ -115,6 +120,8 @@ void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) - cifs_fscache_fill_volume_coherency(tcon, &cd); - fscache_relinquish_volume(tcon->fscache, &cd, false); - tcon->fscache = NULL; -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, -+ netfs_trace_tcon_ref_see_fscache_relinq); - } - - void cifs_fscache_get_inode_cookie(struct inode *inode) -diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c -index fa6330d586e89..9cdbc3ccc1d14 100644 ---- a/fs/smb/client/inode.c -+++ b/fs/smb/client/inode.c -@@ -26,6 +26,7 @@ - #include "fs_context.h" - #include "cifs_ioctl.h" - #include "cached_dir.h" -+#include "reparse.h" - - static void cifs_set_ops(struct inode *inode) - { -@@ -400,7 +401,6 @@ cifs_get_file_info_unix(struct file *filp) - cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb); - } else if (rc == -EREMOTE) { - cifs_create_junction_fattr(&fattr, inode->i_sb); -- rc = 0; - } else - goto cifs_gfiunix_out; - -@@ -666,8 +666,6 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, - /* Fill a cifs_fattr struct with info from POSIX info struct */ - static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, - struct cifs_open_info_data *data, -- struct cifs_sid *owner, -- struct cifs_sid *group, - struct super_block *sb) - { - struct smb311_posix_qinfo *info = &data->posix_fi; -@@ -693,114 +691,43 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, - fattr->cf_mtime.tv_sec += tcon->ses->server->timeAdj; - } - -+ /* -+ * The srv fs device id is overridden on network mount so setting -+ * @fattr->cf_rdev isn't needed here. -+ */ - fattr->cf_eof = le64_to_cpu(info->EndOfFile); - fattr->cf_bytes = le64_to_cpu(info->AllocationSize); - fattr->cf_createtime = le64_to_cpu(info->CreationTime); -- - fattr->cf_nlink = le32_to_cpu(info->HardLinks); - fattr->cf_mode = (umode_t) le32_to_cpu(info->Mode); -- /* The srv fs device id is overridden on network mount so setting rdev isn't needed here */ -- /* fattr->cf_rdev = le32_to_cpu(info->DeviceId); */ - -- if (data->symlink) { -- fattr->cf_mode |= S_IFLNK; -- fattr->cf_dtype = DT_LNK; -- fattr->cf_symlink_target = data->symlink_target; -- data->symlink_target = NULL; -- } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { -+ if (cifs_open_data_reparse(data) && -+ cifs_reparse_point_to_fattr(cifs_sb, fattr, data)) -+ goto out_reparse; -+ -+ fattr->cf_mode &= ~S_IFMT; -+ if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { - fattr->cf_mode |= S_IFDIR; - fattr->cf_dtype = DT_DIR; - } else { /* file */ - fattr->cf_mode |= S_IFREG; - fattr->cf_dtype = DT_REG; - } -- /* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */ - -- sid_to_id(cifs_sb, owner, fattr, SIDOWNER); -- sid_to_id(cifs_sb, group, fattr, SIDGROUP); -+out_reparse: -+ if (S_ISLNK(fattr->cf_mode)) { -+ if (likely(data->symlink_target)) -+ fattr->cf_eof = strnlen(data->symlink_target, PATH_MAX); -+ fattr->cf_symlink_target = data->symlink_target; -+ data->symlink_target = NULL; -+ } -+ sid_to_id(cifs_sb, &data->posix_owner, fattr, SIDOWNER); -+ sid_to_id(cifs_sb, &data->posix_group, fattr, SIDGROUP); - - cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n", - fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink); - } - --static inline dev_t nfs_mkdev(struct reparse_posix_data *buf) --{ -- u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer); -- -- return MKDEV(v >> 32, v & 0xffffffff); --} -- --bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, -- struct cifs_fattr *fattr, -- struct cifs_open_info_data *data) --{ -- struct reparse_posix_data *buf = data->reparse.posix; -- u32 tag = data->reparse.tag; -- -- if (tag == IO_REPARSE_TAG_NFS && buf) { -- switch (le64_to_cpu(buf->InodeType)) { -- case NFS_SPECFILE_CHR: -- fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode; -- fattr->cf_dtype = DT_CHR; -- fattr->cf_rdev = nfs_mkdev(buf); -- break; -- case NFS_SPECFILE_BLK: -- fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode; -- fattr->cf_dtype = DT_BLK; -- fattr->cf_rdev = nfs_mkdev(buf); -- break; -- case NFS_SPECFILE_FIFO: -- fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode; -- fattr->cf_dtype = DT_FIFO; -- break; -- case NFS_SPECFILE_SOCK: -- fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode; -- fattr->cf_dtype = DT_SOCK; -- break; -- case NFS_SPECFILE_LNK: -- fattr->cf_mode = S_IFLNK | cifs_sb->ctx->file_mode; -- fattr->cf_dtype = DT_LNK; -- break; -- default: -- WARN_ON_ONCE(1); -- return false; -- } -- return true; -- } -- -- switch (tag) { -- case IO_REPARSE_TAG_LX_SYMLINK: -- fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode; -- fattr->cf_dtype = DT_LNK; -- break; -- case IO_REPARSE_TAG_LX_FIFO: -- fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode; -- fattr->cf_dtype = DT_FIFO; -- break; -- case IO_REPARSE_TAG_AF_UNIX: -- fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode; -- fattr->cf_dtype = DT_SOCK; -- break; -- case IO_REPARSE_TAG_LX_CHR: -- fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode; -- fattr->cf_dtype = DT_CHR; -- break; -- case IO_REPARSE_TAG_LX_BLK: -- fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode; -- fattr->cf_dtype = DT_BLK; -- break; -- case 0: /* SMB1 symlink */ -- case IO_REPARSE_TAG_SYMLINK: -- case IO_REPARSE_TAG_NFS: -- fattr->cf_mode = S_IFLNK | cifs_sb->ctx->file_mode; -- fattr->cf_dtype = DT_LNK; -- break; -- default: -- return false; -- } -- return true; --} -- - static void cifs_open_info_to_fattr(struct cifs_fattr *fattr, - struct cifs_open_info_data *data, - struct super_block *sb) -@@ -831,7 +758,10 @@ static void cifs_open_info_to_fattr(struct cifs_fattr *fattr, - fattr->cf_bytes = le64_to_cpu(info->AllocationSize); - fattr->cf_createtime = le64_to_cpu(info->CreationTime); - fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); -+ fattr->cf_uid = cifs_sb->ctx->linux_uid; -+ fattr->cf_gid = cifs_sb->ctx->linux_gid; - -+ fattr->cf_mode = cifs_sb->ctx->file_mode; - if (cifs_open_data_reparse(data) && - cifs_reparse_point_to_fattr(cifs_sb, fattr, data)) - goto out_reparse; -@@ -872,9 +802,6 @@ static void cifs_open_info_to_fattr(struct cifs_fattr *fattr, - fattr->cf_symlink_target = data->symlink_target; - data->symlink_target = NULL; - } -- -- fattr->cf_uid = cifs_sb->ctx->linux_uid; -- fattr->cf_gid = cifs_sb->ctx->linux_gid; - } - - static int -@@ -888,9 +815,14 @@ cifs_get_file_info(struct file *filp) - struct cifsFileInfo *cfile = filp->private_data; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - struct TCP_Server_Info *server = tcon->ses->server; -+ struct dentry *dentry = filp->f_path.dentry; -+ void *page = alloc_dentry_path(); -+ const unsigned char *path; - -- if (!server->ops->query_file_info) -+ if (!server->ops->query_file_info) { -+ free_dentry_path(page); - return -ENOSYS; -+ } - - xid = get_xid(); - rc = server->ops->query_file_info(xid, tcon, cfile, &data); -@@ -902,11 +834,17 @@ cifs_get_file_info(struct file *filp) - data.symlink = true; - data.reparse.tag = IO_REPARSE_TAG_SYMLINK; - } -+ path = build_path_from_dentry(dentry, page); -+ if (IS_ERR(path)) { -+ rc = PTR_ERR(path); -+ goto cgfi_exit; -+ } - cifs_open_info_to_fattr(&fattr, &data, inode->i_sb); -+ if (fattr.cf_flags & CIFS_FATTR_DELETE_PENDING) -+ cifs_mark_open_handles_for_deleted_file(inode, path); - break; - case -EREMOTE: - cifs_create_junction_fattr(&fattr, inode->i_sb); -- rc = 0; - break; - case -EOPNOTSUPP: - case -EINVAL: -@@ -932,6 +870,7 @@ cifs_get_file_info(struct file *filp) - rc = cifs_fattr_to_inode(inode, &fattr, false); - cgfi_exit: - cifs_free_open_info(&data); -+ free_dentry_path(page); - free_xid(xid); - return rc; - } -@@ -1078,6 +1017,9 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, - &rsp_iov, &rsp_buftype); - if (!rc) - iov = &rsp_iov; -+ } else if (data->reparse.io.buftype != CIFS_NO_BUFFER && -+ data->reparse.io.iov.iov_base) { -+ iov = &data->reparse.io.iov; - } - - rc = -EOPNOTSUPP; -@@ -1094,16 +1036,20 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, - rc = 0; - goto out; - default: -- if (data->symlink_target) { -+ /* Check for cached reparse point data */ -+ if (data->symlink_target || data->reparse.buf) { - rc = 0; -- } else if (server->ops->parse_reparse_point) { -+ } else if (iov && server->ops->parse_reparse_point) { - rc = server->ops->parse_reparse_point(cifs_sb, - iov, data); - } - break; - } - -- cifs_open_info_to_fattr(fattr, data, sb); -+ if (tcon->posix_extensions) -+ smb311_posix_info_to_fattr(fattr, data, sb); -+ else -+ cifs_open_info_to_fattr(fattr, data, sb); - out: - fattr->cf_cifstag = data->reparse.tag; - free_rsp_buf(rsp_buftype, rsp_iov.iov_base); -@@ -1159,6 +1105,9 @@ static int cifs_get_fattr(struct cifs_open_info_data *data, - } else { - cifs_open_info_to_fattr(fattr, data, sb); - } -+ if (!rc && *inode && -+ (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)) -+ cifs_mark_open_handles_for_deleted_file(*inode, full_path); - break; - case -EREMOTE: - /* DFS link, no metadata available on this server */ -@@ -1293,31 +1242,34 @@ int cifs_get_inode_info(struct inode **inode, - return rc; - } - --static int smb311_posix_get_fattr(struct cifs_fattr *fattr, -+static int smb311_posix_get_fattr(struct cifs_open_info_data *data, -+ struct cifs_fattr *fattr, - const char *full_path, - struct super_block *sb, - const unsigned int xid) - { -- struct cifs_open_info_data data = {}; -+ struct cifs_open_info_data tmp_data = {}; -+ struct TCP_Server_Info *server; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct cifs_tcon *tcon; - struct tcon_link *tlink; -- struct cifs_sid owner, group; - int tmprc; -- int rc; -+ int rc = 0; - - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - tcon = tlink_tcon(tlink); -+ server = tcon->ses->server; - - /* -- * 1. Fetch file metadata -+ * 1. Fetch file metadata if not provided (data) - */ -- -- rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, -- full_path, &data, -- &owner, &group); -+ if (!data) { -+ rc = server->ops->query_path_info(xid, tcon, cifs_sb, -+ full_path, &tmp_data); -+ data = &tmp_data; -+ } - - /* - * 2. Convert it to internal cifs metadata (fattr) -@@ -1325,7 +1277,12 @@ static int smb311_posix_get_fattr(struct cifs_fattr *fattr, - - switch (rc) { - case 0: -- smb311_posix_info_to_fattr(fattr, &data, &owner, &group, sb); -+ if (cifs_open_data_reparse(data)) { -+ rc = reparse_info_to_fattr(data, sb, xid, tcon, -+ full_path, fattr); -+ } else { -+ smb311_posix_info_to_fattr(fattr, data, sb); -+ } - break; - case -EREMOTE: - /* DFS link, no metadata available on this server */ -@@ -1356,12 +1313,15 @@ static int smb311_posix_get_fattr(struct cifs_fattr *fattr, - - out: - cifs_put_tlink(tlink); -- cifs_free_open_info(&data); -+ cifs_free_open_info(data); - return rc; - } - --int smb311_posix_get_inode_info(struct inode **inode, const char *full_path, -- struct super_block *sb, const unsigned int xid) -+int smb311_posix_get_inode_info(struct inode **inode, -+ const char *full_path, -+ struct cifs_open_info_data *data, -+ struct super_block *sb, -+ const unsigned int xid) - { - struct cifs_fattr fattr = {}; - int rc; -@@ -1371,11 +1331,13 @@ int smb311_posix_get_inode_info(struct inode **inode, const char *full_path, - return 0; - } - -- rc = smb311_posix_get_fattr(&fattr, full_path, sb, xid); -+ rc = smb311_posix_get_fattr(data, &fattr, full_path, sb, xid); - if (rc) - goto out; - - rc = update_inode_info(sb, &fattr, inode); -+ if (!rc && fattr.cf_flags & CIFS_FATTR_DELETE_PENDING) -+ cifs_mark_open_handles_for_deleted_file(*inode, full_path); - out: - kfree(fattr.cf_symlink_target); - return rc; -@@ -1521,7 +1483,7 @@ struct inode *cifs_root_iget(struct super_block *sb) - - convert_delimiter(path, CIFS_DIR_SEP(cifs_sb)); - if (tcon->posix_extensions) -- rc = smb311_posix_get_fattr(&fattr, path, sb, xid); -+ rc = smb311_posix_get_fattr(NULL, &fattr, path, sb, xid); - else - rc = cifs_get_fattr(NULL, sb, xid, NULL, &fattr, &inode, path); - -@@ -1539,6 +1501,9 @@ struct inode *cifs_root_iget(struct super_block *sb) - goto out; - } - -+ if (!rc && fattr.cf_flags & CIFS_FATTR_DELETE_PENDING) -+ cifs_mark_open_handles_for_deleted_file(inode, path); -+ - if (rc && tcon->pipe) { - cifs_dbg(FYI, "ipc connection - fake read inode\n"); - spin_lock(&inode->i_lock); -@@ -1825,20 +1790,24 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) - goto psx_del_no_retry; - } - -- rc = server->ops->unlink(xid, tcon, full_path, cifs_sb); -+ rc = server->ops->unlink(xid, tcon, full_path, cifs_sb, dentry); - - psx_del_no_retry: - if (!rc) { -- if (inode) -+ if (inode) { -+ cifs_mark_open_handles_for_deleted_file(inode, full_path); - cifs_drop_nlink(inode); -+ } - } else if (rc == -ENOENT) { - d_drop(dentry); - } else if (rc == -EBUSY) { - if (server->ops->rename_pending_delete) { - rc = server->ops->rename_pending_delete(full_path, - dentry, xid); -- if (rc == 0) -+ if (rc == 0) { -+ cifs_mark_open_handles_for_deleted_file(inode, full_path); - cifs_drop_nlink(inode); -+ } - } - } else if ((rc == -EACCES) && (dosattr == 0) && inode) { - attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); -@@ -1894,16 +1863,18 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, - int rc = 0; - struct inode *inode = NULL; - -- if (tcon->posix_extensions) -- rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid); -+ if (tcon->posix_extensions) { -+ rc = smb311_posix_get_inode_info(&inode, full_path, -+ NULL, parent->i_sb, xid); - #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY -- else if (tcon->unix_ext) -+ } else if (tcon->unix_ext) { - rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb, - xid); - #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ -- else -+ } else { - rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb, - xid, NULL); -+ } - - if (rc) - return rc; -@@ -2585,13 +2556,15 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) - dentry, cifs_get_time(dentry), jiffies); - - again: -- if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions) -- rc = smb311_posix_get_inode_info(&inode, full_path, sb, xid); -- else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) -+ if (cifs_sb_master_tcon(CIFS_SB(sb))->posix_extensions) { -+ rc = smb311_posix_get_inode_info(&inode, full_path, -+ NULL, sb, xid); -+ } else if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) { - rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); -- else -+ } else { - rc = cifs_get_inode_info(&inode, full_path, NULL, sb, - xid, NULL); -+ } - if (rc == -EAGAIN && count++ < 10) - goto again; - out: -@@ -2772,7 +2745,7 @@ void cifs_setsize(struct inode *inode, loff_t offset) - - static int - cifs_set_file_size(struct inode *inode, struct iattr *attrs, -- unsigned int xid, const char *full_path) -+ unsigned int xid, const char *full_path, struct dentry *dentry) - { - int rc; - struct cifsFileInfo *open_file; -@@ -2823,7 +2796,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, - */ - if (server->ops->set_path_size) - rc = server->ops->set_path_size(xid, tcon, full_path, -- attrs->ia_size, cifs_sb, false); -+ attrs->ia_size, cifs_sb, false, dentry); - else - rc = -ENOSYS; - cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc); -@@ -2913,7 +2886,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) - rc = 0; - - if (attrs->ia_valid & ATTR_SIZE) { -- rc = cifs_set_file_size(inode, attrs, xid, full_path); -+ rc = cifs_set_file_size(inode, attrs, xid, full_path, direntry); - if (rc != 0) - goto out; - } -@@ -3079,7 +3052,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) - } - - if (attrs->ia_valid & ATTR_SIZE) { -- rc = cifs_set_file_size(inode, attrs, xid, full_path); -+ rc = cifs_set_file_size(inode, attrs, xid, full_path, direntry); - if (rc != 0) - goto cifs_setattr_exit; - } -diff --git a/fs/smb/client/ioctl.c b/fs/smb/client/ioctl.c -index 204dd7c47126e..855ac5a62edfa 100644 ---- a/fs/smb/client/ioctl.c -+++ b/fs/smb/client/ioctl.c -@@ -143,6 +143,7 @@ static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon, - - fsinf->version = 1; - fsinf->protocol_id = tcon->ses->server->vals->protocol_id; -+ fsinf->tcon_flags = tcon->Flags; - fsinf->device_characteristics = - le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics); - fsinf->device_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); -@@ -348,6 +349,11 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) - xid = get_xid(); - - cifs_dbg(FYI, "cifs ioctl 0x%x\n", command); -+ if (pSMBFile == NULL) -+ trace_smb3_ioctl(xid, 0, command); -+ else -+ trace_smb3_ioctl(xid, pSMBFile->fid.persistent_fid, command); -+ - switch (command) { - case FS_IOC_GETFLAGS: - if (pSMBFile == NULL) -diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c -index 6c4ae52ddc04f..d86da949a9190 100644 ---- a/fs/smb/client/link.c -+++ b/fs/smb/client/link.c -@@ -42,23 +42,11 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash) - - rc = cifs_alloc_hash("md5", &md5); - if (rc) -- goto symlink_hash_err; -+ return rc; - -- rc = crypto_shash_init(md5); -- if (rc) { -- cifs_dbg(VFS, "%s: Could not init md5 shash\n", __func__); -- goto symlink_hash_err; -- } -- rc = crypto_shash_update(md5, link_str, link_len); -- if (rc) { -- cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__); -- goto symlink_hash_err; -- } -- rc = crypto_shash_final(md5, md5_hash); -+ rc = crypto_shash_digest(md5, link_str, link_len, md5_hash); - if (rc) - cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__); -- --symlink_hash_err: - cifs_free_hash(&md5); - return rc; - } -@@ -581,6 +569,7 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode, - int rc = -EOPNOTSUPP; - unsigned int xid; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); -+ struct TCP_Server_Info *server; - struct tcon_link *tlink; - struct cifs_tcon *pTcon; - const char *full_path; -@@ -602,6 +591,7 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode, - goto symlink_exit; - } - pTcon = tlink_tcon(tlink); -+ server = cifs_pick_channel(pTcon->ses); - - full_path = build_path_from_dentry(direntry, page); - if (IS_ERR(full_path)) { -@@ -613,27 +603,32 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode, - cifs_dbg(FYI, "symname is %s\n", symname); - - /* BB what if DFS and this volume is on different share? BB */ -- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) -+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { - rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname); - #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY -- else if (pTcon->unix_ext) -+ } else if (pTcon->unix_ext) { - rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, - cifs_sb->local_nls, - cifs_remap(cifs_sb)); - #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ -- /* else -- rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName, -- cifs_sb_target->local_nls); */ -+ } else if (server->ops->create_reparse_symlink) { -+ rc = server->ops->create_reparse_symlink(xid, inode, direntry, -+ pTcon, full_path, -+ symname); -+ goto symlink_exit; -+ } - - if (rc == 0) { -- if (pTcon->posix_extensions) -- rc = smb311_posix_get_inode_info(&newinode, full_path, inode->i_sb, xid); -- else if (pTcon->unix_ext) -+ if (pTcon->posix_extensions) { -+ rc = smb311_posix_get_inode_info(&newinode, full_path, -+ NULL, inode->i_sb, xid); -+ } else if (pTcon->unix_ext) { - rc = cifs_get_inode_info_unix(&newinode, full_path, - inode->i_sb, xid); -- else -+ } else { - rc = cifs_get_inode_info(&newinode, full_path, NULL, - inode->i_sb, xid, NULL); -+ } - - if (rc != 0) { - cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n", -diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c -index d56959d02e36d..07c468ddb88a8 100644 ---- a/fs/smb/client/misc.c -+++ b/fs/smb/client/misc.c -@@ -27,9 +27,6 @@ - #include "fs_context.h" - #include "cached_dir.h" - --extern mempool_t *cifs_sm_req_poolp; --extern mempool_t *cifs_req_poolp; -- - /* The xid serves as a useful identifier for each incoming vfs request, - in a similar way to the mid which is useful to track each sent smb, - and CurrentXid can also provide a running counter (although it -@@ -114,9 +111,10 @@ sesInfoFree(struct cifs_ses *buf_to_free) - } - - struct cifs_tcon * --tcon_info_alloc(bool dir_leases_enabled) -+tcon_info_alloc(bool dir_leases_enabled, enum smb3_tcon_ref_trace trace) - { - struct cifs_tcon *ret_buf; -+ static atomic_t tcon_debug_id; - - ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL); - if (!ret_buf) -@@ -133,7 +131,8 @@ tcon_info_alloc(bool dir_leases_enabled) - - atomic_inc(&tconInfoAllocCount); - ret_buf->status = TID_NEW; -- ++ret_buf->tc_count; -+ ret_buf->debug_id = atomic_inc_return(&tcon_debug_id); -+ ret_buf->tc_count = 1; - spin_lock_init(&ret_buf->tc_lock); - INIT_LIST_HEAD(&ret_buf->openFileList); - INIT_LIST_HEAD(&ret_buf->tcon_list); -@@ -145,17 +144,19 @@ tcon_info_alloc(bool dir_leases_enabled) - #ifdef CONFIG_CIFS_FSCACHE - mutex_init(&ret_buf->fscache_lock); - #endif -+ trace_smb3_tcon_ref(ret_buf->debug_id, ret_buf->tc_count, trace); - - return ret_buf; - } - - void --tconInfoFree(struct cifs_tcon *tcon) -+tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace) - { - if (tcon == NULL) { - cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n"); - return; - } -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, trace); - free_cached_dirs(tcon->cfids); - atomic_dec(&tconInfoAllocCount); - kfree(tcon->nativeFileSystem); -@@ -853,6 +854,40 @@ cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path) - free_dentry_path(page); - } - -+/* -+ * If a dentry has been deleted, all corresponding open handles should know that -+ * so that we do not defer close them. -+ */ -+void cifs_mark_open_handles_for_deleted_file(struct inode *inode, -+ const char *path) -+{ -+ struct cifsFileInfo *cfile; -+ void *page; -+ const char *full_path; -+ struct cifsInodeInfo *cinode = CIFS_I(inode); -+ -+ page = alloc_dentry_path(); -+ spin_lock(&cinode->open_file_lock); -+ -+ /* -+ * note: we need to construct path from dentry and compare only if the -+ * inode has any hardlinks. When number of hardlinks is 1, we can just -+ * mark all open handles since they are going to be from the same file. -+ */ -+ if (inode->i_nlink > 1) { -+ list_for_each_entry(cfile, &cinode->openFileList, flist) { -+ full_path = build_path_from_dentry(cfile->dentry, page); -+ if (!IS_ERR(full_path) && strcmp(full_path, path) == 0) -+ cfile->status_file_deleted = true; -+ } -+ } else { -+ list_for_each_entry(cfile, &cinode->openFileList, flist) -+ cfile->status_file_deleted = true; -+ } -+ spin_unlock(&cinode->open_file_lock); -+ free_dentry_path(page); -+} -+ - /* parses DFS referral V3 structure - * caller is responsible for freeing target_nodes - * returns: -diff --git a/fs/smb/client/ntlmssp.h b/fs/smb/client/ntlmssp.h -index 2c5dde2ece588..875de43b72de3 100644 ---- a/fs/smb/client/ntlmssp.h -+++ b/fs/smb/client/ntlmssp.h -@@ -133,8 +133,8 @@ typedef struct _AUTHENTICATE_MESSAGE { - SECURITY_BUFFER WorkstationName; - SECURITY_BUFFER SessionKey; - __le32 NegotiateFlags; -- /* SECURITY_BUFFER for version info not present since we -- do not set the version is present flag */ -+ struct ntlmssp_version Version; -+ /* SECURITY_BUFFER */ - char UserString[]; - } __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE; - -diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c -index 56033e4e4bae9..06111d9f39500 100644 ---- a/fs/smb/client/readdir.c -+++ b/fs/smb/client/readdir.c -@@ -22,6 +22,7 @@ - #include "smb2proto.h" - #include "fs_context.h" - #include "cached_dir.h" -+#include "reparse.h" - - /* - * To be safe - for UCS to UTF-8 with strings loaded with the rare long -@@ -55,23 +56,6 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) - } - #endif /* DEBUG2 */ - --/* -- * Match a reparse point inode if reparse tag and ctime haven't changed. -- * -- * Windows Server updates ctime of reparse points when their data have changed. -- * The server doesn't allow changing reparse tags from existing reparse points, -- * though it's worth checking. -- */ --static inline bool reparse_inode_match(struct inode *inode, -- struct cifs_fattr *fattr) --{ -- struct timespec64 ctime = inode_get_ctime(inode); -- -- return (CIFS_I(inode)->cifsAttrs & ATTR_REPARSE) && -- CIFS_I(inode)->reparse_tag == fattr->cf_cifstag && -- timespec64_equal(&ctime, &fattr->cf_ctime); --} -- - /* - * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT - * -@@ -133,14 +117,16 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name, - * Query dir responses don't provide enough - * information about reparse points other than - * their reparse tags. Save an invalidation by -- * not clobbering the existing mode, size and -- * symlink target (if any) when reparse tag and -- * ctime haven't changed. -+ * not clobbering some existing attributes when -+ * reparse tag and ctime haven't changed. - */ - rc = 0; - if (fattr->cf_cifsattrs & ATTR_REPARSE) { - if (likely(reparse_inode_match(inode, fattr))) { - fattr->cf_mode = inode->i_mode; -+ fattr->cf_rdev = inode->i_rdev; -+ fattr->cf_uid = inode->i_uid; -+ fattr->cf_gid = inode->i_gid; - fattr->cf_eof = CIFS_I(inode)->server_eof; - fattr->cf_symlink_target = NULL; - } else { -@@ -647,10 +633,10 @@ static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode) - static int is_dir_changed(struct file *file) - { - struct inode *inode = file_inode(file); -- struct cifsInodeInfo *cifsInfo = CIFS_I(inode); -+ struct cifsInodeInfo *cifs_inode_info = CIFS_I(inode); - -- if (cifsInfo->time == 0) -- return 1; /* directory was changed, perhaps due to unlink */ -+ if (cifs_inode_info->time == 0) -+ return 1; /* directory was changed, e.g. unlink or new file */ - else - return 0; - -diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c -new file mode 100644 -index 0000000000000..a0ffbda907331 ---- /dev/null -+++ b/fs/smb/client/reparse.c -@@ -0,0 +1,532 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (c) 2024 Paulo Alcantara -+ */ -+ -+#include -+#include -+#include -+#include "cifsglob.h" -+#include "smb2proto.h" -+#include "cifsproto.h" -+#include "cifs_unicode.h" -+#include "cifs_debug.h" -+#include "fs_context.h" -+#include "reparse.h" -+ -+int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, const char *symname) -+{ -+ struct reparse_symlink_data_buffer *buf = NULL; -+ struct cifs_open_info_data data; -+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); -+ struct inode *new; -+ struct kvec iov; -+ __le16 *path; -+ char *sym, sep = CIFS_DIR_SEP(cifs_sb); -+ u16 len, plen; -+ int rc = 0; -+ -+ sym = kstrdup(symname, GFP_KERNEL); -+ if (!sym) -+ return -ENOMEM; -+ -+ data = (struct cifs_open_info_data) { -+ .reparse_point = true, -+ .reparse = { .tag = IO_REPARSE_TAG_SYMLINK, }, -+ .symlink_target = sym, -+ }; -+ -+ convert_delimiter(sym, sep); -+ path = cifs_convert_path_to_utf16(sym, cifs_sb); -+ if (!path) { -+ rc = -ENOMEM; -+ goto out; -+ } -+ -+ plen = 2 * UniStrnlen((wchar_t *)path, PATH_MAX); -+ len = sizeof(*buf) + plen * 2; -+ buf = kzalloc(len, GFP_KERNEL); -+ if (!buf) { -+ rc = -ENOMEM; -+ goto out; -+ } -+ -+ buf->ReparseTag = cpu_to_le32(IO_REPARSE_TAG_SYMLINK); -+ buf->ReparseDataLength = cpu_to_le16(len - sizeof(struct reparse_data_buffer)); -+ buf->SubstituteNameOffset = cpu_to_le16(plen); -+ buf->SubstituteNameLength = cpu_to_le16(plen); -+ memcpy(&buf->PathBuffer[plen], path, plen); -+ buf->PrintNameOffset = 0; -+ buf->PrintNameLength = cpu_to_le16(plen); -+ memcpy(buf->PathBuffer, path, plen); -+ buf->Flags = cpu_to_le32(*symname != '/' ? SYMLINK_FLAG_RELATIVE : 0); -+ if (*sym != sep) -+ buf->Flags = cpu_to_le32(SYMLINK_FLAG_RELATIVE); -+ -+ convert_delimiter(sym, '/'); -+ iov.iov_base = buf; -+ iov.iov_len = len; -+ new = smb2_get_reparse_inode(&data, inode->i_sb, xid, -+ tcon, full_path, &iov, NULL); -+ if (!IS_ERR(new)) -+ d_instantiate(dentry, new); -+ else -+ rc = PTR_ERR(new); -+out: -+ kfree(path); -+ cifs_free_open_info(&data); -+ kfree(buf); -+ return rc; -+} -+ -+static int nfs_set_reparse_buf(struct reparse_posix_data *buf, -+ mode_t mode, dev_t dev, -+ struct kvec *iov) -+{ -+ u64 type; -+ u16 len, dlen; -+ -+ len = sizeof(*buf); -+ -+ switch ((type = reparse_mode_nfs_type(mode))) { -+ case NFS_SPECFILE_BLK: -+ case NFS_SPECFILE_CHR: -+ dlen = sizeof(__le64); -+ break; -+ case NFS_SPECFILE_FIFO: -+ case NFS_SPECFILE_SOCK: -+ dlen = 0; -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ buf->ReparseTag = cpu_to_le32(IO_REPARSE_TAG_NFS); -+ buf->Reserved = 0; -+ buf->InodeType = cpu_to_le64(type); -+ buf->ReparseDataLength = cpu_to_le16(len + dlen - -+ sizeof(struct reparse_data_buffer)); -+ *(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MAJOR(dev) << 32) | -+ MINOR(dev)); -+ iov->iov_base = buf; -+ iov->iov_len = len + dlen; -+ return 0; -+} -+ -+static int mknod_nfs(unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, umode_t mode, dev_t dev) -+{ -+ struct cifs_open_info_data data; -+ struct reparse_posix_data *p; -+ struct inode *new; -+ struct kvec iov; -+ __u8 buf[sizeof(*p) + sizeof(__le64)]; -+ int rc; -+ -+ p = (struct reparse_posix_data *)buf; -+ rc = nfs_set_reparse_buf(p, mode, dev, &iov); -+ if (rc) -+ return rc; -+ -+ data = (struct cifs_open_info_data) { -+ .reparse_point = true, -+ .reparse = { .tag = IO_REPARSE_TAG_NFS, .posix = p, }, -+ }; -+ -+ new = smb2_get_reparse_inode(&data, inode->i_sb, xid, -+ tcon, full_path, &iov, NULL); -+ if (!IS_ERR(new)) -+ d_instantiate(dentry, new); -+ else -+ rc = PTR_ERR(new); -+ cifs_free_open_info(&data); -+ return rc; -+} -+ -+static int wsl_set_reparse_buf(struct reparse_data_buffer *buf, -+ mode_t mode, struct kvec *iov) -+{ -+ u32 tag; -+ -+ switch ((tag = reparse_mode_wsl_tag(mode))) { -+ case IO_REPARSE_TAG_LX_BLK: -+ case IO_REPARSE_TAG_LX_CHR: -+ case IO_REPARSE_TAG_LX_FIFO: -+ case IO_REPARSE_TAG_AF_UNIX: -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ buf->ReparseTag = cpu_to_le32(tag); -+ buf->Reserved = 0; -+ buf->ReparseDataLength = 0; -+ iov->iov_base = buf; -+ iov->iov_len = sizeof(*buf); -+ return 0; -+} -+ -+static struct smb2_create_ea_ctx *ea_create_context(u32 dlen, size_t *cc_len) -+{ -+ struct smb2_create_ea_ctx *cc; -+ -+ *cc_len = round_up(sizeof(*cc) + dlen, 8); -+ cc = kzalloc(*cc_len, GFP_KERNEL); -+ if (!cc) -+ return ERR_PTR(-ENOMEM); -+ -+ cc->ctx.NameOffset = cpu_to_le16(offsetof(struct smb2_create_ea_ctx, -+ name)); -+ cc->ctx.NameLength = cpu_to_le16(4); -+ memcpy(cc->name, SMB2_CREATE_EA_BUFFER, strlen(SMB2_CREATE_EA_BUFFER)); -+ cc->ctx.DataOffset = cpu_to_le16(offsetof(struct smb2_create_ea_ctx, ea)); -+ cc->ctx.DataLength = cpu_to_le32(dlen); -+ return cc; -+} -+ -+struct wsl_xattr { -+ const char *name; -+ __le64 value; -+ u16 size; -+ u32 next; -+}; -+ -+static int wsl_set_xattrs(struct inode *inode, umode_t _mode, -+ dev_t _dev, struct kvec *iov) -+{ -+ struct smb2_file_full_ea_info *ea; -+ struct smb2_create_ea_ctx *cc; -+ struct smb3_fs_context *ctx = CIFS_SB(inode->i_sb)->ctx; -+ __le64 uid = cpu_to_le64(from_kuid(current_user_ns(), ctx->linux_uid)); -+ __le64 gid = cpu_to_le64(from_kgid(current_user_ns(), ctx->linux_gid)); -+ __le64 dev = cpu_to_le64(((u64)MINOR(_dev) << 32) | MAJOR(_dev)); -+ __le64 mode = cpu_to_le64(_mode); -+ struct wsl_xattr xattrs[] = { -+ { .name = SMB2_WSL_XATTR_UID, .value = uid, .size = SMB2_WSL_XATTR_UID_SIZE, }, -+ { .name = SMB2_WSL_XATTR_GID, .value = gid, .size = SMB2_WSL_XATTR_GID_SIZE, }, -+ { .name = SMB2_WSL_XATTR_MODE, .value = mode, .size = SMB2_WSL_XATTR_MODE_SIZE, }, -+ { .name = SMB2_WSL_XATTR_DEV, .value = dev, .size = SMB2_WSL_XATTR_DEV_SIZE, }, -+ }; -+ size_t cc_len; -+ u32 dlen = 0, next = 0; -+ int i, num_xattrs; -+ u8 name_size = SMB2_WSL_XATTR_NAME_LEN + 1; -+ -+ memset(iov, 0, sizeof(*iov)); -+ -+ /* Exclude $LXDEV xattr for sockets and fifos */ -+ if (S_ISSOCK(_mode) || S_ISFIFO(_mode)) -+ num_xattrs = ARRAY_SIZE(xattrs) - 1; -+ else -+ num_xattrs = ARRAY_SIZE(xattrs); -+ -+ for (i = 0; i < num_xattrs; i++) { -+ xattrs[i].next = ALIGN(sizeof(*ea) + name_size + -+ xattrs[i].size, 4); -+ dlen += xattrs[i].next; -+ } -+ -+ cc = ea_create_context(dlen, &cc_len); -+ if (IS_ERR(cc)) -+ return PTR_ERR(cc); -+ -+ ea = &cc->ea; -+ for (i = 0; i < num_xattrs; i++) { -+ ea = (void *)((u8 *)ea + next); -+ next = xattrs[i].next; -+ ea->next_entry_offset = cpu_to_le32(next); -+ -+ ea->ea_name_length = name_size - 1; -+ ea->ea_value_length = cpu_to_le16(xattrs[i].size); -+ memcpy(ea->ea_data, xattrs[i].name, name_size); -+ memcpy(&ea->ea_data[name_size], -+ &xattrs[i].value, xattrs[i].size); -+ } -+ ea->next_entry_offset = 0; -+ -+ iov->iov_base = cc; -+ iov->iov_len = cc_len; -+ return 0; -+} -+ -+static int mknod_wsl(unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, umode_t mode, dev_t dev) -+{ -+ struct cifs_open_info_data data; -+ struct reparse_data_buffer buf; -+ struct smb2_create_ea_ctx *cc; -+ struct inode *new; -+ unsigned int len; -+ struct kvec reparse_iov, xattr_iov; -+ int rc; -+ -+ rc = wsl_set_reparse_buf(&buf, mode, &reparse_iov); -+ if (rc) -+ return rc; -+ -+ rc = wsl_set_xattrs(inode, mode, dev, &xattr_iov); -+ if (rc) -+ return rc; -+ -+ data = (struct cifs_open_info_data) { -+ .reparse_point = true, -+ .reparse = { .tag = le32_to_cpu(buf.ReparseTag), .buf = &buf, }, -+ }; -+ -+ cc = xattr_iov.iov_base; -+ len = le32_to_cpu(cc->ctx.DataLength); -+ memcpy(data.wsl.eas, &cc->ea, len); -+ data.wsl.eas_len = len; -+ -+ new = smb2_get_reparse_inode(&data, inode->i_sb, -+ xid, tcon, full_path, -+ &reparse_iov, &xattr_iov); -+ if (!IS_ERR(new)) -+ d_instantiate(dentry, new); -+ else -+ rc = PTR_ERR(new); -+ cifs_free_open_info(&data); -+ kfree(xattr_iov.iov_base); -+ return rc; -+} -+ -+int smb2_mknod_reparse(unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, umode_t mode, dev_t dev) -+{ -+ struct smb3_fs_context *ctx = CIFS_SB(inode->i_sb)->ctx; -+ int rc = -EOPNOTSUPP; -+ -+ switch (ctx->reparse_type) { -+ case CIFS_REPARSE_TYPE_NFS: -+ rc = mknod_nfs(xid, inode, dentry, tcon, full_path, mode, dev); -+ break; -+ case CIFS_REPARSE_TYPE_WSL: -+ rc = mknod_wsl(xid, inode, dentry, tcon, full_path, mode, dev); -+ break; -+ } -+ return rc; -+} -+ -+/* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */ -+static int parse_reparse_posix(struct reparse_posix_data *buf, -+ struct cifs_sb_info *cifs_sb, -+ struct cifs_open_info_data *data) -+{ -+ unsigned int len; -+ u64 type; -+ -+ switch ((type = le64_to_cpu(buf->InodeType))) { -+ case NFS_SPECFILE_LNK: -+ len = le16_to_cpu(buf->ReparseDataLength); -+ data->symlink_target = cifs_strndup_from_utf16(buf->DataBuffer, -+ len, true, -+ cifs_sb->local_nls); -+ if (!data->symlink_target) -+ return -ENOMEM; -+ convert_delimiter(data->symlink_target, '/'); -+ cifs_dbg(FYI, "%s: target path: %s\n", -+ __func__, data->symlink_target); -+ break; -+ case NFS_SPECFILE_CHR: -+ case NFS_SPECFILE_BLK: -+ case NFS_SPECFILE_FIFO: -+ case NFS_SPECFILE_SOCK: -+ break; -+ default: -+ cifs_dbg(VFS, "%s: unhandled inode type: 0x%llx\n", -+ __func__, type); -+ return -EOPNOTSUPP; -+ } -+ return 0; -+} -+ -+static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym, -+ u32 plen, bool unicode, -+ struct cifs_sb_info *cifs_sb, -+ struct cifs_open_info_data *data) -+{ -+ unsigned int len; -+ unsigned int offs; -+ -+ /* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */ -+ -+ offs = le16_to_cpu(sym->SubstituteNameOffset); -+ len = le16_to_cpu(sym->SubstituteNameLength); -+ if (offs + 20 > plen || offs + len + 20 > plen) { -+ cifs_dbg(VFS, "srv returned malformed symlink buffer\n"); -+ return -EIO; -+ } -+ -+ data->symlink_target = cifs_strndup_from_utf16(sym->PathBuffer + offs, -+ len, unicode, -+ cifs_sb->local_nls); -+ if (!data->symlink_target) -+ return -ENOMEM; -+ -+ convert_delimiter(data->symlink_target, '/'); -+ cifs_dbg(FYI, "%s: target path: %s\n", __func__, data->symlink_target); -+ -+ return 0; -+} -+ -+int parse_reparse_point(struct reparse_data_buffer *buf, -+ u32 plen, struct cifs_sb_info *cifs_sb, -+ bool unicode, struct cifs_open_info_data *data) -+{ -+ data->reparse.buf = buf; -+ -+ /* See MS-FSCC 2.1.2 */ -+ switch (le32_to_cpu(buf->ReparseTag)) { -+ case IO_REPARSE_TAG_NFS: -+ return parse_reparse_posix((struct reparse_posix_data *)buf, -+ cifs_sb, data); -+ case IO_REPARSE_TAG_SYMLINK: -+ return parse_reparse_symlink( -+ (struct reparse_symlink_data_buffer *)buf, -+ plen, unicode, cifs_sb, data); -+ case IO_REPARSE_TAG_LX_SYMLINK: -+ case IO_REPARSE_TAG_AF_UNIX: -+ case IO_REPARSE_TAG_LX_FIFO: -+ case IO_REPARSE_TAG_LX_CHR: -+ case IO_REPARSE_TAG_LX_BLK: -+ return 0; -+ default: -+ cifs_dbg(VFS, "%s: unhandled reparse tag: 0x%08x\n", -+ __func__, le32_to_cpu(buf->ReparseTag)); -+ return -EOPNOTSUPP; -+ } -+} -+ -+int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, -+ struct kvec *rsp_iov, -+ struct cifs_open_info_data *data) -+{ -+ struct reparse_data_buffer *buf; -+ struct smb2_ioctl_rsp *io = rsp_iov->iov_base; -+ u32 plen = le32_to_cpu(io->OutputCount); -+ -+ buf = (struct reparse_data_buffer *)((u8 *)io + -+ le32_to_cpu(io->OutputOffset)); -+ return parse_reparse_point(buf, plen, cifs_sb, true, data); -+} -+ -+static void wsl_to_fattr(struct cifs_open_info_data *data, -+ struct cifs_sb_info *cifs_sb, -+ u32 tag, struct cifs_fattr *fattr) -+{ -+ struct smb2_file_full_ea_info *ea; -+ u32 next = 0; -+ -+ switch (tag) { -+ case IO_REPARSE_TAG_LX_SYMLINK: -+ fattr->cf_mode |= S_IFLNK; -+ break; -+ case IO_REPARSE_TAG_LX_FIFO: -+ fattr->cf_mode |= S_IFIFO; -+ break; -+ case IO_REPARSE_TAG_AF_UNIX: -+ fattr->cf_mode |= S_IFSOCK; -+ break; -+ case IO_REPARSE_TAG_LX_CHR: -+ fattr->cf_mode |= S_IFCHR; -+ break; -+ case IO_REPARSE_TAG_LX_BLK: -+ fattr->cf_mode |= S_IFBLK; -+ break; -+ } -+ -+ if (!data->wsl.eas_len) -+ goto out; -+ -+ ea = (struct smb2_file_full_ea_info *)data->wsl.eas; -+ do { -+ const char *name; -+ void *v; -+ u8 nlen; -+ -+ ea = (void *)((u8 *)ea + next); -+ next = le32_to_cpu(ea->next_entry_offset); -+ if (!le16_to_cpu(ea->ea_value_length)) -+ continue; -+ -+ name = ea->ea_data; -+ nlen = ea->ea_name_length; -+ v = (void *)((u8 *)ea->ea_data + ea->ea_name_length + 1); -+ -+ if (!strncmp(name, SMB2_WSL_XATTR_UID, nlen)) -+ fattr->cf_uid = wsl_make_kuid(cifs_sb, v); -+ else if (!strncmp(name, SMB2_WSL_XATTR_GID, nlen)) -+ fattr->cf_gid = wsl_make_kgid(cifs_sb, v); -+ else if (!strncmp(name, SMB2_WSL_XATTR_MODE, nlen)) -+ fattr->cf_mode = (umode_t)le32_to_cpu(*(__le32 *)v); -+ else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen)) -+ fattr->cf_rdev = wsl_mkdev(v); -+ } while (next); -+out: -+ fattr->cf_dtype = S_DT(fattr->cf_mode); -+} -+ -+bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, -+ struct cifs_fattr *fattr, -+ struct cifs_open_info_data *data) -+{ -+ struct reparse_posix_data *buf = data->reparse.posix; -+ u32 tag = data->reparse.tag; -+ -+ if (tag == IO_REPARSE_TAG_NFS && buf) { -+ switch (le64_to_cpu(buf->InodeType)) { -+ case NFS_SPECFILE_CHR: -+ fattr->cf_mode |= S_IFCHR; -+ fattr->cf_rdev = reparse_nfs_mkdev(buf); -+ break; -+ case NFS_SPECFILE_BLK: -+ fattr->cf_mode |= S_IFBLK; -+ fattr->cf_rdev = reparse_nfs_mkdev(buf); -+ break; -+ case NFS_SPECFILE_FIFO: -+ fattr->cf_mode |= S_IFIFO; -+ break; -+ case NFS_SPECFILE_SOCK: -+ fattr->cf_mode |= S_IFSOCK; -+ break; -+ case NFS_SPECFILE_LNK: -+ fattr->cf_mode |= S_IFLNK; -+ break; -+ default: -+ WARN_ON_ONCE(1); -+ return false; -+ } -+ goto out; -+ } -+ -+ switch (tag) { -+ case IO_REPARSE_TAG_DFS: -+ case IO_REPARSE_TAG_DFSR: -+ case IO_REPARSE_TAG_MOUNT_POINT: -+ /* See cifs_create_junction_fattr() */ -+ fattr->cf_mode = S_IFDIR | 0711; -+ break; -+ case IO_REPARSE_TAG_LX_SYMLINK: -+ case IO_REPARSE_TAG_LX_FIFO: -+ case IO_REPARSE_TAG_AF_UNIX: -+ case IO_REPARSE_TAG_LX_CHR: -+ case IO_REPARSE_TAG_LX_BLK: -+ wsl_to_fattr(data, cifs_sb, tag, fattr); -+ break; -+ case 0: /* SMB1 symlink */ -+ case IO_REPARSE_TAG_SYMLINK: -+ case IO_REPARSE_TAG_NFS: -+ fattr->cf_mode |= S_IFLNK; -+ break; -+ default: -+ return false; -+ } -+out: -+ fattr->cf_dtype = S_DT(fattr->cf_mode); -+ return true; -+} -diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h -new file mode 100644 -index 0000000000000..6b55d1df9e2f8 ---- /dev/null -+++ b/fs/smb/client/reparse.h -@@ -0,0 +1,113 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Copyright (c) 2024 Paulo Alcantara -+ */ -+ -+#ifndef _CIFS_REPARSE_H -+#define _CIFS_REPARSE_H -+ -+#include -+#include -+#include -+#include "fs_context.h" -+#include "cifsglob.h" -+ -+static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf) -+{ -+ u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer); -+ -+ return MKDEV(v >> 32, v & 0xffffffff); -+} -+ -+static inline dev_t wsl_mkdev(void *ptr) -+{ -+ u64 v = le64_to_cpu(*(__le64 *)ptr); -+ -+ return MKDEV(v & 0xffffffff, v >> 32); -+} -+ -+static inline kuid_t wsl_make_kuid(struct cifs_sb_info *cifs_sb, -+ void *ptr) -+{ -+ u32 uid = le32_to_cpu(*(__le32 *)ptr); -+ -+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) -+ return cifs_sb->ctx->linux_uid; -+ return make_kuid(current_user_ns(), uid); -+} -+ -+static inline kgid_t wsl_make_kgid(struct cifs_sb_info *cifs_sb, -+ void *ptr) -+{ -+ u32 gid = le32_to_cpu(*(__le32 *)ptr); -+ -+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) -+ return cifs_sb->ctx->linux_gid; -+ return make_kgid(current_user_ns(), gid); -+} -+ -+static inline u64 reparse_mode_nfs_type(mode_t mode) -+{ -+ switch (mode & S_IFMT) { -+ case S_IFBLK: return NFS_SPECFILE_BLK; -+ case S_IFCHR: return NFS_SPECFILE_CHR; -+ case S_IFIFO: return NFS_SPECFILE_FIFO; -+ case S_IFSOCK: return NFS_SPECFILE_SOCK; -+ } -+ return 0; -+} -+ -+static inline u32 reparse_mode_wsl_tag(mode_t mode) -+{ -+ switch (mode & S_IFMT) { -+ case S_IFBLK: return IO_REPARSE_TAG_LX_BLK; -+ case S_IFCHR: return IO_REPARSE_TAG_LX_CHR; -+ case S_IFIFO: return IO_REPARSE_TAG_LX_FIFO; -+ case S_IFSOCK: return IO_REPARSE_TAG_AF_UNIX; -+ } -+ return 0; -+} -+ -+/* -+ * Match a reparse point inode if reparse tag and ctime haven't changed. -+ * -+ * Windows Server updates ctime of reparse points when their data have changed. -+ * The server doesn't allow changing reparse tags from existing reparse points, -+ * though it's worth checking. -+ */ -+static inline bool reparse_inode_match(struct inode *inode, -+ struct cifs_fattr *fattr) -+{ -+ struct timespec64 ctime = inode_get_ctime(inode); -+ -+ return (CIFS_I(inode)->cifsAttrs & ATTR_REPARSE) && -+ CIFS_I(inode)->reparse_tag == fattr->cf_cifstag && -+ timespec64_equal(&ctime, &fattr->cf_ctime); -+} -+ -+static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data) -+{ -+ struct smb2_file_all_info *fi = &data->fi; -+ u32 attrs = le32_to_cpu(fi->Attributes); -+ bool ret; -+ -+ ret = data->reparse_point || (attrs & ATTR_REPARSE); -+ if (ret) -+ attrs |= ATTR_REPARSE; -+ fi->Attributes = cpu_to_le32(attrs); -+ return ret; -+} -+ -+bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, -+ struct cifs_fattr *fattr, -+ struct cifs_open_info_data *data); -+int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, const char *symname); -+int smb2_mknod_reparse(unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, umode_t mode, dev_t dev); -+int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, struct kvec *rsp_iov, -+ struct cifs_open_info_data *data); -+ -+#endif /* _CIFS_REPARSE_H */ -diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c -index e4168cd8b6c28..3216f786908fb 100644 ---- a/fs/smb/client/sess.c -+++ b/fs/smb/client/sess.c -@@ -108,6 +108,7 @@ cifs_chan_clear_in_reconnect(struct cifs_ses *ses, - struct TCP_Server_Info *server) - { - unsigned int chan_index = cifs_ses_get_chan_index(ses, server); -+ - if (chan_index == CIFS_INVAL_CHAN_INDEX) - return; - -@@ -119,6 +120,7 @@ cifs_chan_in_reconnect(struct cifs_ses *ses, - struct TCP_Server_Info *server) - { - unsigned int chan_index = cifs_ses_get_chan_index(ses, server); -+ - if (chan_index == CIFS_INVAL_CHAN_INDEX) - return true; /* err on the safer side */ - -@@ -130,6 +132,7 @@ cifs_chan_set_need_reconnect(struct cifs_ses *ses, - struct TCP_Server_Info *server) - { - unsigned int chan_index = cifs_ses_get_chan_index(ses, server); -+ - if (chan_index == CIFS_INVAL_CHAN_INDEX) - return; - -@@ -143,6 +146,7 @@ cifs_chan_clear_need_reconnect(struct cifs_ses *ses, - struct TCP_Server_Info *server) - { - unsigned int chan_index = cifs_ses_get_chan_index(ses, server); -+ - if (chan_index == CIFS_INVAL_CHAN_INDEX) - return; - -@@ -156,6 +160,7 @@ cifs_chan_needs_reconnect(struct cifs_ses *ses, - struct TCP_Server_Info *server) - { - unsigned int chan_index = cifs_ses_get_chan_index(ses, server); -+ - if (chan_index == CIFS_INVAL_CHAN_INDEX) - return true; /* err on the safer side */ - -@@ -167,6 +172,7 @@ cifs_chan_is_iface_active(struct cifs_ses *ses, - struct TCP_Server_Info *server) - { - unsigned int chan_index = cifs_ses_get_chan_index(ses, server); -+ - if (chan_index == CIFS_INVAL_CHAN_INDEX) - return true; /* err on the safer side */ - -@@ -331,10 +337,10 @@ cifs_disable_secondary_channels(struct cifs_ses *ses) - - if (iface) { - spin_lock(&ses->iface_lock); -- kref_put(&iface->refcount, release_iface); - iface->num_channels--; - if (iface->weight_fulfilled) - iface->weight_fulfilled--; -+ kref_put(&iface->refcount, release_iface); - spin_unlock(&ses->iface_lock); - } - -@@ -436,8 +442,14 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server) - } - - if (!iface) { -- cifs_dbg(FYI, "unable to get the interface matching: %pIS\n", -- &ss); -+ if (!chan_index) -+ cifs_dbg(FYI, "unable to get the interface matching: %pIS\n", -+ &ss); -+ else { -+ cifs_dbg(FYI, "unable to find another interface to replace: %pIS\n", -+ &old_iface->sockaddr); -+ } -+ - spin_unlock(&ses->iface_lock); - return; - } -@@ -455,10 +467,6 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server) - iface->weight_fulfilled++; - - kref_put(&old_iface->refcount, release_iface); -- } else if (old_iface) { -- /* if a new candidate is not found, keep things as is */ -- cifs_dbg(FYI, "could not replace iface: %pIS\n", -- &old_iface->sockaddr); - } else if (!chan_index) { - /* special case: update interface for primary channel */ - cifs_dbg(FYI, "referencing primary channel iface: %pIS\n", -@@ -477,8 +485,6 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server) - - ses->chans[chan_index].iface = iface; - spin_unlock(&ses->chan_lock); -- -- return; - } - - /* -@@ -677,8 +683,7 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, - - /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ - -- /* BB verify whether signing required on neg or just on auth frame -- (and NTLM case) */ -+ /* BB verify whether signing required on neg or just auth frame (and NTLM case) */ - - capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | - CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; -@@ -735,8 +740,10 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses, - - /* copy domain */ - if (ses->domainName == NULL) { -- /* Sending null domain better than using a bogus domain name (as -- we did briefly in 2.6.18) since server will use its default */ -+ /* -+ * Sending null domain better than using a bogus domain name (as -+ * we did briefly in 2.6.18) since server will use its default -+ */ - *bcc_ptr = 0; - *(bcc_ptr+1) = 0; - bytes_ret = 0; -@@ -755,8 +762,7 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, - char *bcc_ptr = *pbcc_area; - int bytes_ret = 0; - -- /* BB FIXME add check that strings total less -- than 335 or will need to send them as arrays */ -+ /* BB FIXME add check that strings less than 335 or will need to send as arrays */ - - /* copy user */ - if (ses->user_name == NULL) { -@@ -801,8 +807,7 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, - if (WARN_ON_ONCE(len < 0)) - len = CIFS_MAX_DOMAINNAME_LEN - 1; - bcc_ptr += len; -- } /* else we will send a null domain name -- so the server will default to its own domain */ -+ } /* else we send a null domain name so server will default to its own domain */ - *bcc_ptr = 0; - bcc_ptr++; - -@@ -898,11 +903,14 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft, - if (len > bleft) - return; - -- /* No domain field in LANMAN case. Domain is -- returned by old servers in the SMB negprot response */ -- /* BB For newer servers which do not support Unicode, -- but thus do return domain here we could add parsing -- for it later, but it is not very important */ -+ /* -+ * No domain field in LANMAN case. Domain is -+ * returned by old servers in the SMB negprot response -+ * -+ * BB For newer servers which do not support Unicode, -+ * but thus do return domain here, we could add parsing -+ * for it later, but it is not very important -+ */ - cifs_dbg(FYI, "ascii: bytes left %d\n", bleft); - } - #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ -@@ -958,9 +966,12 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, - ses->ntlmssp->server_flags = server_flags; - - memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE); -- /* In particular we can examine sign flags */ -- /* BB spec says that if AvId field of MsvAvTimestamp is populated then -- we must set the MIC field of the AUTHENTICATE_MESSAGE */ -+ /* -+ * In particular we can examine sign flags -+ * -+ * BB spec says that if AvId field of MsvAvTimestamp is populated then -+ * we must set the MIC field of the AUTHENTICATE_MESSAGE -+ */ - - tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset); - tilen = le16_to_cpu(pblob->TargetInfoArray.Length); -@@ -1201,10 +1212,16 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer, - memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); - sec_blob->MessageType = NtLmAuthenticate; - -+ /* send version information in ntlmssp authenticate also */ - flags = ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET | -- NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED; -- /* we only send version information in ntlmssp negotiate, so do not set this flag */ -- flags = flags & ~NTLMSSP_NEGOTIATE_VERSION; -+ NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_VERSION | -+ NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED; -+ -+ sec_blob->Version.ProductMajorVersion = LINUX_VERSION_MAJOR; -+ sec_blob->Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL; -+ sec_blob->Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD); -+ sec_blob->Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3; -+ - tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE); - sec_blob->NegotiateFlags = cpu_to_le32(flags); - -diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c -index 1aebcf95c1951..212ec6f66ec65 100644 ---- a/fs/smb/client/smb1ops.c -+++ b/fs/smb/client/smb1ops.c -@@ -1041,15 +1041,7 @@ cifs_make_node(unsigned int xid, struct inode *inode, - { - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct inode *newinode = NULL; -- int rc = -EPERM; -- struct cifs_open_info_data buf = {}; -- struct cifs_io_parms io_parms; -- __u32 oplock = 0; -- struct cifs_fid fid; -- struct cifs_open_parms oparms; -- unsigned int bytes_written; -- struct win_dev *pdev; -- struct kvec iov[2]; -+ int rc; - - if (tcon->unix_ext) { - /* -@@ -1083,74 +1075,18 @@ cifs_make_node(unsigned int xid, struct inode *inode, - d_instantiate(dentry, newinode); - return rc; - } -- - /* -- * SMB1 SFU emulation: should work with all servers, but only -- * support block and char device (no socket & fifo) -+ * Check if mounted with mount parm 'sfu' mount parm. -+ * SFU emulation should work with all servers, but only -+ * supports block and char device (no socket & fifo), -+ * and was used by default in earlier versions of Windows - */ - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) -- return rc; -- -- if (!S_ISCHR(mode) && !S_ISBLK(mode)) -- return rc; -- -- cifs_dbg(FYI, "sfu compat create special file\n"); -- -- oparms = (struct cifs_open_parms) { -- .tcon = tcon, -- .cifs_sb = cifs_sb, -- .desired_access = GENERIC_WRITE, -- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | -- CREATE_OPTION_SPECIAL), -- .disposition = FILE_CREATE, -- .path = full_path, -- .fid = &fid, -- }; -- -- if (tcon->ses->server->oplocks) -- oplock = REQ_OPLOCK; -- else -- oplock = 0; -- rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf); -- if (rc) -- return rc; -- -- /* -- * BB Do not bother to decode buf since no local inode yet to put -- * timestamps in, but we can reuse it safely. -- */ -- -- pdev = (struct win_dev *)&buf.fi; -- io_parms.pid = current->tgid; -- io_parms.tcon = tcon; -- io_parms.offset = 0; -- io_parms.length = sizeof(struct win_dev); -- iov[1].iov_base = &buf.fi; -- iov[1].iov_len = sizeof(struct win_dev); -- if (S_ISCHR(mode)) { -- memcpy(pdev->type, "IntxCHR", 8); -- pdev->major = cpu_to_le64(MAJOR(dev)); -- pdev->minor = cpu_to_le64(MINOR(dev)); -- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, -- &bytes_written, iov, 1); -- } else if (S_ISBLK(mode)) { -- memcpy(pdev->type, "IntxBLK", 8); -- pdev->major = cpu_to_le64(MAJOR(dev)); -- pdev->minor = cpu_to_le64(MINOR(dev)); -- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, -- &bytes_written, iov, 1); -- } -- tcon->ses->server->ops->close(xid, tcon, &fid); -- d_drop(dentry); -- -- /* FIXME: add code here to set EAs */ -- -- cifs_free_open_info(&buf); -- return rc; -+ return -EPERM; -+ return cifs_sfu_make_node(xid, inode, dentry, tcon, -+ full_path, mode, dev); - } - -- -- - struct smb_version_operations smb1_operations = { - .send_cancel = send_nt_cancel, - .compare_fids = cifs_compare_fids, -diff --git a/fs/smb/client/smb2glob.h b/fs/smb/client/smb2glob.h -index 82e916ad167c0..2466e61551369 100644 ---- a/fs/smb/client/smb2glob.h -+++ b/fs/smb/client/smb2glob.h -@@ -23,17 +23,22 @@ - * Identifiers for functions that use the open, operation, close pattern - * in smb2inode.c:smb2_compound_op() - */ --#define SMB2_OP_SET_DELETE 1 --#define SMB2_OP_SET_INFO 2 --#define SMB2_OP_QUERY_INFO 3 --#define SMB2_OP_QUERY_DIR 4 --#define SMB2_OP_MKDIR 5 --#define SMB2_OP_RENAME 6 --#define SMB2_OP_DELETE 7 --#define SMB2_OP_HARDLINK 8 --#define SMB2_OP_SET_EOF 9 --#define SMB2_OP_RMDIR 10 --#define SMB2_OP_POSIX_QUERY_INFO 11 -+enum smb2_compound_ops { -+ SMB2_OP_SET_DELETE = 1, -+ SMB2_OP_SET_INFO, -+ SMB2_OP_QUERY_INFO, -+ SMB2_OP_QUERY_DIR, -+ SMB2_OP_MKDIR, -+ SMB2_OP_RENAME, -+ SMB2_OP_DELETE, -+ SMB2_OP_HARDLINK, -+ SMB2_OP_SET_EOF, -+ SMB2_OP_RMDIR, -+ SMB2_OP_POSIX_QUERY_INFO, -+ SMB2_OP_SET_REPARSE, -+ SMB2_OP_GET_REPARSE, -+ SMB2_OP_QUERY_WSL_EA, -+}; - - /* Used when constructing chained read requests. */ - #define CHAINED_REQUEST 1 -diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c -index 6cac0b107a2d0..86f8c81791374 100644 ---- a/fs/smb/client/smb2inode.c -+++ b/fs/smb/client/smb2inode.c -@@ -26,15 +26,6 @@ - #include "cached_dir.h" - #include "smb2status.h" - --static void --free_set_inf_compound(struct smb_rqst *rqst) --{ -- if (rqst[1].rq_iov) -- SMB2_set_info_free(&rqst[1]); -- if (rqst[2].rq_iov) -- SMB2_close_free(&rqst[2]); --} -- - static inline __u32 file_create_options(struct dentry *dentry) - { - struct cifsInodeInfo *ci; -@@ -47,6 +38,129 @@ static inline __u32 file_create_options(struct dentry *dentry) - return 0; - } - -+static struct reparse_data_buffer *reparse_buf_ptr(struct kvec *iov) -+{ -+ struct reparse_data_buffer *buf; -+ struct smb2_ioctl_rsp *io = iov->iov_base; -+ u32 off, count, len; -+ -+ count = le32_to_cpu(io->OutputCount); -+ off = le32_to_cpu(io->OutputOffset); -+ if (check_add_overflow(off, count, &len) || len > iov->iov_len) -+ return ERR_PTR(-EIO); -+ -+ buf = (struct reparse_data_buffer *)((u8 *)io + off); -+ len = sizeof(*buf); -+ if (count < len || count < le16_to_cpu(buf->ReparseDataLength) + len) -+ return ERR_PTR(-EIO); -+ return buf; -+} -+ -+/* Parse owner and group from SMB3.1.1 POSIX query info */ -+static int parse_posix_sids(struct cifs_open_info_data *data, -+ struct kvec *rsp_iov) -+{ -+ struct smb2_query_info_rsp *qi = rsp_iov->iov_base; -+ unsigned int out_len = le32_to_cpu(qi->OutputBufferLength); -+ unsigned int qi_len = sizeof(data->posix_fi); -+ int owner_len, group_len; -+ u8 *sidsbuf, *sidsbuf_end; -+ -+ if (out_len <= qi_len) -+ return -EINVAL; -+ -+ sidsbuf = (u8 *)qi + le16_to_cpu(qi->OutputBufferOffset) + qi_len; -+ sidsbuf_end = sidsbuf + out_len - qi_len; -+ -+ owner_len = posix_info_sid_size(sidsbuf, sidsbuf_end); -+ if (owner_len == -1) -+ return -EINVAL; -+ -+ memcpy(&data->posix_owner, sidsbuf, owner_len); -+ group_len = posix_info_sid_size(sidsbuf + owner_len, sidsbuf_end); -+ if (group_len == -1) -+ return -EINVAL; -+ -+ memcpy(&data->posix_group, sidsbuf + owner_len, group_len); -+ return 0; -+} -+ -+struct wsl_query_ea { -+ __le32 next; -+ __u8 name_len; -+ __u8 name[SMB2_WSL_XATTR_NAME_LEN + 1]; -+} __packed; -+ -+#define NEXT_OFF cpu_to_le32(sizeof(struct wsl_query_ea)) -+ -+static const struct wsl_query_ea wsl_query_eas[] = { -+ { .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_UID, }, -+ { .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_GID, }, -+ { .next = NEXT_OFF, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_MODE, }, -+ { .next = 0, .name_len = SMB2_WSL_XATTR_NAME_LEN, .name = SMB2_WSL_XATTR_DEV, }, -+}; -+ -+static int check_wsl_eas(struct kvec *rsp_iov) -+{ -+ struct smb2_file_full_ea_info *ea; -+ struct smb2_query_info_rsp *rsp = rsp_iov->iov_base; -+ unsigned long addr; -+ u32 outlen, next; -+ u16 vlen; -+ u8 nlen; -+ u8 *end; -+ -+ outlen = le32_to_cpu(rsp->OutputBufferLength); -+ if (outlen < SMB2_WSL_MIN_QUERY_EA_RESP_SIZE || -+ outlen > SMB2_WSL_MAX_QUERY_EA_RESP_SIZE) -+ return -EINVAL; -+ -+ ea = (void *)((u8 *)rsp_iov->iov_base + -+ le16_to_cpu(rsp->OutputBufferOffset)); -+ end = (u8 *)rsp_iov->iov_base + rsp_iov->iov_len; -+ for (;;) { -+ if ((u8 *)ea > end - sizeof(*ea)) -+ return -EINVAL; -+ -+ nlen = ea->ea_name_length; -+ vlen = le16_to_cpu(ea->ea_value_length); -+ if (nlen != SMB2_WSL_XATTR_NAME_LEN || -+ (u8 *)ea + nlen + 1 + vlen > end) -+ return -EINVAL; -+ -+ switch (vlen) { -+ case 4: -+ if (strncmp(ea->ea_data, SMB2_WSL_XATTR_UID, nlen) && -+ strncmp(ea->ea_data, SMB2_WSL_XATTR_GID, nlen) && -+ strncmp(ea->ea_data, SMB2_WSL_XATTR_MODE, nlen)) -+ return -EINVAL; -+ break; -+ case 8: -+ if (strncmp(ea->ea_data, SMB2_WSL_XATTR_DEV, nlen)) -+ return -EINVAL; -+ break; -+ case 0: -+ if (!strncmp(ea->ea_data, SMB2_WSL_XATTR_UID, nlen) || -+ !strncmp(ea->ea_data, SMB2_WSL_XATTR_GID, nlen) || -+ !strncmp(ea->ea_data, SMB2_WSL_XATTR_MODE, nlen) || -+ !strncmp(ea->ea_data, SMB2_WSL_XATTR_DEV, nlen)) -+ break; -+ fallthrough; -+ default: -+ return -EINVAL; -+ } -+ -+ next = le32_to_cpu(ea->next_entry_offset); -+ if (!next) -+ break; -+ if (!IS_ALIGNED(next, 4) || -+ check_add_overflow((unsigned long)ea, next, &addr)) -+ return -EINVAL; -+ ea = (void *)addr; -+ } -+ return 0; -+} -+ - /* - * note: If cfile is passed, the reference to it is dropped here. - * So make sure that you do not reuse cfile after return from this func. -@@ -57,13 +171,14 @@ static inline __u32 file_create_options(struct dentry *dentry) - */ - static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, const char *full_path, -- __u32 desired_access, __u32 create_disposition, __u32 create_options, -- umode_t mode, void *ptr, int command, struct cifsFileInfo *cfile, -- __u8 **extbuf, size_t *extbuflen, -- struct kvec *out_iov, int *out_buftype) -+ struct cifs_open_parms *oparms, struct kvec *in_iov, -+ int *cmds, int num_cmds, struct cifsFileInfo *cfile, -+ struct kvec *out_iov, int *out_buftype, struct dentry *dentry) - { -+ -+ struct reparse_data_buffer *rbuf; - struct smb2_compound_vars *vars = NULL; -- struct kvec *rsp_iov; -+ struct kvec *rsp_iov, *iov; - struct smb_rqst *rqst; - int rc; - __le16 *utf16_path = NULL; -@@ -71,15 +186,24 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, - struct cifs_fid fid; - struct cifs_ses *ses = tcon->ses; - struct TCP_Server_Info *server; -- int num_rqst = 0; -- int resp_buftype[3]; -+ int num_rqst = 0, i; -+ int resp_buftype[MAX_COMPOUND]; - struct smb2_query_info_rsp *qi_rsp = NULL; - struct cifs_open_info_data *idata; -+ struct inode *inode = NULL; - int flags = 0; - __u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0}; - unsigned int size[2]; - void *data[2]; -- int len; -+ unsigned int len; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ oplock = SMB2_OPLOCK_LEVEL_NONE; -+ num_rqst = 0; -+ server = cifs_pick_channel(ses); - - vars = kzalloc(sizeof(*vars), GFP_ATOMIC); - if (vars == NULL) -@@ -87,12 +211,11 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, - rqst = &vars->rqst[0]; - rsp_iov = &vars->rsp_iov[0]; - -- server = cifs_pick_channel(ses); -- - if (smb3_encryption_required(tcon)) - flags |= CIFS_TRANSFORM_REQ; - -- resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; -+ for (i = 0; i < ARRAY_SIZE(resp_buftype); i++) -+ resp_buftype[i] = CIFS_NO_BUFFER; - - /* We already have a handle so we can skip the open */ - if (cfile) -@@ -105,16 +228,28 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, - goto finished; - } - -- vars->oparms = (struct cifs_open_parms) { -- .tcon = tcon, -- .path = full_path, -- .desired_access = desired_access, -- .disposition = create_disposition, -- .create_options = cifs_create_options(cifs_sb, create_options), -- .fid = &fid, -- .mode = mode, -- .cifs_sb = cifs_sb, -- }; -+ /* if there is an existing lease, reuse it */ -+ -+ /* -+ * note: files with hardlinks cause unexpected behaviour. As per MS-SMB2, -+ * lease keys are associated with the filepath. We are maintaining lease keys -+ * with the inode on the client. If the file has hardlinks, it is possible -+ * that the lease for a file be reused for an operation on its hardlink or -+ * vice versa. -+ * As a workaround, send request using an existing lease key and if the server -+ * returns STATUS_INVALID_PARAMETER, which maps to EINVAL, send the request -+ * again without the lease. -+ */ -+ if (dentry) { -+ inode = d_inode(dentry); -+ if (CIFS_I(inode)->lease_granted && server->ops->get_lease_key) { -+ oplock = SMB2_OPLOCK_LEVEL_LEASE; -+ server->ops->get_lease_key(inode, &fid); -+ } -+ } -+ -+ vars->oparms = *oparms; -+ vars->oparms.fid = &fid; - - rqst[num_rqst].rq_iov = &vars->open_iov[0]; - rqst[num_rqst].rq_nvec = SMB2_CREATE_IOV_SIZE; -@@ -130,242 +265,330 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, - num_rqst++; - rc = 0; - -- /* Operation */ -- switch (command) { -- case SMB2_OP_QUERY_INFO: -- rqst[num_rqst].rq_iov = &vars->qi_iov; -- rqst[num_rqst].rq_nvec = 1; -- -- if (cfile) -- rc = SMB2_query_info_init(tcon, server, -- &rqst[num_rqst], -- cfile->fid.persistent_fid, -- cfile->fid.volatile_fid, -- FILE_ALL_INFORMATION, -- SMB2_O_INFO_FILE, 0, -- sizeof(struct smb2_file_all_info) + -- PATH_MAX * 2, 0, NULL); -- else { -- rc = SMB2_query_info_init(tcon, server, -- &rqst[num_rqst], -- COMPOUND_FID, -- COMPOUND_FID, -- FILE_ALL_INFORMATION, -- SMB2_O_INFO_FILE, 0, -- sizeof(struct smb2_file_all_info) + -- PATH_MAX * 2, 0, NULL); -- if (!rc) { -+ for (i = 0; i < num_cmds; i++) { -+ /* Operation */ -+ switch (cmds[i]) { -+ case SMB2_OP_QUERY_INFO: -+ rqst[num_rqst].rq_iov = &vars->qi_iov; -+ rqst[num_rqst].rq_nvec = 1; -+ -+ if (cfile) { -+ rc = SMB2_query_info_init(tcon, server, -+ &rqst[num_rqst], -+ cfile->fid.persistent_fid, -+ cfile->fid.volatile_fid, -+ FILE_ALL_INFORMATION, -+ SMB2_O_INFO_FILE, 0, -+ sizeof(struct smb2_file_all_info) + -+ PATH_MAX * 2, 0, NULL); -+ } else { -+ rc = SMB2_query_info_init(tcon, server, -+ &rqst[num_rqst], -+ COMPOUND_FID, -+ COMPOUND_FID, -+ FILE_ALL_INFORMATION, -+ SMB2_O_INFO_FILE, 0, -+ sizeof(struct smb2_file_all_info) + -+ PATH_MAX * 2, 0, NULL); -+ } -+ if (!rc && (!cfile || num_rqst > 1)) { - smb2_set_next_command(tcon, &rqst[num_rqst]); - smb2_set_related(&rqst[num_rqst]); -+ } else if (rc) { -+ goto finished; - } -- } -+ num_rqst++; -+ trace_smb3_query_info_compound_enter(xid, ses->Suid, -+ tcon->tid, full_path); -+ break; -+ case SMB2_OP_POSIX_QUERY_INFO: -+ rqst[num_rqst].rq_iov = &vars->qi_iov; -+ rqst[num_rqst].rq_nvec = 1; - -- if (rc) -- goto finished; -- num_rqst++; -- trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid, -- full_path); -- break; -- case SMB2_OP_POSIX_QUERY_INFO: -- rqst[num_rqst].rq_iov = &vars->qi_iov; -- rqst[num_rqst].rq_nvec = 1; -- -- if (cfile) -- rc = SMB2_query_info_init(tcon, server, -- &rqst[num_rqst], -- cfile->fid.persistent_fid, -- cfile->fid.volatile_fid, -- SMB_FIND_FILE_POSIX_INFO, -- SMB2_O_INFO_FILE, 0, -+ if (cfile) { - /* TBD: fix following to allow for longer SIDs */ -- sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) + -- (sizeof(struct cifs_sid) * 2), 0, NULL); -- else { -- rc = SMB2_query_info_init(tcon, server, -- &rqst[num_rqst], -- COMPOUND_FID, -- COMPOUND_FID, -- SMB_FIND_FILE_POSIX_INFO, -- SMB2_O_INFO_FILE, 0, -- sizeof(struct smb311_posix_qinfo *) + (PATH_MAX * 2) + -- (sizeof(struct cifs_sid) * 2), 0, NULL); -- if (!rc) { -+ rc = SMB2_query_info_init(tcon, server, -+ &rqst[num_rqst], -+ cfile->fid.persistent_fid, -+ cfile->fid.volatile_fid, -+ SMB_FIND_FILE_POSIX_INFO, -+ SMB2_O_INFO_FILE, 0, -+ sizeof(struct smb311_posix_qinfo *) + -+ (PATH_MAX * 2) + -+ (sizeof(struct cifs_sid) * 2), 0, NULL); -+ } else { -+ rc = SMB2_query_info_init(tcon, server, -+ &rqst[num_rqst], -+ COMPOUND_FID, -+ COMPOUND_FID, -+ SMB_FIND_FILE_POSIX_INFO, -+ SMB2_O_INFO_FILE, 0, -+ sizeof(struct smb311_posix_qinfo *) + -+ (PATH_MAX * 2) + -+ (sizeof(struct cifs_sid) * 2), 0, NULL); -+ } -+ if (!rc && (!cfile || num_rqst > 1)) { - smb2_set_next_command(tcon, &rqst[num_rqst]); - smb2_set_related(&rqst[num_rqst]); -+ } else if (rc) { -+ goto finished; - } -- } -- -- if (rc) -- goto finished; -- num_rqst++; -- trace_smb3_posix_query_info_compound_enter(xid, ses->Suid, tcon->tid, full_path); -- break; -- case SMB2_OP_DELETE: -- trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path); -- break; -- case SMB2_OP_MKDIR: -- /* -- * Directories are created through parameters in the -- * SMB2_open() call. -- */ -- trace_smb3_mkdir_enter(xid, ses->Suid, tcon->tid, full_path); -- break; -- case SMB2_OP_RMDIR: -- rqst[num_rqst].rq_iov = &vars->si_iov[0]; -- rqst[num_rqst].rq_nvec = 1; -- -- size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */ -- data[0] = &delete_pending[0]; -- -- rc = SMB2_set_info_init(tcon, server, -- &rqst[num_rqst], COMPOUND_FID, -- COMPOUND_FID, current->tgid, -- FILE_DISPOSITION_INFORMATION, -- SMB2_O_INFO_FILE, 0, data, size); -- if (rc) -- goto finished; -- smb2_set_next_command(tcon, &rqst[num_rqst]); -- smb2_set_related(&rqst[num_rqst++]); -- trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path); -- break; -- case SMB2_OP_SET_EOF: -- rqst[num_rqst].rq_iov = &vars->si_iov[0]; -- rqst[num_rqst].rq_nvec = 1; -+ num_rqst++; -+ trace_smb3_posix_query_info_compound_enter(xid, ses->Suid, -+ tcon->tid, full_path); -+ break; -+ case SMB2_OP_DELETE: -+ trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path); -+ break; -+ case SMB2_OP_MKDIR: -+ /* -+ * Directories are created through parameters in the -+ * SMB2_open() call. -+ */ -+ trace_smb3_mkdir_enter(xid, ses->Suid, tcon->tid, full_path); -+ break; -+ case SMB2_OP_RMDIR: -+ rqst[num_rqst].rq_iov = &vars->si_iov[0]; -+ rqst[num_rqst].rq_nvec = 1; - -- size[0] = 8; /* sizeof __le64 */ -- data[0] = ptr; -+ size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */ -+ data[0] = &delete_pending[0]; - -- if (cfile) { -- rc = SMB2_set_info_init(tcon, server, -- &rqst[num_rqst], -- cfile->fid.persistent_fid, -- cfile->fid.volatile_fid, -- current->tgid, -- FILE_END_OF_FILE_INFORMATION, -- SMB2_O_INFO_FILE, 0, -- data, size); -- } else { - rc = SMB2_set_info_init(tcon, server, -- &rqst[num_rqst], -- COMPOUND_FID, -- COMPOUND_FID, -- current->tgid, -- FILE_END_OF_FILE_INFORMATION, -- SMB2_O_INFO_FILE, 0, -- data, size); -- if (!rc) { -+ &rqst[num_rqst], COMPOUND_FID, -+ COMPOUND_FID, current->tgid, -+ FILE_DISPOSITION_INFORMATION, -+ SMB2_O_INFO_FILE, 0, data, size); -+ if (rc) -+ goto finished; -+ smb2_set_next_command(tcon, &rqst[num_rqst]); -+ smb2_set_related(&rqst[num_rqst++]); -+ trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path); -+ break; -+ case SMB2_OP_SET_EOF: -+ rqst[num_rqst].rq_iov = &vars->si_iov[0]; -+ rqst[num_rqst].rq_nvec = 1; -+ -+ size[0] = in_iov[i].iov_len; -+ data[0] = in_iov[i].iov_base; -+ -+ if (cfile) { -+ rc = SMB2_set_info_init(tcon, server, -+ &rqst[num_rqst], -+ cfile->fid.persistent_fid, -+ cfile->fid.volatile_fid, -+ current->tgid, -+ FILE_END_OF_FILE_INFORMATION, -+ SMB2_O_INFO_FILE, 0, -+ data, size); -+ } else { -+ rc = SMB2_set_info_init(tcon, server, -+ &rqst[num_rqst], -+ COMPOUND_FID, -+ COMPOUND_FID, -+ current->tgid, -+ FILE_END_OF_FILE_INFORMATION, -+ SMB2_O_INFO_FILE, 0, -+ data, size); -+ } -+ if (!rc && (!cfile || num_rqst > 1)) { - smb2_set_next_command(tcon, &rqst[num_rqst]); - smb2_set_related(&rqst[num_rqst]); -+ } else if (rc) { -+ goto finished; - } -- } -- if (rc) -- goto finished; -- num_rqst++; -- trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path); -- break; -- case SMB2_OP_SET_INFO: -- rqst[num_rqst].rq_iov = &vars->si_iov[0]; -- rqst[num_rqst].rq_nvec = 1; -- -- -- size[0] = sizeof(FILE_BASIC_INFO); -- data[0] = ptr; -- -- if (cfile) -- rc = SMB2_set_info_init(tcon, server, -- &rqst[num_rqst], -- cfile->fid.persistent_fid, -- cfile->fid.volatile_fid, current->tgid, -- FILE_BASIC_INFORMATION, -- SMB2_O_INFO_FILE, 0, data, size); -- else { -- rc = SMB2_set_info_init(tcon, server, -- &rqst[num_rqst], -- COMPOUND_FID, -- COMPOUND_FID, current->tgid, -- FILE_BASIC_INFORMATION, -- SMB2_O_INFO_FILE, 0, data, size); -- if (!rc) { -+ num_rqst++; -+ trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path); -+ break; -+ case SMB2_OP_SET_INFO: -+ rqst[num_rqst].rq_iov = &vars->si_iov[0]; -+ rqst[num_rqst].rq_nvec = 1; -+ -+ size[0] = in_iov[i].iov_len; -+ data[0] = in_iov[i].iov_base; -+ -+ if (cfile) { -+ rc = SMB2_set_info_init(tcon, server, -+ &rqst[num_rqst], -+ cfile->fid.persistent_fid, -+ cfile->fid.volatile_fid, current->tgid, -+ FILE_BASIC_INFORMATION, -+ SMB2_O_INFO_FILE, 0, data, size); -+ } else { -+ rc = SMB2_set_info_init(tcon, server, -+ &rqst[num_rqst], -+ COMPOUND_FID, -+ COMPOUND_FID, current->tgid, -+ FILE_BASIC_INFORMATION, -+ SMB2_O_INFO_FILE, 0, data, size); -+ } -+ if (!rc && (!cfile || num_rqst > 1)) { - smb2_set_next_command(tcon, &rqst[num_rqst]); - smb2_set_related(&rqst[num_rqst]); -+ } else if (rc) { -+ goto finished; - } -- } -- -- if (rc) -- goto finished; -- num_rqst++; -- trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid, -- full_path); -- break; -- case SMB2_OP_RENAME: -- rqst[num_rqst].rq_iov = &vars->si_iov[0]; -- rqst[num_rqst].rq_nvec = 2; -+ num_rqst++; -+ trace_smb3_set_info_compound_enter(xid, ses->Suid, -+ tcon->tid, full_path); -+ break; -+ case SMB2_OP_RENAME: -+ rqst[num_rqst].rq_iov = &vars->si_iov[0]; -+ rqst[num_rqst].rq_nvec = 2; - -- len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX)); -+ len = in_iov[i].iov_len; - -- vars->rename_info.ReplaceIfExists = 1; -- vars->rename_info.RootDirectory = 0; -- vars->rename_info.FileNameLength = cpu_to_le32(len); -+ vars->rename_info.ReplaceIfExists = 1; -+ vars->rename_info.RootDirectory = 0; -+ vars->rename_info.FileNameLength = cpu_to_le32(len); - -- size[0] = sizeof(struct smb2_file_rename_info); -- data[0] = &vars->rename_info; -+ size[0] = sizeof(struct smb2_file_rename_info); -+ data[0] = &vars->rename_info; - -- size[1] = len + 2 /* null */; -- data[1] = (__le16 *)ptr; -+ size[1] = len + 2 /* null */; -+ data[1] = in_iov[i].iov_base; - -- if (cfile) -- rc = SMB2_set_info_init(tcon, server, -- &rqst[num_rqst], -- cfile->fid.persistent_fid, -- cfile->fid.volatile_fid, -- current->tgid, FILE_RENAME_INFORMATION, -- SMB2_O_INFO_FILE, 0, data, size); -- else { -- rc = SMB2_set_info_init(tcon, server, -- &rqst[num_rqst], -- COMPOUND_FID, COMPOUND_FID, -- current->tgid, FILE_RENAME_INFORMATION, -- SMB2_O_INFO_FILE, 0, data, size); -- if (!rc) { -+ if (cfile) { -+ rc = SMB2_set_info_init(tcon, server, -+ &rqst[num_rqst], -+ cfile->fid.persistent_fid, -+ cfile->fid.volatile_fid, -+ current->tgid, FILE_RENAME_INFORMATION, -+ SMB2_O_INFO_FILE, 0, data, size); -+ } else { -+ rc = SMB2_set_info_init(tcon, server, -+ &rqst[num_rqst], -+ COMPOUND_FID, COMPOUND_FID, -+ current->tgid, FILE_RENAME_INFORMATION, -+ SMB2_O_INFO_FILE, 0, data, size); -+ } -+ if (!rc && (!cfile || num_rqst > 1)) { - smb2_set_next_command(tcon, &rqst[num_rqst]); - smb2_set_related(&rqst[num_rqst]); -+ } else if (rc) { -+ goto finished; - } -- } -- if (rc) -- goto finished; -- num_rqst++; -- trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path); -- break; -- case SMB2_OP_HARDLINK: -- rqst[num_rqst].rq_iov = &vars->si_iov[0]; -- rqst[num_rqst].rq_nvec = 2; -+ num_rqst++; -+ trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path); -+ break; -+ case SMB2_OP_HARDLINK: -+ rqst[num_rqst].rq_iov = &vars->si_iov[0]; -+ rqst[num_rqst].rq_nvec = 2; - -- len = (2 * UniStrnlen((wchar_t *)ptr, PATH_MAX)); -+ len = in_iov[i].iov_len; - -- vars->link_info.ReplaceIfExists = 0; -- vars->link_info.RootDirectory = 0; -- vars->link_info.FileNameLength = cpu_to_le32(len); -+ vars->link_info.ReplaceIfExists = 0; -+ vars->link_info.RootDirectory = 0; -+ vars->link_info.FileNameLength = cpu_to_le32(len); - -- size[0] = sizeof(struct smb2_file_link_info); -- data[0] = &vars->link_info; -+ size[0] = sizeof(struct smb2_file_link_info); -+ data[0] = &vars->link_info; - -- size[1] = len + 2 /* null */; -- data[1] = (__le16 *)ptr; -+ size[1] = len + 2 /* null */; -+ data[1] = in_iov[i].iov_base; - -- rc = SMB2_set_info_init(tcon, server, -- &rqst[num_rqst], COMPOUND_FID, -- COMPOUND_FID, current->tgid, -- FILE_LINK_INFORMATION, -- SMB2_O_INFO_FILE, 0, data, size); -- if (rc) -- goto finished; -- smb2_set_next_command(tcon, &rqst[num_rqst]); -- smb2_set_related(&rqst[num_rqst++]); -- trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path); -- break; -- default: -- cifs_dbg(VFS, "Invalid command\n"); -- rc = -EINVAL; -+ rc = SMB2_set_info_init(tcon, server, -+ &rqst[num_rqst], COMPOUND_FID, -+ COMPOUND_FID, current->tgid, -+ FILE_LINK_INFORMATION, -+ SMB2_O_INFO_FILE, 0, data, size); -+ if (rc) -+ goto finished; -+ smb2_set_next_command(tcon, &rqst[num_rqst]); -+ smb2_set_related(&rqst[num_rqst++]); -+ trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path); -+ break; -+ case SMB2_OP_SET_REPARSE: -+ rqst[num_rqst].rq_iov = vars->io_iov; -+ rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov); -+ -+ if (cfile) { -+ rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst], -+ cfile->fid.persistent_fid, -+ cfile->fid.volatile_fid, -+ FSCTL_SET_REPARSE_POINT, -+ in_iov[i].iov_base, -+ in_iov[i].iov_len, 0); -+ } else { -+ rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst], -+ COMPOUND_FID, COMPOUND_FID, -+ FSCTL_SET_REPARSE_POINT, -+ in_iov[i].iov_base, -+ in_iov[i].iov_len, 0); -+ } -+ if (!rc && (!cfile || num_rqst > 1)) { -+ smb2_set_next_command(tcon, &rqst[num_rqst]); -+ smb2_set_related(&rqst[num_rqst]); -+ } else if (rc) { -+ goto finished; -+ } -+ num_rqst++; -+ trace_smb3_set_reparse_compound_enter(xid, ses->Suid, -+ tcon->tid, full_path); -+ break; -+ case SMB2_OP_GET_REPARSE: -+ rqst[num_rqst].rq_iov = vars->io_iov; -+ rqst[num_rqst].rq_nvec = ARRAY_SIZE(vars->io_iov); -+ -+ if (cfile) { -+ rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst], -+ cfile->fid.persistent_fid, -+ cfile->fid.volatile_fid, -+ FSCTL_GET_REPARSE_POINT, -+ NULL, 0, CIFSMaxBufSize); -+ } else { -+ rc = SMB2_ioctl_init(tcon, server, &rqst[num_rqst], -+ COMPOUND_FID, COMPOUND_FID, -+ FSCTL_GET_REPARSE_POINT, -+ NULL, 0, CIFSMaxBufSize); -+ } -+ if (!rc && (!cfile || num_rqst > 1)) { -+ smb2_set_next_command(tcon, &rqst[num_rqst]); -+ smb2_set_related(&rqst[num_rqst]); -+ } else if (rc) { -+ goto finished; -+ } -+ num_rqst++; -+ trace_smb3_get_reparse_compound_enter(xid, ses->Suid, -+ tcon->tid, full_path); -+ break; -+ case SMB2_OP_QUERY_WSL_EA: -+ rqst[num_rqst].rq_iov = &vars->ea_iov; -+ rqst[num_rqst].rq_nvec = 1; -+ -+ if (cfile) { -+ rc = SMB2_query_info_init(tcon, server, -+ &rqst[num_rqst], -+ cfile->fid.persistent_fid, -+ cfile->fid.volatile_fid, -+ FILE_FULL_EA_INFORMATION, -+ SMB2_O_INFO_FILE, 0, -+ SMB2_WSL_MAX_QUERY_EA_RESP_SIZE, -+ sizeof(wsl_query_eas), -+ (void *)wsl_query_eas); -+ } else { -+ rc = SMB2_query_info_init(tcon, server, -+ &rqst[num_rqst], -+ COMPOUND_FID, -+ COMPOUND_FID, -+ FILE_FULL_EA_INFORMATION, -+ SMB2_O_INFO_FILE, 0, -+ SMB2_WSL_MAX_QUERY_EA_RESP_SIZE, -+ sizeof(wsl_query_eas), -+ (void *)wsl_query_eas); -+ } -+ if (!rc && (!cfile || num_rqst > 1)) { -+ smb2_set_next_command(tcon, &rqst[num_rqst]); -+ smb2_set_related(&rqst[num_rqst]); -+ } else if (rc) { -+ goto finished; -+ } -+ num_rqst++; -+ break; -+ default: -+ cifs_dbg(VFS, "Invalid command\n"); -+ rc = -EINVAL; -+ } - } - if (rc) - goto finished; -@@ -387,157 +610,219 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, - num_rqst++; - - if (cfile) { -+ if (retries) -+ for (i = 1; i < num_rqst - 2; i++) -+ smb2_set_replay(server, &rqst[i]); -+ - rc = compound_send_recv(xid, ses, server, - flags, num_rqst - 2, - &rqst[1], &resp_buftype[1], - &rsp_iov[1]); -- } else -+ } else { -+ if (retries) -+ for (i = 0; i < num_rqst; i++) -+ smb2_set_replay(server, &rqst[i]); -+ - rc = compound_send_recv(xid, ses, server, - flags, num_rqst, - rqst, resp_buftype, - rsp_iov); -+ } - -- finished: -- SMB2_open_free(&rqst[0]); -+finished: -+ num_rqst = 0; -+ SMB2_open_free(&rqst[num_rqst++]); - if (rc == -EREMCHG) { - pr_warn_once("server share %s deleted\n", tcon->tree_name); - tcon->need_reconnect = true; - } - -- switch (command) { -- case SMB2_OP_QUERY_INFO: -- idata = ptr; -- if (rc == 0 && cfile && cfile->symlink_target) { -- idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); -- if (!idata->symlink_target) -- rc = -ENOMEM; -- } -- if (rc == 0) { -- qi_rsp = (struct smb2_query_info_rsp *) -- rsp_iov[1].iov_base; -- rc = smb2_validate_and_copy_iov( -- le16_to_cpu(qi_rsp->OutputBufferOffset), -- le32_to_cpu(qi_rsp->OutputBufferLength), -- &rsp_iov[1], sizeof(idata->fi), (char *)&idata->fi); -- } -- if (rqst[1].rq_iov) -- SMB2_query_info_free(&rqst[1]); -- if (rqst[2].rq_iov) -- SMB2_close_free(&rqst[2]); -- if (rc) -- trace_smb3_query_info_compound_err(xid, ses->Suid, -- tcon->tid, rc); -- else -- trace_smb3_query_info_compound_done(xid, ses->Suid, -- tcon->tid); -- break; -- case SMB2_OP_POSIX_QUERY_INFO: -- idata = ptr; -- if (rc == 0 && cfile && cfile->symlink_target) { -- idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); -- if (!idata->symlink_target) -- rc = -ENOMEM; -- } -- if (rc == 0) { -- qi_rsp = (struct smb2_query_info_rsp *) -- rsp_iov[1].iov_base; -- rc = smb2_validate_and_copy_iov( -- le16_to_cpu(qi_rsp->OutputBufferOffset), -- le32_to_cpu(qi_rsp->OutputBufferLength), -- &rsp_iov[1], sizeof(idata->posix_fi) /* add SIDs */, -- (char *)&idata->posix_fi); -- } -- if (rc == 0) { -- unsigned int length = le32_to_cpu(qi_rsp->OutputBufferLength); -- -- if (length > sizeof(idata->posix_fi)) { -- char *base = (char *)rsp_iov[1].iov_base + -- le16_to_cpu(qi_rsp->OutputBufferOffset) + -- sizeof(idata->posix_fi); -- *extbuflen = length - sizeof(idata->posix_fi); -- *extbuf = kmemdup(base, *extbuflen, GFP_KERNEL); -- if (!*extbuf) -+ for (i = 0; i < num_cmds; i++) { -+ switch (cmds[i]) { -+ case SMB2_OP_QUERY_INFO: -+ idata = in_iov[i].iov_base; -+ if (rc == 0 && cfile && cfile->symlink_target) { -+ idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); -+ if (!idata->symlink_target) - rc = -ENOMEM; -+ } -+ if (rc == 0) { -+ qi_rsp = (struct smb2_query_info_rsp *) -+ rsp_iov[i + 1].iov_base; -+ rc = smb2_validate_and_copy_iov( -+ le16_to_cpu(qi_rsp->OutputBufferOffset), -+ le32_to_cpu(qi_rsp->OutputBufferLength), -+ &rsp_iov[i + 1], sizeof(idata->fi), (char *)&idata->fi); -+ } -+ SMB2_query_info_free(&rqst[num_rqst++]); -+ if (rc) -+ trace_smb3_query_info_compound_err(xid, ses->Suid, -+ tcon->tid, rc); -+ else -+ trace_smb3_query_info_compound_done(xid, ses->Suid, -+ tcon->tid); -+ break; -+ case SMB2_OP_POSIX_QUERY_INFO: -+ idata = in_iov[i].iov_base; -+ if (rc == 0 && cfile && cfile->symlink_target) { -+ idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); -+ if (!idata->symlink_target) -+ rc = -ENOMEM; -+ } -+ if (rc == 0) { -+ qi_rsp = (struct smb2_query_info_rsp *) -+ rsp_iov[i + 1].iov_base; -+ rc = smb2_validate_and_copy_iov( -+ le16_to_cpu(qi_rsp->OutputBufferOffset), -+ le32_to_cpu(qi_rsp->OutputBufferLength), -+ &rsp_iov[i + 1], sizeof(idata->posix_fi) /* add SIDs */, -+ (char *)&idata->posix_fi); -+ } -+ if (rc == 0) -+ rc = parse_posix_sids(idata, &rsp_iov[i + 1]); -+ -+ SMB2_query_info_free(&rqst[num_rqst++]); -+ if (rc) -+ trace_smb3_posix_query_info_compound_err(xid, ses->Suid, -+ tcon->tid, rc); -+ else -+ trace_smb3_posix_query_info_compound_done(xid, ses->Suid, -+ tcon->tid); -+ break; -+ case SMB2_OP_DELETE: -+ if (rc) -+ trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc); -+ else { -+ /* -+ * If dentry (hence, inode) is NULL, lease break is going to -+ * take care of degrading leases on handles for deleted files. -+ */ -+ if (inode) -+ cifs_mark_open_handles_for_deleted_file(inode, full_path); -+ trace_smb3_delete_done(xid, ses->Suid, tcon->tid); -+ } -+ break; -+ case SMB2_OP_MKDIR: -+ if (rc) -+ trace_smb3_mkdir_err(xid, ses->Suid, tcon->tid, rc); -+ else -+ trace_smb3_mkdir_done(xid, ses->Suid, tcon->tid); -+ break; -+ case SMB2_OP_HARDLINK: -+ if (rc) -+ trace_smb3_hardlink_err(xid, ses->Suid, tcon->tid, rc); -+ else -+ trace_smb3_hardlink_done(xid, ses->Suid, tcon->tid); -+ SMB2_set_info_free(&rqst[num_rqst++]); -+ break; -+ case SMB2_OP_RENAME: -+ if (rc) -+ trace_smb3_rename_err(xid, ses->Suid, tcon->tid, rc); -+ else -+ trace_smb3_rename_done(xid, ses->Suid, tcon->tid); -+ SMB2_set_info_free(&rqst[num_rqst++]); -+ break; -+ case SMB2_OP_RMDIR: -+ if (rc) -+ trace_smb3_rmdir_err(xid, ses->Suid, tcon->tid, rc); -+ else -+ trace_smb3_rmdir_done(xid, ses->Suid, tcon->tid); -+ SMB2_set_info_free(&rqst[num_rqst++]); -+ break; -+ case SMB2_OP_SET_EOF: -+ if (rc) -+ trace_smb3_set_eof_err(xid, ses->Suid, tcon->tid, rc); -+ else -+ trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid); -+ SMB2_set_info_free(&rqst[num_rqst++]); -+ break; -+ case SMB2_OP_SET_INFO: -+ if (rc) -+ trace_smb3_set_info_compound_err(xid, ses->Suid, -+ tcon->tid, rc); -+ else -+ trace_smb3_set_info_compound_done(xid, ses->Suid, -+ tcon->tid); -+ SMB2_set_info_free(&rqst[num_rqst++]); -+ break; -+ case SMB2_OP_SET_REPARSE: -+ if (rc) { -+ trace_smb3_set_reparse_compound_err(xid, ses->Suid, -+ tcon->tid, rc); -+ } else { -+ trace_smb3_set_reparse_compound_done(xid, ses->Suid, -+ tcon->tid); -+ } -+ SMB2_ioctl_free(&rqst[num_rqst++]); -+ break; -+ case SMB2_OP_GET_REPARSE: -+ if (!rc) { -+ iov = &rsp_iov[i + 1]; -+ idata = in_iov[i].iov_base; -+ idata->reparse.io.iov = *iov; -+ idata->reparse.io.buftype = resp_buftype[i + 1]; -+ rbuf = reparse_buf_ptr(iov); -+ if (IS_ERR(rbuf)) { -+ rc = PTR_ERR(rbuf); -+ trace_smb3_set_reparse_compound_err(xid, ses->Suid, -+ tcon->tid, rc); -+ } else { -+ idata->reparse.tag = le32_to_cpu(rbuf->ReparseTag); -+ trace_smb3_set_reparse_compound_done(xid, ses->Suid, -+ tcon->tid); -+ } -+ memset(iov, 0, sizeof(*iov)); -+ resp_buftype[i + 1] = CIFS_NO_BUFFER; -+ } else { -+ trace_smb3_set_reparse_compound_err(xid, ses->Suid, -+ tcon->tid, rc); -+ } -+ SMB2_ioctl_free(&rqst[num_rqst++]); -+ break; -+ case SMB2_OP_QUERY_WSL_EA: -+ if (!rc) { -+ idata = in_iov[i].iov_base; -+ qi_rsp = rsp_iov[i + 1].iov_base; -+ data[0] = (u8 *)qi_rsp + le16_to_cpu(qi_rsp->OutputBufferOffset); -+ size[0] = le32_to_cpu(qi_rsp->OutputBufferLength); -+ rc = check_wsl_eas(&rsp_iov[i + 1]); -+ if (!rc) { -+ memcpy(idata->wsl.eas, data[0], size[0]); -+ idata->wsl.eas_len = size[0]; -+ } -+ } -+ if (!rc) { -+ trace_smb3_query_wsl_ea_compound_done(xid, ses->Suid, -+ tcon->tid); - } else { -- rc = -EINVAL; -+ trace_smb3_query_wsl_ea_compound_err(xid, ses->Suid, -+ tcon->tid, rc); - } -+ SMB2_query_info_free(&rqst[num_rqst++]); -+ break; - } -- if (rqst[1].rq_iov) -- SMB2_query_info_free(&rqst[1]); -- if (rqst[2].rq_iov) -- SMB2_close_free(&rqst[2]); -- if (rc) -- trace_smb3_posix_query_info_compound_err(xid, ses->Suid, tcon->tid, rc); -- else -- trace_smb3_posix_query_info_compound_done(xid, ses->Suid, tcon->tid); -- break; -- case SMB2_OP_DELETE: -- if (rc) -- trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc); -- else -- trace_smb3_delete_done(xid, ses->Suid, tcon->tid); -- if (rqst[1].rq_iov) -- SMB2_close_free(&rqst[1]); -- break; -- case SMB2_OP_MKDIR: -- if (rc) -- trace_smb3_mkdir_err(xid, ses->Suid, tcon->tid, rc); -- else -- trace_smb3_mkdir_done(xid, ses->Suid, tcon->tid); -- if (rqst[1].rq_iov) -- SMB2_close_free(&rqst[1]); -- break; -- case SMB2_OP_HARDLINK: -- if (rc) -- trace_smb3_hardlink_err(xid, ses->Suid, tcon->tid, rc); -- else -- trace_smb3_hardlink_done(xid, ses->Suid, tcon->tid); -- free_set_inf_compound(rqst); -- break; -- case SMB2_OP_RENAME: -- if (rc) -- trace_smb3_rename_err(xid, ses->Suid, tcon->tid, rc); -- else -- trace_smb3_rename_done(xid, ses->Suid, tcon->tid); -- free_set_inf_compound(rqst); -- break; -- case SMB2_OP_RMDIR: -- if (rc) -- trace_smb3_rmdir_err(xid, ses->Suid, tcon->tid, rc); -- else -- trace_smb3_rmdir_done(xid, ses->Suid, tcon->tid); -- free_set_inf_compound(rqst); -- break; -- case SMB2_OP_SET_EOF: -- if (rc) -- trace_smb3_set_eof_err(xid, ses->Suid, tcon->tid, rc); -- else -- trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid); -- free_set_inf_compound(rqst); -- break; -- case SMB2_OP_SET_INFO: -- if (rc) -- trace_smb3_set_info_compound_err(xid, ses->Suid, -- tcon->tid, rc); -- else -- trace_smb3_set_info_compound_done(xid, ses->Suid, -- tcon->tid); -- free_set_inf_compound(rqst); -- break; - } -+ SMB2_close_free(&rqst[num_rqst]); - -- if (cfile) -- cifsFileInfo_put(cfile); -- -+ num_cmds += 2; - if (out_iov && out_buftype) { -- memcpy(out_iov, rsp_iov, 3 * sizeof(*out_iov)); -- memcpy(out_buftype, resp_buftype, 3 * sizeof(*out_buftype)); -+ memcpy(out_iov, rsp_iov, num_cmds * sizeof(*out_iov)); -+ memcpy(out_buftype, resp_buftype, -+ num_cmds * sizeof(*out_buftype)); - } else { -- free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); -- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); -- free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base); -+ for (i = 0; i < num_cmds; i++) -+ free_rsp_buf(resp_buftype[i], rsp_iov[i].iov_base); - } -+ num_cmds -= 2; /* correct num_cmds as there could be a retry */ - kfree(vars); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ -+ if (cfile) -+ cifsFileInfo_put(cfile); -+ - return rc; - } - -@@ -577,38 +862,64 @@ int smb2_query_path_info(const unsigned int xid, - const char *full_path, - struct cifs_open_info_data *data) - { -+ struct cifs_open_parms oparms; - __u32 create_options = 0; - struct cifsFileInfo *cfile; - struct cached_fid *cfid = NULL; - struct smb2_hdr *hdr; -- struct kvec out_iov[3] = {}; -+ struct kvec in_iov[3], out_iov[3] = {}; - int out_buftype[3] = {}; -+ int cmds[3]; - bool islink; -+ int i, num_cmds = 0; - int rc, rc2; - - data->adjust_tz = false; - data->reparse_point = false; - -- if (strcmp(full_path, "")) -- rc = -ENOENT; -- else -- rc = open_cached_dir(xid, tcon, full_path, cifs_sb, false, &cfid); -- /* If it is a root and its handle is cached then use it */ -- if (!rc) { -- if (cfid->file_all_info_is_valid) { -- memcpy(&data->fi, &cfid->file_all_info, sizeof(data->fi)); -+ /* -+ * BB TODO: Add support for using cached root handle in SMB3.1.1 POSIX. -+ * Create SMB2_query_posix_info worker function to do non-compounded -+ * query when we already have an open file handle for this. For now this -+ * is fast enough (always using the compounded version). -+ */ -+ if (!tcon->posix_extensions) { -+ if (*full_path) { -+ rc = -ENOENT; - } else { -- rc = SMB2_query_info(xid, tcon, cfid->fid.persistent_fid, -- cfid->fid.volatile_fid, &data->fi); -+ rc = open_cached_dir(xid, tcon, full_path, -+ cifs_sb, false, &cfid); -+ } -+ /* If it is a root and its handle is cached then use it */ -+ if (!rc) { -+ if (cfid->file_all_info_is_valid) { -+ memcpy(&data->fi, &cfid->file_all_info, -+ sizeof(data->fi)); -+ } else { -+ rc = SMB2_query_info(xid, tcon, -+ cfid->fid.persistent_fid, -+ cfid->fid.volatile_fid, -+ &data->fi); -+ } -+ close_cached_dir(cfid); -+ return rc; - } -- close_cached_dir(cfid); -- return rc; -+ cmds[num_cmds++] = SMB2_OP_QUERY_INFO; -+ } else { -+ cmds[num_cmds++] = SMB2_OP_POSIX_QUERY_INFO; - } - -+ in_iov[0].iov_base = data; -+ in_iov[0].iov_len = sizeof(*data); -+ in_iov[1] = in_iov[0]; -+ in_iov[2] = in_iov[0]; -+ - cifs_get_readable_path(tcon, full_path, &cfile); -- rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN, -- create_options, ACL_NO_MODE, data, SMB2_OP_QUERY_INFO, cfile, -- NULL, NULL, out_iov, out_buftype); -+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_READ_ATTRIBUTES, -+ FILE_OPEN, create_options, ACL_NO_MODE); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, -+ &oparms, in_iov, cmds, num_cmds, -+ cfile, out_iov, out_buftype, NULL); - hdr = out_iov[0].iov_base; - /* - * If first iov is unset, then SMB session was dropped or we've got a -@@ -620,18 +931,30 @@ int smb2_query_path_info(const unsigned int xid, - switch (rc) { - case 0: - case -EOPNOTSUPP: -+ /* -+ * BB TODO: When support for special files added to Samba -+ * re-verify this path. -+ */ - rc = parse_create_response(data, cifs_sb, &out_iov[0]); - if (rc || !data->reparse_point) - goto out; - -- create_options |= OPEN_REPARSE_POINT; -- /* Failed on a symbolic link - query a reparse point info */ -+ cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA; -+ /* -+ * Skip SMB2_OP_GET_REPARSE if symlink already parsed in create -+ * response. -+ */ -+ if (data->reparse.tag != IO_REPARSE_TAG_SYMLINK) -+ cmds[num_cmds++] = SMB2_OP_GET_REPARSE; -+ -+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, -+ FILE_READ_ATTRIBUTES | FILE_READ_EA, -+ FILE_OPEN, create_options | -+ OPEN_REPARSE_POINT, ACL_NO_MODE); - cifs_get_readable_path(tcon, full_path, &cfile); - rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, -- FILE_READ_ATTRIBUTES, FILE_OPEN, -- create_options, ACL_NO_MODE, data, -- SMB2_OP_QUERY_INFO, cfile, NULL, NULL, -- NULL, NULL); -+ &oparms, in_iov, cmds, num_cmds, -+ cfile, NULL, NULL, NULL); - break; - case -EREMOTE: - break; -@@ -649,93 +972,8 @@ int smb2_query_path_info(const unsigned int xid, - } - - out: -- free_rsp_buf(out_buftype[0], out_iov[0].iov_base); -- free_rsp_buf(out_buftype[1], out_iov[1].iov_base); -- free_rsp_buf(out_buftype[2], out_iov[2].iov_base); -- return rc; --} -- --int smb311_posix_query_path_info(const unsigned int xid, -- struct cifs_tcon *tcon, -- struct cifs_sb_info *cifs_sb, -- const char *full_path, -- struct cifs_open_info_data *data, -- struct cifs_sid *owner, -- struct cifs_sid *group) --{ -- int rc; -- __u32 create_options = 0; -- struct cifsFileInfo *cfile; -- struct kvec out_iov[3] = {}; -- int out_buftype[3] = {}; -- __u8 *sidsbuf = NULL; -- __u8 *sidsbuf_end = NULL; -- size_t sidsbuflen = 0; -- size_t owner_len, group_len; -- -- data->adjust_tz = false; -- data->reparse_point = false; -- -- /* -- * BB TODO: Add support for using the cached root handle. -- * Create SMB2_query_posix_info worker function to do non-compounded query -- * when we already have an open file handle for this. For now this is fast enough -- * (always using the compounded version). -- */ -- -- cifs_get_readable_path(tcon, full_path, &cfile); -- rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN, -- create_options, ACL_NO_MODE, data, SMB2_OP_POSIX_QUERY_INFO, cfile, -- &sidsbuf, &sidsbuflen, out_iov, out_buftype); -- /* -- * If first iov is unset, then SMB session was dropped or we've got a -- * cached open file (@cfile). -- */ -- if (!out_iov[0].iov_base || out_buftype[0] == CIFS_NO_BUFFER) -- goto out; -- -- switch (rc) { -- case 0: -- case -EOPNOTSUPP: -- /* BB TODO: When support for special files added to Samba re-verify this path */ -- rc = parse_create_response(data, cifs_sb, &out_iov[0]); -- if (rc || !data->reparse_point) -- goto out; -- -- create_options |= OPEN_REPARSE_POINT; -- /* Failed on a symbolic link - query a reparse point info */ -- cifs_get_readable_path(tcon, full_path, &cfile); -- rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, -- FILE_OPEN, create_options, ACL_NO_MODE, data, -- SMB2_OP_POSIX_QUERY_INFO, cfile, -- &sidsbuf, &sidsbuflen, NULL, NULL); -- break; -- } -- --out: -- if (rc == 0) { -- sidsbuf_end = sidsbuf + sidsbuflen; -- -- owner_len = posix_info_sid_size(sidsbuf, sidsbuf_end); -- if (owner_len == -1) { -- rc = -EINVAL; -- goto out; -- } -- memcpy(owner, sidsbuf, owner_len); -- -- group_len = posix_info_sid_size( -- sidsbuf + owner_len, sidsbuf_end); -- if (group_len == -1) { -- rc = -EINVAL; -- goto out; -- } -- memcpy(group, sidsbuf + owner_len, group_len); -- } -- -- kfree(sidsbuf); -- free_rsp_buf(out_buftype[0], out_iov[0].iov_base); -- free_rsp_buf(out_buftype[1], out_iov[1].iov_base); -- free_rsp_buf(out_buftype[2], out_iov[2].iov_base); -+ for (i = 0; i < ARRAY_SIZE(out_buftype); i++) -+ free_rsp_buf(out_buftype[i], out_iov[i].iov_base); - return rc; - } - -@@ -744,10 +982,14 @@ smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode, - struct cifs_tcon *tcon, const char *name, - struct cifs_sb_info *cifs_sb) - { -- return smb2_compound_op(xid, tcon, cifs_sb, name, -- FILE_WRITE_ATTRIBUTES, FILE_CREATE, -- CREATE_NOT_FILE, mode, NULL, SMB2_OP_MKDIR, -- NULL, NULL, NULL, NULL, NULL); -+ struct cifs_open_parms oparms; -+ -+ oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES, -+ FILE_CREATE, CREATE_NOT_FILE, mode); -+ return smb2_compound_op(xid, tcon, cifs_sb, -+ name, &oparms, NULL, -+ &(int){SMB2_OP_MKDIR}, 1, -+ NULL, NULL, NULL, NULL); - } - - void -@@ -755,21 +997,26 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name, - struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon, - const unsigned int xid) - { -- FILE_BASIC_INFO data; -+ struct cifs_open_parms oparms; -+ FILE_BASIC_INFO data = {}; - struct cifsInodeInfo *cifs_i; - struct cifsFileInfo *cfile; -+ struct kvec in_iov; - u32 dosattrs; - int tmprc; - -- memset(&data, 0, sizeof(data)); -+ in_iov.iov_base = &data; -+ in_iov.iov_len = sizeof(data); - cifs_i = CIFS_I(inode); - dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; - data.Attributes = cpu_to_le32(dosattrs); - cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile); -+ oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES, -+ FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE); - tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, -- FILE_WRITE_ATTRIBUTES, FILE_CREATE, -- CREATE_NOT_FILE, ACL_NO_MODE, -- &data, SMB2_OP_SET_INFO, cfile, NULL, NULL, NULL, NULL); -+ &oparms, &in_iov, -+ &(int){SMB2_OP_SET_INFO}, 1, -+ cfile, NULL, NULL, NULL); - if (tmprc == 0) - cifs_i->cifsAttrs = dosattrs; - } -@@ -778,27 +1025,48 @@ int - smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, - struct cifs_sb_info *cifs_sb) - { -+ struct cifs_open_parms oparms; -+ - drop_cached_dir_by_name(xid, tcon, name, cifs_sb); -- return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, -- CREATE_NOT_FILE, ACL_NO_MODE, -- NULL, SMB2_OP_RMDIR, NULL, NULL, NULL, NULL, NULL); -+ oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE, -+ FILE_OPEN, CREATE_NOT_FILE, ACL_NO_MODE); -+ return smb2_compound_op(xid, tcon, cifs_sb, -+ name, &oparms, NULL, -+ &(int){SMB2_OP_RMDIR}, 1, -+ NULL, NULL, NULL, NULL); - } - - int - smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name, -- struct cifs_sb_info *cifs_sb) -+ struct cifs_sb_info *cifs_sb, struct dentry *dentry) - { -- return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, -- CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT, -- ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL, NULL, NULL, NULL, NULL); -+ struct cifs_open_parms oparms; -+ -+ oparms = CIFS_OPARMS(cifs_sb, tcon, name, -+ DELETE, FILE_OPEN, -+ CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT, -+ ACL_NO_MODE); -+ int rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, -+ NULL, &(int){SMB2_OP_DELETE}, 1, -+ NULL, NULL, NULL, dentry); -+ if (rc == -EINVAL) { -+ cifs_dbg(FYI, "invalid lease key, resending request without lease"); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, -+ NULL, &(int){SMB2_OP_DELETE}, 1, -+ NULL, NULL, NULL, NULL); -+ } -+ return rc; - } - - static int smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon, - const char *from_name, const char *to_name, - struct cifs_sb_info *cifs_sb, - __u32 create_options, __u32 access, -- int command, struct cifsFileInfo *cfile) -+ int command, struct cifsFileInfo *cfile, -+ struct dentry *dentry) - { -+ struct cifs_open_parms oparms; -+ struct kvec in_iov; - __le16 *smb2_to_name = NULL; - int rc; - -@@ -807,9 +1075,13 @@ static int smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon, - rc = -ENOMEM; - goto smb2_rename_path; - } -- rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access, -- FILE_OPEN, create_options, ACL_NO_MODE, smb2_to_name, -- command, cfile, NULL, NULL, NULL, NULL); -+ in_iov.iov_base = smb2_to_name; -+ in_iov.iov_len = 2 * UniStrnlen((wchar_t *)smb2_to_name, PATH_MAX); -+ oparms = CIFS_OPARMS(cifs_sb, tcon, from_name, access, FILE_OPEN, -+ create_options, ACL_NO_MODE); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, -+ &oparms, &in_iov, &command, 1, -+ cfile, NULL, NULL, dentry); - smb2_rename_path: - kfree(smb2_to_name); - return rc; -@@ -827,8 +1099,14 @@ int smb2_rename_path(const unsigned int xid, - drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb); - cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile); - -- return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, -- co, DELETE, SMB2_OP_RENAME, cfile); -+ int rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, -+ co, DELETE, SMB2_OP_RENAME, cfile, source_dentry); -+ if (rc == -EINVAL) { -+ cifs_dbg(FYI, "invalid lease key, resending request without lease"); -+ rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, -+ co, DELETE, SMB2_OP_RENAME, cfile, NULL); -+ } -+ return rc; - } - - int smb2_create_hardlink(const unsigned int xid, -@@ -841,31 +1119,51 @@ int smb2_create_hardlink(const unsigned int xid, - - return smb2_set_path_attr(xid, tcon, from_name, to_name, - cifs_sb, co, FILE_READ_ATTRIBUTES, -- SMB2_OP_HARDLINK, NULL); -+ SMB2_OP_HARDLINK, NULL, NULL); - } - - int - smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon, - const char *full_path, __u64 size, -- struct cifs_sb_info *cifs_sb, bool set_alloc) -+ struct cifs_sb_info *cifs_sb, bool set_alloc, -+ struct dentry *dentry) - { -- __le64 eof = cpu_to_le64(size); -+ struct cifs_open_parms oparms; - struct cifsFileInfo *cfile; -+ struct kvec in_iov; -+ __le64 eof = cpu_to_le64(size); -+ int rc; - -+ in_iov.iov_base = &eof; -+ in_iov.iov_len = sizeof(eof); - cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); -- return smb2_compound_op(xid, tcon, cifs_sb, full_path, -- FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE, -- &eof, SMB2_OP_SET_EOF, cfile, NULL, NULL, NULL, NULL); -+ -+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA, -+ FILE_OPEN, 0, ACL_NO_MODE); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, -+ full_path, &oparms, &in_iov, -+ &(int){SMB2_OP_SET_EOF}, 1, -+ cfile, NULL, NULL, dentry); -+ if (rc == -EINVAL) { -+ cifs_dbg(FYI, "invalid lease key, resending request without lease"); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, -+ full_path, &oparms, &in_iov, -+ &(int){SMB2_OP_SET_EOF}, 1, -+ cfile, NULL, NULL, NULL); -+ } -+ return rc; - } - - int - smb2_set_file_info(struct inode *inode, const char *full_path, - FILE_BASIC_INFO *buf, const unsigned int xid) - { -+ struct cifs_open_parms oparms; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - struct tcon_link *tlink; - struct cifs_tcon *tcon; - struct cifsFileInfo *cfile; -+ struct kvec in_iov = { .iov_base = buf, .iov_len = sizeof(*buf), }; - int rc; - - if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) && -@@ -879,10 +1177,100 @@ smb2_set_file_info(struct inode *inode, const char *full_path, - tcon = tlink_tcon(tlink); - - cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); -- rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, -- FILE_WRITE_ATTRIBUTES, FILE_OPEN, -- 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, cfile, -- NULL, NULL, NULL, NULL); -+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_ATTRIBUTES, -+ FILE_OPEN, 0, ACL_NO_MODE); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, -+ full_path, &oparms, &in_iov, -+ &(int){SMB2_OP_SET_INFO}, 1, -+ cfile, NULL, NULL, NULL); - cifs_put_tlink(tlink); - return rc; - } -+ -+struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data, -+ struct super_block *sb, -+ const unsigned int xid, -+ struct cifs_tcon *tcon, -+ const char *full_path, -+ struct kvec *reparse_iov, -+ struct kvec *xattr_iov) -+{ -+ struct cifs_open_parms oparms; -+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb); -+ struct cifsFileInfo *cfile; -+ struct inode *new = NULL; -+ struct kvec in_iov[2]; -+ int cmds[2]; -+ int rc; -+ -+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, -+ SYNCHRONIZE | DELETE | -+ FILE_READ_ATTRIBUTES | -+ FILE_WRITE_ATTRIBUTES, -+ FILE_CREATE, -+ CREATE_NOT_DIR | OPEN_REPARSE_POINT, -+ ACL_NO_MODE); -+ if (xattr_iov) -+ oparms.ea_cctx = xattr_iov; -+ -+ cmds[0] = SMB2_OP_SET_REPARSE; -+ in_iov[0] = *reparse_iov; -+ in_iov[1].iov_base = data; -+ in_iov[1].iov_len = sizeof(*data); -+ -+ if (tcon->posix_extensions) { -+ cmds[1] = SMB2_OP_POSIX_QUERY_INFO; -+ cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, -+ in_iov, cmds, 2, cfile, NULL, NULL, NULL); -+ if (!rc) { -+ rc = smb311_posix_get_inode_info(&new, full_path, -+ data, sb, xid); -+ } -+ } else { -+ cmds[1] = SMB2_OP_QUERY_INFO; -+ cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, -+ in_iov, cmds, 2, cfile, NULL, NULL, NULL); -+ if (!rc) { -+ rc = cifs_get_inode_info(&new, full_path, -+ data, sb, xid, NULL); -+ } -+ } -+ return rc ? ERR_PTR(rc) : new; -+} -+ -+int smb2_query_reparse_point(const unsigned int xid, -+ struct cifs_tcon *tcon, -+ struct cifs_sb_info *cifs_sb, -+ const char *full_path, -+ u32 *tag, struct kvec *rsp, -+ int *rsp_buftype) -+{ -+ struct cifs_open_parms oparms; -+ struct cifs_open_info_data data = {}; -+ struct cifsFileInfo *cfile; -+ struct kvec in_iov = { .iov_base = &data, .iov_len = sizeof(data), }; -+ int rc; -+ -+ cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); -+ -+ cifs_get_readable_path(tcon, full_path, &cfile); -+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_READ_ATTRIBUTES, -+ FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, -+ full_path, &oparms, &in_iov, -+ &(int){SMB2_OP_GET_REPARSE}, 1, -+ cfile, NULL, NULL, NULL); -+ if (rc) -+ goto out; -+ -+ *tag = data.reparse.tag; -+ *rsp = data.reparse.io.iov; -+ *rsp_buftype = data.reparse.io.buftype; -+ memset(&data.reparse.io.iov, 0, sizeof(data.reparse.io.iov)); -+ data.reparse.io.buftype = CIFS_NO_BUFFER; -+out: -+ cifs_free_open_info(&data); -+ return rc; -+} -diff --git a/fs/smb/client/smb2maperror.c b/fs/smb/client/smb2maperror.c -index 1a90dd78b238f..ac1895358908a 100644 ---- a/fs/smb/client/smb2maperror.c -+++ b/fs/smb/client/smb2maperror.c -@@ -1210,6 +1210,8 @@ static const struct status_to_posix_error smb2_error_map_table[] = { - {STATUS_INVALID_TASK_INDEX, -EIO, "STATUS_INVALID_TASK_INDEX"}, - {STATUS_THREAD_ALREADY_IN_TASK, -EIO, "STATUS_THREAD_ALREADY_IN_TASK"}, - {STATUS_CALLBACK_BYPASS, -EIO, "STATUS_CALLBACK_BYPASS"}, -+ {STATUS_SERVER_UNAVAILABLE, -EAGAIN, "STATUS_SERVER_UNAVAILABLE"}, -+ {STATUS_FILE_NOT_AVAILABLE, -EAGAIN, "STATUS_FILE_NOT_AVAILABLE"}, - {STATUS_PORT_CLOSED, -EIO, "STATUS_PORT_CLOSED"}, - {STATUS_MESSAGE_LOST, -EIO, "STATUS_MESSAGE_LOST"}, - {STATUS_INVALID_MESSAGE, -EIO, "STATUS_INVALID_MESSAGE"}, -diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c -index cc72be5a93a93..677ef6f99a5be 100644 ---- a/fs/smb/client/smb2misc.c -+++ b/fs/smb/client/smb2misc.c -@@ -767,7 +767,7 @@ smb2_cancelled_close_fid(struct work_struct *work) - if (rc) - cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc); - -- cifs_put_tcon(tcon); -+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close_fid); - kfree(cancelled); - } - -@@ -811,6 +811,8 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, - if (tcon->tc_count <= 0) { - struct TCP_Server_Info *server = NULL; - -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, -+ netfs_trace_tcon_ref_see_cancelled_close); - WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative"); - spin_unlock(&cifs_tcp_ses_lock); - -@@ -823,12 +825,14 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, - return 0; - } - tcon->tc_count++; -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, -+ netfs_trace_tcon_ref_get_cancelled_close); - spin_unlock(&cifs_tcp_ses_lock); - - rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0, - persistent_fid, volatile_fid); - if (rc) -- cifs_put_tcon(tcon); -+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close); - - return rc; - } -@@ -856,7 +860,7 @@ smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *serve - rsp->PersistentFileId, - rsp->VolatileFileId); - if (rc) -- cifs_put_tcon(tcon); -+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_mid); - - return rc; - } -diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c -index 04fea874d0a33..66cfce456263b 100644 ---- a/fs/smb/client/smb2ops.c -+++ b/fs/smb/client/smb2ops.c -@@ -28,6 +28,7 @@ - #include "fscache.h" - #include "fs_context.h" - #include "cached_dir.h" -+#include "reparse.h" - - /* Change credits for different ops and return the total number of credits */ - static int -@@ -1108,7 +1109,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, - { - struct smb2_compound_vars *vars; - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - struct smb_rqst *rqst; - struct kvec *rsp_iov; - __le16 *utf16_path = NULL; -@@ -1124,6 +1125,13 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, - struct smb2_file_full_ea_info *ea = NULL; - struct smb2_query_info_rsp *rsp; - int rc, used_len = 0; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = CIFS_CP_CREATE_CLOSE_OP; -+ oplock = SMB2_OPLOCK_LEVEL_NONE; -+ server = cifs_pick_channel(ses); - - if (smb3_encryption_required(tcon)) - flags |= CIFS_TRANSFORM_REQ; -@@ -1197,6 +1205,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, - .disposition = FILE_OPEN, - .create_options = cifs_create_options(cifs_sb, 0), - .fid = &fid, -+ .replay = !!(retries), - }; - - rc = SMB2_open_init(tcon, server, -@@ -1244,6 +1253,12 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, - goto sea_exit; - smb2_set_related(&rqst[2]); - -+ if (retries) { -+ smb2_set_replay(server, &rqst[0]); -+ smb2_set_replay(server, &rqst[1]); -+ smb2_set_replay(server, &rqst[2]); -+ } -+ - rc = compound_send_recv(xid, ses, server, - flags, 3, rqst, - resp_buftype, rsp_iov); -@@ -1260,6 +1275,11 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, - kfree(vars); - out_free_path: - kfree(utf16_path); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - #endif -@@ -1485,7 +1505,7 @@ smb2_ioctl_query_info(const unsigned int xid, - struct smb_rqst *rqst; - struct kvec *rsp_iov; - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - char __user *arg = (char __user *)p; - struct smb_query_info qi; - struct smb_query_info __user *pqi; -@@ -1502,6 +1522,13 @@ smb2_ioctl_query_info(const unsigned int xid, - void *data[2]; - int create_options = is_dir ? CREATE_NOT_FILE : CREATE_NOT_DIR; - void (*free_req1_func)(struct smb_rqst *r); -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = CIFS_CP_CREATE_CLOSE_OP; -+ oplock = SMB2_OPLOCK_LEVEL_NONE; -+ server = cifs_pick_channel(ses); - - vars = kzalloc(sizeof(*vars), GFP_ATOMIC); - if (vars == NULL) -@@ -1545,6 +1572,7 @@ smb2_ioctl_query_info(const unsigned int xid, - .disposition = FILE_OPEN, - .create_options = cifs_create_options(cifs_sb, create_options), - .fid = &fid, -+ .replay = !!(retries), - }; - - if (qi.flags & PASSTHRU_FSCTL) { -@@ -1642,6 +1670,12 @@ smb2_ioctl_query_info(const unsigned int xid, - goto free_req_1; - smb2_set_related(&rqst[2]); - -+ if (retries) { -+ smb2_set_replay(server, &rqst[0]); -+ smb2_set_replay(server, &rqst[1]); -+ smb2_set_replay(server, &rqst[2]); -+ } -+ - rc = compound_send_recv(xid, ses, server, - flags, 3, rqst, - resp_buftype, rsp_iov); -@@ -1702,6 +1736,11 @@ smb2_ioctl_query_info(const unsigned int xid, - kfree(buffer); - free_vars: - kfree(vars); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -1932,7 +1971,6 @@ static int - smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon, - struct cifsFileInfo *cfile, __u64 size, bool set_alloc) - { -- __le64 eof = cpu_to_le64(size); - struct inode *inode; - - /* -@@ -1949,7 +1987,7 @@ smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon, - } - - return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, -- cfile->fid.volatile_fid, cfile->pid, &eof); -+ cfile->fid.volatile_fid, cfile->pid, size); - } - - static int -@@ -2229,8 +2267,14 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, - struct cifs_open_parms oparms; - struct smb2_query_directory_rsp *qd_rsp = NULL; - struct smb2_create_rsp *op_rsp = NULL; -- struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); -- int retry_count = 0; -+ struct TCP_Server_Info *server; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ oplock = SMB2_OPLOCK_LEVEL_NONE; -+ server = cifs_pick_channel(tcon->ses); - - utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); - if (!utf16_path) -@@ -2255,6 +2299,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, - .disposition = FILE_OPEN, - .create_options = cifs_create_options(cifs_sb, 0), - .fid = fid, -+ .replay = !!(retries), - }; - - rc = SMB2_open_init(tcon, server, -@@ -2280,14 +2325,15 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, - - smb2_set_related(&rqst[1]); - --again: -+ if (retries) { -+ smb2_set_replay(server, &rqst[0]); -+ smb2_set_replay(server, &rqst[1]); -+ } -+ - rc = compound_send_recv(xid, tcon->ses, server, - flags, 2, rqst, - resp_buftype, rsp_iov); - -- if (rc == -EAGAIN && retry_count++ < 10) -- goto again; -- - /* If the open failed there is nothing to do */ - op_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base; - if (op_rsp == NULL || op_rsp->hdr.Status != STATUS_SUCCESS) { -@@ -2335,6 +2381,11 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, - SMB2_query_directory_free(&rqst[1]); - free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); - free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -2461,6 +2512,22 @@ smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid, - CIFS_CACHE_READ(cinode) ? 1 : 0); - } - -+void -+smb2_set_replay(struct TCP_Server_Info *server, struct smb_rqst *rqst) -+{ -+ struct smb2_hdr *shdr; -+ -+ if (server->dialect < SMB30_PROT_ID) -+ return; -+ -+ shdr = (struct smb2_hdr *)(rqst->rq_iov[0].iov_base); -+ if (shdr == NULL) { -+ cifs_dbg(FYI, "shdr NULL in smb2_set_related\n"); -+ return; -+ } -+ shdr->Flags |= SMB2_FLAGS_REPLAY_OPERATION; -+} -+ - void - smb2_set_related(struct smb_rqst *rqst) - { -@@ -2533,6 +2600,27 @@ smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst) - shdr->NextCommand = cpu_to_le32(len); - } - -+/* -+ * helper function for exponential backoff and check if replayable -+ */ -+bool smb2_should_replay(struct cifs_tcon *tcon, -+ int *pretries, -+ int *pcur_sleep) -+{ -+ if (!pretries || !pcur_sleep) -+ return false; -+ -+ if (tcon->retry || (*pretries)++ < tcon->ses->server->retrans) { -+ msleep(*pcur_sleep); -+ (*pcur_sleep) = ((*pcur_sleep) << 1); -+ if ((*pcur_sleep) > CIFS_MAX_SLEEP) -+ (*pcur_sleep) = CIFS_MAX_SLEEP; -+ return true; -+ } -+ -+ return false; -+} -+ - /* - * Passes the query info response back to the caller on success. - * Caller need to free this with free_rsp_buf(). -@@ -2546,7 +2634,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, - { - struct smb2_compound_vars *vars; - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - int flags = CIFS_CP_CREATE_CLOSE_OP; - struct smb_rqst *rqst; - int resp_buftype[3]; -@@ -2557,6 +2645,13 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, - int rc; - __le16 *utf16_path; - struct cached_fid *cfid = NULL; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = CIFS_CP_CREATE_CLOSE_OP; -+ oplock = SMB2_OPLOCK_LEVEL_NONE; -+ server = cifs_pick_channel(ses); - - if (!path) - path = ""; -@@ -2593,6 +2688,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, - .disposition = FILE_OPEN, - .create_options = cifs_create_options(cifs_sb, 0), - .fid = &fid, -+ .replay = !!(retries), - }; - - rc = SMB2_open_init(tcon, server, -@@ -2637,6 +2733,14 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, - goto qic_exit; - smb2_set_related(&rqst[2]); - -+ if (retries) { -+ if (!cfid) { -+ smb2_set_replay(server, &rqst[0]); -+ smb2_set_replay(server, &rqst[2]); -+ } -+ smb2_set_replay(server, &rqst[1]); -+ } -+ - if (cfid) { - rc = compound_send_recv(xid, ses, server, - flags, 1, &rqst[1], -@@ -2669,6 +2773,11 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, - kfree(vars); - out_free_path: - kfree(utf16_path); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -2806,8 +2915,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, - tcon = list_first_entry_or_null(&ses->tcon_list, - struct cifs_tcon, - tcon_list); -- if (tcon) -+ if (tcon) { - tcon->tc_count++; -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, -+ netfs_trace_tcon_ref_get_dfs_refer); -+ } - spin_unlock(&cifs_tcp_ses_lock); - } - -@@ -2871,6 +2983,8 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, - /* ipc tcons are not refcounted */ - spin_lock(&cifs_tcp_ses_lock); - tcon->tc_count--; -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, -+ netfs_trace_tcon_ref_dec_dfs_refer); - /* tc_count can never go negative */ - WARN_ON(tcon->tc_count < 0); - spin_unlock(&cifs_tcp_ses_lock); -@@ -2881,260 +2995,6 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, - return rc; - } - --/* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */ --static int parse_reparse_posix(struct reparse_posix_data *buf, -- struct cifs_sb_info *cifs_sb, -- struct cifs_open_info_data *data) --{ -- unsigned int len; -- u64 type; -- -- switch ((type = le64_to_cpu(buf->InodeType))) { -- case NFS_SPECFILE_LNK: -- len = le16_to_cpu(buf->ReparseDataLength); -- data->symlink_target = cifs_strndup_from_utf16(buf->DataBuffer, -- len, true, -- cifs_sb->local_nls); -- if (!data->symlink_target) -- return -ENOMEM; -- convert_delimiter(data->symlink_target, '/'); -- cifs_dbg(FYI, "%s: target path: %s\n", -- __func__, data->symlink_target); -- break; -- case NFS_SPECFILE_CHR: -- case NFS_SPECFILE_BLK: -- case NFS_SPECFILE_FIFO: -- case NFS_SPECFILE_SOCK: -- break; -- default: -- cifs_dbg(VFS, "%s: unhandled inode type: 0x%llx\n", -- __func__, type); -- return -EOPNOTSUPP; -- } -- return 0; --} -- --static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym, -- u32 plen, bool unicode, -- struct cifs_sb_info *cifs_sb, -- struct cifs_open_info_data *data) --{ -- unsigned int len; -- unsigned int offs; -- -- /* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */ -- -- offs = le16_to_cpu(sym->SubstituteNameOffset); -- len = le16_to_cpu(sym->SubstituteNameLength); -- if (offs + 20 > plen || offs + len + 20 > plen) { -- cifs_dbg(VFS, "srv returned malformed symlink buffer\n"); -- return -EIO; -- } -- -- data->symlink_target = cifs_strndup_from_utf16(sym->PathBuffer + offs, -- len, unicode, -- cifs_sb->local_nls); -- if (!data->symlink_target) -- return -ENOMEM; -- -- convert_delimiter(data->symlink_target, '/'); -- cifs_dbg(FYI, "%s: target path: %s\n", __func__, data->symlink_target); -- -- return 0; --} -- --int parse_reparse_point(struct reparse_data_buffer *buf, -- u32 plen, struct cifs_sb_info *cifs_sb, -- bool unicode, struct cifs_open_info_data *data) --{ -- if (plen < sizeof(*buf)) { -- cifs_dbg(VFS, "%s: reparse buffer is too small. Must be at least 8 bytes but was %d\n", -- __func__, plen); -- return -EIO; -- } -- -- if (plen < le16_to_cpu(buf->ReparseDataLength) + sizeof(*buf)) { -- cifs_dbg(VFS, "%s: invalid reparse buf length: %d\n", -- __func__, plen); -- return -EIO; -- } -- -- data->reparse.buf = buf; -- -- /* See MS-FSCC 2.1.2 */ -- switch (le32_to_cpu(buf->ReparseTag)) { -- case IO_REPARSE_TAG_NFS: -- return parse_reparse_posix((struct reparse_posix_data *)buf, -- cifs_sb, data); -- case IO_REPARSE_TAG_SYMLINK: -- return parse_reparse_symlink( -- (struct reparse_symlink_data_buffer *)buf, -- plen, unicode, cifs_sb, data); -- case IO_REPARSE_TAG_LX_SYMLINK: -- case IO_REPARSE_TAG_AF_UNIX: -- case IO_REPARSE_TAG_LX_FIFO: -- case IO_REPARSE_TAG_LX_CHR: -- case IO_REPARSE_TAG_LX_BLK: -- return 0; -- default: -- cifs_dbg(VFS, "%s: unhandled reparse tag: 0x%08x\n", -- __func__, le32_to_cpu(buf->ReparseTag)); -- return -EOPNOTSUPP; -- } --} -- --static int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, -- struct kvec *rsp_iov, -- struct cifs_open_info_data *data) --{ -- struct reparse_data_buffer *buf; -- struct smb2_ioctl_rsp *io = rsp_iov->iov_base; -- u32 plen = le32_to_cpu(io->OutputCount); -- -- buf = (struct reparse_data_buffer *)((u8 *)io + -- le32_to_cpu(io->OutputOffset)); -- return parse_reparse_point(buf, plen, cifs_sb, true, data); --} -- --static int smb2_query_reparse_point(const unsigned int xid, -- struct cifs_tcon *tcon, -- struct cifs_sb_info *cifs_sb, -- const char *full_path, -- u32 *tag, struct kvec *rsp, -- int *rsp_buftype) --{ -- struct smb2_compound_vars *vars; -- int rc; -- __le16 *utf16_path = NULL; -- __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; -- struct cifs_open_parms oparms; -- struct cifs_fid fid; -- struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); -- int flags = CIFS_CP_CREATE_CLOSE_OP; -- struct smb_rqst *rqst; -- int resp_buftype[3]; -- struct kvec *rsp_iov; -- struct smb2_ioctl_rsp *ioctl_rsp; -- struct reparse_data_buffer *reparse_buf; -- u32 off, count, len; -- -- cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); -- -- if (smb3_encryption_required(tcon)) -- flags |= CIFS_TRANSFORM_REQ; -- -- utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); -- if (!utf16_path) -- return -ENOMEM; -- -- resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; -- vars = kzalloc(sizeof(*vars), GFP_KERNEL); -- if (!vars) { -- rc = -ENOMEM; -- goto out_free_path; -- } -- rqst = vars->rqst; -- rsp_iov = vars->rsp_iov; -- -- /* -- * setup smb2open - TODO add optimization to call cifs_get_readable_path -- * to see if there is a handle already open that we can use -- */ -- rqst[0].rq_iov = vars->open_iov; -- rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; -- -- oparms = (struct cifs_open_parms) { -- .tcon = tcon, -- .path = full_path, -- .desired_access = FILE_READ_ATTRIBUTES, -- .disposition = FILE_OPEN, -- .create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT), -- .fid = &fid, -- }; -- -- rc = SMB2_open_init(tcon, server, -- &rqst[0], &oplock, &oparms, utf16_path); -- if (rc) -- goto query_rp_exit; -- smb2_set_next_command(tcon, &rqst[0]); -- -- -- /* IOCTL */ -- rqst[1].rq_iov = vars->io_iov; -- rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE; -- -- rc = SMB2_ioctl_init(tcon, server, -- &rqst[1], COMPOUND_FID, -- COMPOUND_FID, FSCTL_GET_REPARSE_POINT, NULL, 0, -- CIFSMaxBufSize - -- MAX_SMB2_CREATE_RESPONSE_SIZE - -- MAX_SMB2_CLOSE_RESPONSE_SIZE); -- if (rc) -- goto query_rp_exit; -- -- smb2_set_next_command(tcon, &rqst[1]); -- smb2_set_related(&rqst[1]); -- -- /* Close */ -- rqst[2].rq_iov = &vars->close_iov; -- rqst[2].rq_nvec = 1; -- -- rc = SMB2_close_init(tcon, server, -- &rqst[2], COMPOUND_FID, COMPOUND_FID, false); -- if (rc) -- goto query_rp_exit; -- -- smb2_set_related(&rqst[2]); -- -- rc = compound_send_recv(xid, tcon->ses, server, -- flags, 3, rqst, -- resp_buftype, rsp_iov); -- -- ioctl_rsp = rsp_iov[1].iov_base; -- -- /* -- * Open was successful and we got an ioctl response. -- */ -- if (rc == 0) { -- /* See MS-FSCC 2.3.23 */ -- off = le32_to_cpu(ioctl_rsp->OutputOffset); -- count = le32_to_cpu(ioctl_rsp->OutputCount); -- if (check_add_overflow(off, count, &len) || -- len > rsp_iov[1].iov_len) { -- cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n", -- __func__, off, count); -- rc = -EIO; -- goto query_rp_exit; -- } -- -- reparse_buf = (void *)((u8 *)ioctl_rsp + off); -- len = sizeof(*reparse_buf); -- if (count < len || -- count < le16_to_cpu(reparse_buf->ReparseDataLength) + len) { -- cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n", -- __func__, off, count); -- rc = -EIO; -- goto query_rp_exit; -- } -- *tag = le32_to_cpu(reparse_buf->ReparseTag); -- *rsp = rsp_iov[1]; -- *rsp_buftype = resp_buftype[1]; -- resp_buftype[1] = CIFS_NO_BUFFER; -- } -- -- query_rp_exit: -- SMB2_open_free(&rqst[0]); -- SMB2_ioctl_free(&rqst[1]); -- SMB2_close_free(&rqst[2]); -- free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); -- free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); -- free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base); -- kfree(vars); --out_free_path: -- kfree(utf16_path); -- return rc; --} -- - static struct cifs_ntsd * - get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb, - const struct cifs_fid *cifsfid, u32 *pacllen, u32 info) -@@ -3335,7 +3195,6 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, - unsigned long long new_size; - long rc; - unsigned int xid; -- __le64 eof; - - xid = get_xid(); - -@@ -3365,9 +3224,8 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, - */ - new_size = offset + len; - if (keep_size == false && (unsigned long long)i_size_read(inode) < new_size) { -- eof = cpu_to_le64(new_size); - rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, -- cfile->fid.volatile_fid, cfile->pid, &eof); -+ cfile->fid.volatile_fid, cfile->pid, new_size); - if (rc >= 0) { - truncate_setsize(inode, new_size); - fscache_resize_cookie(cifs_inode_cookie(inode), new_size); -@@ -3560,7 +3418,7 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, - struct cifsFileInfo *cfile = file->private_data; - long rc = -EOPNOTSUPP; - unsigned int xid; -- __le64 eof; -+ loff_t new_eof; - - xid = get_xid(); - -@@ -3589,14 +3447,14 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, - if (cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE) - smb2_set_sparse(xid, tcon, cfile, inode, false); - -- eof = cpu_to_le64(off + len); -+ new_eof = off + len; - rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, -- cfile->fid.volatile_fid, cfile->pid, &eof); -+ cfile->fid.volatile_fid, cfile->pid, new_eof); - if (rc == 0) { -- cifsi->server_eof = off + len; -- cifs_setsize(inode, off + len); -+ cifsi->server_eof = new_eof; -+ cifs_setsize(inode, new_eof); - cifs_truncate_page(inode->i_mapping, inode->i_size); -- truncate_setsize(inode, off + len); -+ truncate_setsize(inode, new_eof); - } - goto out; - } -@@ -3687,8 +3545,7 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon, - struct inode *inode = file_inode(file); - struct cifsFileInfo *cfile = file->private_data; - struct cifsInodeInfo *cifsi = CIFS_I(inode); -- __le64 eof; -- loff_t old_eof; -+ loff_t old_eof, new_eof; - - xid = get_xid(); - -@@ -3713,9 +3570,9 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon, - if (rc < 0) - goto out_2; - -- eof = cpu_to_le64(old_eof - len); -+ new_eof = old_eof - len; - rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, -- cfile->fid.volatile_fid, cfile->pid, &eof); -+ cfile->fid.volatile_fid, cfile->pid, new_eof); - if (rc < 0) - goto out_2; - -@@ -3739,8 +3596,7 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon, - unsigned int xid; - struct cifsFileInfo *cfile = file->private_data; - struct inode *inode = file_inode(file); -- __le64 eof; -- __u64 count, old_eof; -+ __u64 count, old_eof, new_eof; - - xid = get_xid(); - -@@ -3753,20 +3609,20 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon, - } - - count = old_eof - off; -- eof = cpu_to_le64(old_eof + len); -+ new_eof = old_eof + len; - - filemap_invalidate_lock(inode->i_mapping); -- rc = filemap_write_and_wait_range(inode->i_mapping, off, old_eof + len - 1); -+ rc = filemap_write_and_wait_range(inode->i_mapping, off, new_eof - 1); - if (rc < 0) - goto out_2; - truncate_pagecache_range(inode, off, old_eof); - - rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, -- cfile->fid.volatile_fid, cfile->pid, &eof); -+ cfile->fid.volatile_fid, cfile->pid, new_eof); - if (rc < 0) - goto out_2; - -- truncate_setsize(inode, old_eof + len); -+ truncate_setsize(inode, new_eof); - fscache_resize_cookie(cifs_inode_cookie(inode), i_size_read(inode)); - - rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len); -@@ -5105,98 +4961,107 @@ static int smb2_next_header(struct TCP_Server_Info *server, char *buf, - return 0; - } - --static int --smb2_make_node(unsigned int xid, struct inode *inode, -- struct dentry *dentry, struct cifs_tcon *tcon, -- const char *full_path, umode_t mode, dev_t dev) -+static int __cifs_sfu_make_node(unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, umode_t mode, dev_t dev) - { -+ struct TCP_Server_Info *server = tcon->ses->server; -+ struct cifs_open_parms oparms; -+ struct cifs_io_parms io_parms = {}; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); -- int rc = -EPERM; -- struct cifs_open_info_data buf = {}; -- struct cifs_io_parms io_parms = {0}; -- __u32 oplock = 0; - struct cifs_fid fid; -- struct cifs_open_parms oparms; - unsigned int bytes_written; -- struct win_dev *pdev; -+ struct win_dev pdev = {}; - struct kvec iov[2]; -+ __u32 oplock = server->oplocks ? REQ_OPLOCK : 0; -+ int rc; - -- /* -- * Check if mounted with mount parm 'sfu' mount parm. -- * SFU emulation should work with all servers, but only -- * supports block and char device (no socket & fifo), -- * and was used by default in earlier versions of Windows -- */ -- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) -- return rc; -+ switch (mode & S_IFMT) { -+ case S_IFCHR: -+ strscpy(pdev.type, "IntxCHR", strlen("IntxChr")); -+ pdev.major = cpu_to_le64(MAJOR(dev)); -+ pdev.minor = cpu_to_le64(MINOR(dev)); -+ break; -+ case S_IFBLK: -+ strscpy(pdev.type, "IntxBLK", strlen("IntxBLK")); -+ pdev.major = cpu_to_le64(MAJOR(dev)); -+ pdev.minor = cpu_to_le64(MINOR(dev)); -+ break; -+ case S_IFIFO: -+ strscpy(pdev.type, "LnxFIFO", strlen("LnxFIFO")); -+ break; -+ default: -+ return -EPERM; -+ } - -- /* -- * TODO: Add ability to create instead via reparse point. Windows (e.g. -- * their current NFS server) uses this approach to expose special files -- * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions -- */ -+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, GENERIC_WRITE, -+ FILE_CREATE, CREATE_NOT_DIR | -+ CREATE_OPTION_SPECIAL, ACL_NO_MODE); -+ oparms.fid = &fid; - -- if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode)) -+ rc = server->ops->open(xid, &oparms, &oplock, NULL); -+ if (rc) - return rc; - -- cifs_dbg(FYI, "sfu compat create special file\n"); -+ io_parms.pid = current->tgid; -+ io_parms.tcon = tcon; -+ io_parms.length = sizeof(pdev); -+ iov[1].iov_base = &pdev; -+ iov[1].iov_len = sizeof(pdev); - -- oparms = (struct cifs_open_parms) { -- .tcon = tcon, -- .cifs_sb = cifs_sb, -- .desired_access = GENERIC_WRITE, -- .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | -- CREATE_OPTION_SPECIAL), -- .disposition = FILE_CREATE, -- .path = full_path, -- .fid = &fid, -- }; -+ rc = server->ops->sync_write(xid, &fid, &io_parms, -+ &bytes_written, iov, 1); -+ server->ops->close(xid, tcon, &fid); -+ return rc; -+} - -- if (tcon->ses->server->oplocks) -- oplock = REQ_OPLOCK; -- else -- oplock = 0; -- rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf); -+int cifs_sfu_make_node(unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, umode_t mode, dev_t dev) -+{ -+ struct inode *new = NULL; -+ int rc; -+ -+ rc = __cifs_sfu_make_node(xid, inode, dentry, tcon, -+ full_path, mode, dev); - if (rc) - return rc; - -+ if (tcon->posix_extensions) { -+ rc = smb311_posix_get_inode_info(&new, full_path, NULL, -+ inode->i_sb, xid); -+ } else if (tcon->unix_ext) { -+ rc = cifs_get_inode_info_unix(&new, full_path, -+ inode->i_sb, xid); -+ } else { -+ rc = cifs_get_inode_info(&new, full_path, NULL, -+ inode->i_sb, xid, NULL); -+ } -+ if (!rc) -+ d_instantiate(dentry, new); -+ return rc; -+} -+ -+static int smb2_make_node(unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, umode_t mode, dev_t dev) -+{ -+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); -+ int rc; -+ - /* -- * BB Do not bother to decode buf since no local inode yet to put -- * timestamps in, but we can reuse it safely. -+ * Check if mounted with mount parm 'sfu' mount parm. -+ * SFU emulation should work with all servers, but only -+ * supports block and char device (no socket & fifo), -+ * and was used by default in earlier versions of Windows - */ -- -- pdev = (struct win_dev *)&buf.fi; -- io_parms.pid = current->tgid; -- io_parms.tcon = tcon; -- io_parms.offset = 0; -- io_parms.length = sizeof(struct win_dev); -- iov[1].iov_base = &buf.fi; -- iov[1].iov_len = sizeof(struct win_dev); -- if (S_ISCHR(mode)) { -- memcpy(pdev->type, "IntxCHR", 8); -- pdev->major = cpu_to_le64(MAJOR(dev)); -- pdev->minor = cpu_to_le64(MINOR(dev)); -- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, -- &bytes_written, iov, 1); -- } else if (S_ISBLK(mode)) { -- memcpy(pdev->type, "IntxBLK", 8); -- pdev->major = cpu_to_le64(MAJOR(dev)); -- pdev->minor = cpu_to_le64(MINOR(dev)); -- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, -- &bytes_written, iov, 1); -- } else if (S_ISFIFO(mode)) { -- memcpy(pdev->type, "LnxFIFO", 8); -- pdev->major = 0; -- pdev->minor = 0; -- rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, -- &bytes_written, iov, 1); -- } -- tcon->ses->server->ops->close(xid, tcon, &fid); -- d_drop(dentry); -- -- /* FIXME: add code here to set EAs */ -- -- cifs_free_open_info(&buf); -+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { -+ rc = cifs_sfu_make_node(xid, inode, dentry, tcon, -+ full_path, mode, dev); -+ } else { -+ rc = smb2_mknod_reparse(xid, inode, dentry, tcon, -+ full_path, mode, dev); -+ } - return rc; - } - -@@ -5253,6 +5118,7 @@ struct smb_version_operations smb20_operations = { - .parse_reparse_point = smb2_parse_reparse_point, - .query_mf_symlink = smb3_query_mf_symlink, - .create_mf_symlink = smb3_create_mf_symlink, -+ .create_reparse_symlink = smb2_create_reparse_symlink, - .open = smb2_open_file, - .set_fid = smb2_set_fid, - .close = smb2_close_file, -@@ -5355,6 +5221,7 @@ struct smb_version_operations smb21_operations = { - .parse_reparse_point = smb2_parse_reparse_point, - .query_mf_symlink = smb3_query_mf_symlink, - .create_mf_symlink = smb3_create_mf_symlink, -+ .create_reparse_symlink = smb2_create_reparse_symlink, - .open = smb2_open_file, - .set_fid = smb2_set_fid, - .close = smb2_close_file, -@@ -5461,6 +5328,7 @@ struct smb_version_operations smb30_operations = { - .parse_reparse_point = smb2_parse_reparse_point, - .query_mf_symlink = smb3_query_mf_symlink, - .create_mf_symlink = smb3_create_mf_symlink, -+ .create_reparse_symlink = smb2_create_reparse_symlink, - .open = smb2_open_file, - .set_fid = smb2_set_fid, - .close = smb2_close_file, -@@ -5576,6 +5444,7 @@ struct smb_version_operations smb311_operations = { - .parse_reparse_point = smb2_parse_reparse_point, - .query_mf_symlink = smb3_query_mf_symlink, - .create_mf_symlink = smb3_create_mf_symlink, -+ .create_reparse_symlink = smb2_create_reparse_symlink, - .open = smb2_open_file, - .set_fid = smb2_set_fid, - .close = smb2_close_file, -diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c -index 70530108b9bb9..a5efce03cb58e 100644 ---- a/fs/smb/client/smb2pdu.c -+++ b/fs/smb/client/smb2pdu.c -@@ -743,7 +743,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, - pneg_ctxt += sizeof(struct smb2_posix_neg_context); - neg_context_count++; - -- if (server->compress_algorithm) { -+ if (server->compression.requested) { - build_compression_ctxt((struct smb2_compression_capabilities_context *) - pneg_ctxt); - ctxt_len = ALIGN(sizeof(struct smb2_compression_capabilities_context), 8); -@@ -791,6 +791,9 @@ static void decode_compress_ctx(struct TCP_Server_Info *server, - struct smb2_compression_capabilities_context *ctxt) - { - unsigned int len = le16_to_cpu(ctxt->DataLength); -+ __le16 alg; -+ -+ server->compression.enabled = false; - - /* - * Caller checked that DataLength remains within SMB boundary. We still -@@ -801,15 +804,22 @@ static void decode_compress_ctx(struct TCP_Server_Info *server, - pr_warn_once("server sent bad compression cntxt\n"); - return; - } -+ - if (le16_to_cpu(ctxt->CompressionAlgorithmCount) != 1) { -- pr_warn_once("Invalid SMB3 compress algorithm count\n"); -+ pr_warn_once("invalid SMB3 compress algorithm count\n"); - return; - } -- if (le16_to_cpu(ctxt->CompressionAlgorithms[0]) > 3) { -- pr_warn_once("unknown compression algorithm\n"); -+ -+ alg = ctxt->CompressionAlgorithms[0]; -+ -+ /* 'NONE' (0) compressor type is never negotiated */ -+ if (alg == 0 || le16_to_cpu(alg) > 3) { -+ pr_warn_once("invalid compression algorithm '%u'\n", alg); - return; - } -- server->compress_algorithm = ctxt->CompressionAlgorithms[0]; -+ -+ server->compression.alg = alg; -+ server->compression.enabled = true; - } - - static int decode_encrypt_ctx(struct TCP_Server_Info *server, -@@ -2019,10 +2029,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, - __le16 *unc_path = NULL; - int flags = 0; - unsigned int total_len; -- struct TCP_Server_Info *server; -- -- /* always use master channel */ -- server = ses->server; -+ struct TCP_Server_Info *server = cifs_pick_channel(ses); - - cifs_dbg(FYI, "TCON\n"); - -@@ -2155,6 +2162,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) - struct smb2_tree_disconnect_req *req; /* response is trivial */ - int rc = 0; - struct cifs_ses *ses = tcon->ses; -+ struct TCP_Server_Info *server = cifs_pick_channel(ses); - int flags = 0; - unsigned int total_len; - struct kvec iov[1]; -@@ -2177,7 +2185,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) - - invalidate_all_cached_dirs(tcon); - -- rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, ses->server, -+ rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, server, - (void **) &req, - &total_len); - if (rc) -@@ -2195,7 +2203,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) - rqst.rq_iov = iov; - rqst.rq_nvec = 1; - -- rc = cifs_send_recv(xid, ses, ses->server, -+ rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buf_type, flags, &rsp_iov); - cifs_small_buf_release(req); - if (rc) { -@@ -2423,8 +2431,13 @@ create_durable_v2_buf(struct cifs_open_parms *oparms) - */ - buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout); - buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT); -- generate_random_uuid(buf->dcontext.CreateGuid); -- memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16); -+ -+ /* for replay, we should not overwrite the existing create guid */ -+ if (!oparms->replay) { -+ generate_random_uuid(buf->dcontext.CreateGuid); -+ memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16); -+ } else -+ memcpy(buf->dcontext.CreateGuid, pfid->create_guid, 16); - - /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */ - buf->Name[0] = 'D'; -@@ -2729,6 +2742,17 @@ add_query_id_context(struct kvec *iov, unsigned int *num_iovec) - return 0; - } - -+static void add_ea_context(struct cifs_open_parms *oparms, -+ struct kvec *rq_iov, unsigned int *num_iovs) -+{ -+ struct kvec *iov = oparms->ea_cctx; -+ -+ if (iov && iov->iov_base && iov->iov_len) { -+ rq_iov[(*num_iovs)++] = *iov; -+ memset(iov, 0, sizeof(*iov)); -+ } -+} -+ - static int - alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len, - const char *treename, const __le16 *path) -@@ -2797,7 +2821,14 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, - int flags = 0; - unsigned int total_len; - __le16 *utf16_path = NULL; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ n_iov = 2; -+ server = cifs_pick_channel(ses); - - cifs_dbg(FYI, "mkdir\n"); - -@@ -2901,6 +2932,10 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, - /* no need to inc num_remote_opens because we close it just below */ - trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, full_path, CREATE_NOT_FILE, - FILE_WRITE_ATTRIBUTES); -+ -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - /* resource #4: response buffer */ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); -@@ -2938,6 +2973,11 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, - cifs_small_buf_release(req); - err_free_path: - kfree(utf16_path); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -3079,6 +3119,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, - } - - add_query_id_context(iov, &n_iov); -+ add_ea_context(oparms, iov, &n_iov); - - if (n_iov > 2) { - /* -@@ -3133,12 +3174,19 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, - struct smb2_create_rsp *rsp = NULL; - struct cifs_tcon *tcon = oparms->tcon; - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - struct kvec iov[SMB2_CREATE_IOV_SIZE]; - struct kvec rsp_iov = {NULL, 0}; - int resp_buftype = CIFS_NO_BUFFER; - int rc = 0; - int flags = 0; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ server = cifs_pick_channel(ses); -+ oparms->replay = !!(retries); - - cifs_dbg(FYI, "create/open\n"); - if (!ses || !server) -@@ -3160,6 +3208,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, - trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid, oparms->path, - oparms->create_options, oparms->desired_access); - -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, - &rsp_iov); -@@ -3213,6 +3264,11 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, - creat_exit: - SMB2_open_free(&rqst); - free_rsp_buf(resp_buftype, rsp); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -3337,15 +3393,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, - int resp_buftype = CIFS_NO_BUFFER; - int rc = 0; - int flags = 0; -- -- cifs_dbg(FYI, "SMB2 IOCTL\n"); -- -- if (out_data != NULL) -- *out_data = NULL; -- -- /* zero out returned data len, in case of error */ -- if (plen) -- *plen = 0; -+ int retries = 0, cur_sleep = 1; - - if (!tcon) - return -EIO; -@@ -3354,10 +3402,23 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, - if (!ses) - return -EIO; - -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; - server = cifs_pick_channel(ses); -+ - if (!server) - return -EIO; - -+ cifs_dbg(FYI, "SMB2 IOCTL\n"); -+ -+ if (out_data != NULL) -+ *out_data = NULL; -+ -+ /* zero out returned data len, in case of error */ -+ if (plen) -+ *plen = 0; -+ - if (smb3_encryption_required(tcon)) - flags |= CIFS_TRANSFORM_REQ; - -@@ -3372,6 +3433,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, - if (rc) - goto ioctl_exit; - -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, - &rsp_iov); -@@ -3441,6 +3505,11 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, - ioctl_exit: - SMB2_ioctl_free(&rqst); - free_rsp_buf(resp_buftype, rsp); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -3512,13 +3581,20 @@ __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, - struct smb_rqst rqst; - struct smb2_close_rsp *rsp = NULL; - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - struct kvec iov[1]; - struct kvec rsp_iov; - int resp_buftype = CIFS_NO_BUFFER; - int rc = 0; - int flags = 0; - bool query_attrs = false; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ query_attrs = false; -+ server = cifs_pick_channel(ses); - - cifs_dbg(FYI, "Close\n"); - -@@ -3544,6 +3620,9 @@ __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, - if (rc) - goto close_exit; - -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); - rsp = (struct smb2_close_rsp *)rsp_iov.iov_base; -@@ -3577,6 +3656,11 @@ __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, - cifs_dbg(VFS, "handle cancelled close fid 0x%llx returned error %d\n", - persistent_fid, tmp_rc); - } -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -3707,12 +3791,19 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, - struct TCP_Server_Info *server; - int flags = 0; - bool allocated = false; -+ int retries = 0, cur_sleep = 1; - - cifs_dbg(FYI, "Query Info\n"); - - if (!ses) - return -EIO; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ allocated = false; - server = cifs_pick_channel(ses); -+ - if (!server) - return -EIO; - -@@ -3734,6 +3825,9 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, - trace_smb3_query_info_enter(xid, persistent_fid, tcon->tid, - ses->Suid, info_class, (__u32)info_type); - -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); - rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; -@@ -3776,6 +3870,11 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, - qinf_exit: - SMB2_query_info_free(&rqst); - free_rsp_buf(resp_buftype, rsp); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -3876,7 +3975,7 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, - u32 *plen /* returned data len */) - { - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - struct smb_rqst rqst; - struct smb2_change_notify_rsp *smb_rsp; - struct kvec iov[1]; -@@ -3884,6 +3983,12 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, - int resp_buftype = CIFS_NO_BUFFER; - int flags = 0; - int rc = 0; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ server = cifs_pick_channel(ses); - - cifs_dbg(FYI, "change notify\n"); - if (!ses || !server) -@@ -3908,6 +4013,10 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, - - trace_smb3_notify_enter(xid, persistent_fid, tcon->tid, ses->Suid, - (u8)watch_tree, completion_filter); -+ -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); - -@@ -3942,6 +4051,11 @@ SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon, - if (rqst.rq_iov) - cifs_small_buf_release(rqst.rq_iov[0].iov_base); /* request */ - free_rsp_buf(resp_buftype, rsp_iov.iov_base); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -3979,7 +4093,7 @@ void smb2_reconnect_server(struct work_struct *work) - struct cifs_ses *ses, *ses2; - struct cifs_tcon *tcon, *tcon2; - struct list_head tmp_list, tmp_ses_list; -- bool tcon_exist = false, ses_exist = false; -+ bool ses_exist = false; - bool tcon_selected = false; - int rc; - bool resched = false; -@@ -4024,8 +4138,10 @@ void smb2_reconnect_server(struct work_struct *work) - list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { - if (tcon->need_reconnect || tcon->need_reopen_files) { - tcon->tc_count++; -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, -+ netfs_trace_tcon_ref_get_reconnect_server); - list_add_tail(&tcon->rlist, &tmp_list); -- tcon_selected = tcon_exist = true; -+ tcon_selected = true; - } - } - /* -@@ -4034,7 +4150,7 @@ void smb2_reconnect_server(struct work_struct *work) - */ - if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) { - list_add_tail(&ses->tcon_ipc->rlist, &tmp_list); -- tcon_selected = tcon_exist = true; -+ tcon_selected = true; - cifs_smb_ses_inc_refcount(ses); - } - /* -@@ -4062,14 +4178,14 @@ void smb2_reconnect_server(struct work_struct *work) - if (tcon->ipc) - cifs_put_smb_ses(tcon->ses); - else -- cifs_put_tcon(tcon); -+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_reconnect_server); - } - - if (!ses_exist) - goto done; - - /* allocate a dummy tcon struct used for reconnect */ -- tcon = tcon_info_alloc(false); -+ tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_reconnect_server); - if (!tcon) { - resched = true; - list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) { -@@ -4092,7 +4208,7 @@ void smb2_reconnect_server(struct work_struct *work) - list_del_init(&ses->rlist); - cifs_put_smb_ses(ses); - } -- tconInfoFree(tcon); -+ tconInfoFree(tcon, netfs_trace_tcon_ref_free_reconnect_server); - - done: - cifs_dbg(FYI, "Reconnecting tcons and channels finished\n"); -@@ -4184,10 +4300,16 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, - struct smb_rqst rqst; - struct kvec iov[1]; - struct kvec rsp_iov = {NULL, 0}; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - int resp_buftype = CIFS_NO_BUFFER; - int flags = 0; - int rc = 0; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ server = cifs_pick_channel(ses); - - cifs_dbg(FYI, "flush\n"); - if (!ses || !(ses->server)) -@@ -4207,6 +4329,10 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, - goto flush_exit; - - trace_smb3_flush_enter(xid, persistent_fid, tcon->tid, ses->Suid); -+ -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); - -@@ -4221,6 +4347,11 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, - flush_exit: - SMB2_flush_free(&rqst); - free_rsp_buf(resp_buftype, rsp_iov.iov_base); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -4700,7 +4831,7 @@ smb2_async_writev(struct cifs_writedata *wdata, - struct cifs_io_parms *io_parms = NULL; - int credit_request; - -- if (!wdata->server) -+ if (!wdata->server || wdata->replay) - server = wdata->server = cifs_pick_channel(tcon->ses); - - /* -@@ -4785,6 +4916,8 @@ smb2_async_writev(struct cifs_writedata *wdata, - rqst.rq_nvec = 1; - rqst.rq_iter = wdata->iter; - rqst.rq_iter_size = iov_iter_count(&rqst.rq_iter); -+ if (wdata->replay) -+ smb2_set_replay(server, &rqst); - #ifdef CONFIG_CIFS_SMB_DIRECT - if (wdata->mr) - iov[0].iov_len += sizeof(struct smbd_buffer_descriptor_v1); -@@ -4858,18 +4991,21 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, - int flags = 0; - unsigned int total_len; - struct TCP_Server_Info *server; -+ int retries = 0, cur_sleep = 1; - -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; - *nbytes = 0; -- -- if (n_vec < 1) -- return rc; -- - if (!io_parms->server) - io_parms->server = cifs_pick_channel(io_parms->tcon->ses); - server = io_parms->server; - if (server == NULL) - return -ECONNABORTED; - -+ if (n_vec < 1) -+ return rc; -+ - rc = smb2_plain_req_init(SMB2_WRITE, io_parms->tcon, server, - (void **) &req, &total_len); - if (rc) -@@ -4903,6 +5039,9 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, - rqst.rq_iov = iov; - rqst.rq_nvec = n_vec + 1; - -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, io_parms->tcon->ses, server, - &rqst, - &resp_buftype, flags, &rsp_iov); -@@ -4927,6 +5066,11 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, - - cifs_small_buf_release(req); - free_rsp_buf(resp_buftype, rsp); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(io_parms->tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -5244,8 +5388,14 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, - struct kvec rsp_iov; - int rc = 0; - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - int flags = 0; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ server = cifs_pick_channel(ses); - - if (!ses || !(ses->server)) - return -EIO; -@@ -5265,6 +5415,9 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, - if (rc) - goto qdir_exit; - -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); - rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base; -@@ -5299,6 +5452,11 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, - qdir_exit: - SMB2_query_directory_free(&rqst); - free_rsp_buf(resp_buftype, rsp); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -5365,8 +5523,14 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, - int rc = 0; - int resp_buftype; - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - int flags = 0; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ server = cifs_pick_channel(ses); - - if (!ses || !server) - return -EIO; -@@ -5394,6 +5558,8 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, - return rc; - } - -+ if (retries) -+ smb2_set_replay(server, &rqst); - - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, -@@ -5409,23 +5575,28 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, - - free_rsp_buf(resp_buftype, rsp); - kfree(iov); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - - int - SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, -- u64 volatile_fid, u32 pid, __le64 *eof) -+ u64 volatile_fid, u32 pid, loff_t new_eof) - { - struct smb2_file_eof_info info; - void *data; - unsigned int size; - -- info.EndOfFile = *eof; -+ info.EndOfFile = cpu_to_le64(new_eof); - - data = &info; - size = sizeof(struct smb2_file_eof_info); - -- trace_smb3_set_eof(xid, persistent_fid, tcon->tid, tcon->ses->Suid, le64_to_cpu(*eof)); -+ trace_smb3_set_eof(xid, persistent_fid, tcon->tid, tcon->ses->Suid, new_eof); - - return send_set_info(xid, tcon, persistent_fid, volatile_fid, - pid, FILE_END_OF_FILE_INFORMATION, SMB2_O_INFO_FILE, -@@ -5461,12 +5632,18 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, - int rc; - struct smb2_oplock_break *req = NULL; - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - int flags = CIFS_OBREAK_OP; - unsigned int total_len; - struct kvec iov[1]; - struct kvec rsp_iov; - int resp_buf_type; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = CIFS_OBREAK_OP; -+ server = cifs_pick_channel(ses); - - cifs_dbg(FYI, "SMB2_oplock_break\n"); - rc = smb2_plain_req_init(SMB2_OPLOCK_BREAK, tcon, server, -@@ -5491,15 +5668,21 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, - rqst.rq_iov = iov; - rqst.rq_nvec = 1; - -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buf_type, flags, &rsp_iov); - cifs_small_buf_release(req); -- - if (rc) { - cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE); - cifs_dbg(FYI, "Send error in Oplock Break = %d\n", rc); - } - -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -5585,9 +5768,15 @@ SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon, - int rc = 0; - int resp_buftype; - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - FILE_SYSTEM_POSIX_INFO *info = NULL; - int flags = 0; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ server = cifs_pick_channel(ses); - - rc = build_qfs_info_req(&iov, tcon, server, - FS_POSIX_INFORMATION, -@@ -5603,6 +5792,9 @@ SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon, - rqst.rq_iov = &iov; - rqst.rq_nvec = 1; - -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); - free_qfs_info_req(&iov); -@@ -5622,6 +5814,11 @@ SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon, - - posix_qfsinf_exit: - free_rsp_buf(resp_buftype, rsp_iov.iov_base); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -5636,9 +5833,15 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, - int rc = 0; - int resp_buftype; - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - struct smb2_fs_full_size_info *info = NULL; - int flags = 0; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ server = cifs_pick_channel(ses); - - rc = build_qfs_info_req(&iov, tcon, server, - FS_FULL_SIZE_INFORMATION, -@@ -5654,6 +5857,9 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, - rqst.rq_iov = &iov; - rqst.rq_nvec = 1; - -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); - free_qfs_info_req(&iov); -@@ -5673,6 +5879,11 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, - - qfsinf_exit: - free_rsp_buf(resp_buftype, rsp_iov.iov_base); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -5687,9 +5898,15 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, - int rc = 0; - int resp_buftype, max_len, min_len; - struct cifs_ses *ses = tcon->ses; -- struct TCP_Server_Info *server = cifs_pick_channel(ses); -+ struct TCP_Server_Info *server; - unsigned int rsp_len, offset; - int flags = 0; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = 0; -+ server = cifs_pick_channel(ses); - - if (level == FS_DEVICE_INFORMATION) { - max_len = sizeof(FILE_SYSTEM_DEVICE_INFO); -@@ -5721,6 +5938,9 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, - rqst.rq_iov = &iov; - rqst.rq_nvec = 1; - -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, ses, server, - &rqst, &resp_buftype, flags, &rsp_iov); - free_qfs_info_req(&iov); -@@ -5758,6 +5978,11 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, - - qfsattr_exit: - free_rsp_buf(resp_buftype, rsp_iov.iov_base); -+ -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -@@ -5775,7 +6000,13 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, - unsigned int count; - int flags = CIFS_NO_RSP_BUF; - unsigned int total_len; -- struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses); -+ struct TCP_Server_Info *server; -+ int retries = 0, cur_sleep = 1; -+ -+replay_again: -+ /* reinitialize for possible replay */ -+ flags = CIFS_NO_RSP_BUF; -+ server = cifs_pick_channel(tcon->ses); - - cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock); - -@@ -5806,6 +6037,9 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, - rqst.rq_iov = iov; - rqst.rq_nvec = 2; - -+ if (retries) -+ smb2_set_replay(server, &rqst); -+ - rc = cifs_send_recv(xid, tcon->ses, server, - &rqst, &resp_buf_type, flags, - &rsp_iov); -@@ -5817,6 +6051,10 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, - tcon->ses->Suid, rc); - } - -+ if (is_replayable_error(rc) && -+ smb2_should_replay(tcon, &retries, &cur_sleep)) -+ goto replay_again; -+ - return rc; - } - -diff --git a/fs/smb/client/smb2pdu.h b/fs/smb/client/smb2pdu.h -index b00f707bddfcc..5c458ab3b05a4 100644 ---- a/fs/smb/client/smb2pdu.h -+++ b/fs/smb/client/smb2pdu.h -@@ -117,9 +117,10 @@ struct share_redirect_error_context_rsp { - * [4] : posix context - * [5] : time warp context - * [6] : query id context -- * [7] : compound padding -+ * [7] : create ea context -+ * [8] : compound padding - */ --#define SMB2_CREATE_IOV_SIZE 8 -+#define SMB2_CREATE_IOV_SIZE 9 - - /* - * Maximum size of a SMB2_CREATE response is 64 (smb2 header) + -@@ -144,7 +145,7 @@ struct durable_context_v2 { - } __packed; - - struct create_durable_v2 { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - struct durable_context_v2 dcontext; - } __packed; -@@ -166,7 +167,7 @@ struct durable_reconnect_context_v2_rsp { - } __packed; - - struct create_durable_handle_reconnect_v2 { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - struct durable_reconnect_context_v2 dcontext; - __u8 Pad[4]; -@@ -174,7 +175,7 @@ struct create_durable_handle_reconnect_v2 { - - /* See MS-SMB2 2.2.13.2.5 */ - struct crt_twarp_ctxt { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - __le64 Timestamp; - -@@ -182,12 +183,12 @@ struct crt_twarp_ctxt { - - /* See MS-SMB2 2.2.13.2.9 */ - struct crt_query_id_ctxt { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - } __packed; - - struct crt_sd_ctxt { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - struct smb3_sd sd; - } __packed; -@@ -413,4 +414,35 @@ struct smb2_posix_info_parsed { - const u8 *name; - }; - -+struct smb2_create_ea_ctx { -+ struct create_context_hdr ctx; -+ __u8 name[8]; -+ struct smb2_file_full_ea_info ea; -+} __packed; -+ -+#define SMB2_WSL_XATTR_UID "$LXUID" -+#define SMB2_WSL_XATTR_GID "$LXGID" -+#define SMB2_WSL_XATTR_MODE "$LXMOD" -+#define SMB2_WSL_XATTR_DEV "$LXDEV" -+#define SMB2_WSL_XATTR_NAME_LEN 6 -+#define SMB2_WSL_NUM_XATTRS 4 -+ -+#define SMB2_WSL_XATTR_UID_SIZE 4 -+#define SMB2_WSL_XATTR_GID_SIZE 4 -+#define SMB2_WSL_XATTR_MODE_SIZE 4 -+#define SMB2_WSL_XATTR_DEV_SIZE 8 -+ -+#define SMB2_WSL_MIN_QUERY_EA_RESP_SIZE \ -+ (ALIGN((SMB2_WSL_NUM_XATTRS - 1) * \ -+ (SMB2_WSL_XATTR_NAME_LEN + 1 + \ -+ sizeof(struct smb2_file_full_ea_info)), 4) + \ -+ SMB2_WSL_XATTR_NAME_LEN + 1 + sizeof(struct smb2_file_full_ea_info)) -+ -+#define SMB2_WSL_MAX_QUERY_EA_RESP_SIZE \ -+ (ALIGN(SMB2_WSL_MIN_QUERY_EA_RESP_SIZE + \ -+ SMB2_WSL_XATTR_UID_SIZE + \ -+ SMB2_WSL_XATTR_GID_SIZE + \ -+ SMB2_WSL_XATTR_MODE_SIZE + \ -+ SMB2_WSL_XATTR_DEV_SIZE, 4)) -+ - #endif /* _SMB2PDU_H */ -diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h -index a8084ce7fcbd2..732169d8a67a3 100644 ---- a/fs/smb/client/smb2proto.h -+++ b/fs/smb/client/smb2proto.h -@@ -56,6 +56,19 @@ extern int smb3_handle_read_data(struct TCP_Server_Info *server, - extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, const char *path, - __u32 *reparse_tag); -+struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data, -+ struct super_block *sb, -+ const unsigned int xid, -+ struct cifs_tcon *tcon, -+ const char *full_path, -+ struct kvec *reparse_iov, -+ struct kvec *xattr_iov); -+int smb2_query_reparse_point(const unsigned int xid, -+ struct cifs_tcon *tcon, -+ struct cifs_sb_info *cifs_sb, -+ const char *full_path, -+ u32 *tag, struct kvec *rsp, -+ int *rsp_buftype); - int smb2_query_path_info(const unsigned int xid, - struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, -@@ -63,7 +76,8 @@ int smb2_query_path_info(const unsigned int xid, - struct cifs_open_info_data *data); - extern int smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon, - const char *full_path, __u64 size, -- struct cifs_sb_info *cifs_sb, bool set_alloc); -+ struct cifs_sb_info *cifs_sb, bool set_alloc, -+ struct dentry *dentry); - extern int smb2_set_file_info(struct inode *inode, const char *full_path, - FILE_BASIC_INFO *buf, const unsigned int xid); - extern int smb311_posix_mkdir(const unsigned int xid, struct inode *inode, -@@ -79,7 +93,8 @@ extern void smb2_mkdir_setinfo(struct inode *inode, const char *full_path, - extern int smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, - const char *name, struct cifs_sb_info *cifs_sb); - extern int smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, -- const char *name, struct cifs_sb_info *cifs_sb); -+ const char *name, struct cifs_sb_info *cifs_sb, -+ struct dentry *dentry); - int smb2_rename_path(const unsigned int xid, - struct cifs_tcon *tcon, - struct dentry *source_dentry, -@@ -110,6 +125,11 @@ extern unsigned long smb_rqst_len(struct TCP_Server_Info *server, - extern void smb2_set_next_command(struct cifs_tcon *tcon, - struct smb_rqst *rqst); - extern void smb2_set_related(struct smb_rqst *rqst); -+extern void smb2_set_replay(struct TCP_Server_Info *server, -+ struct smb_rqst *rqst); -+extern bool smb2_should_replay(struct cifs_tcon *tcon, -+ int *pretries, -+ int *pcur_sleep); - - /* - * SMB2 Worker functions - most of protocol specific implementation details -@@ -209,7 +229,7 @@ extern int SMB2_query_directory_init(unsigned int xid, struct cifs_tcon *tcon, - extern void SMB2_query_directory_free(struct smb_rqst *rqst); - extern int SMB2_set_eof(const unsigned int xid, struct cifs_tcon *tcon, - u64 persistent_fid, u64 volatile_fid, u32 pid, -- __le64 *eof); -+ loff_t new_eof); - extern int SMB2_set_info_init(struct cifs_tcon *tcon, - struct TCP_Server_Info *server, - struct smb_rqst *rqst, -@@ -287,10 +307,15 @@ int smb311_posix_query_path_info(const unsigned int xid, - struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, - const char *full_path, -- struct cifs_open_info_data *data, -- struct cifs_sid *owner, -- struct cifs_sid *group); -+ struct cifs_open_info_data *data); - int posix_info_parse(const void *beg, const void *end, - struct smb2_posix_info_parsed *out); - int posix_info_sid_size(const void *beg, const void *end); -+int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, const char *symname); -+int smb2_make_nfs_node(unsigned int xid, struct inode *inode, -+ struct dentry *dentry, struct cifs_tcon *tcon, -+ const char *full_path, umode_t mode, dev_t dev); -+ - #endif /* _SMB2PROTO_H */ -diff --git a/fs/smb/client/smb2status.h b/fs/smb/client/smb2status.h -index a9e958166fc53..9c6d79b0bd497 100644 ---- a/fs/smb/client/smb2status.h -+++ b/fs/smb/client/smb2status.h -@@ -982,6 +982,8 @@ struct ntstatus { - #define STATUS_INVALID_TASK_INDEX cpu_to_le32(0xC0000501) - #define STATUS_THREAD_ALREADY_IN_TASK cpu_to_le32(0xC0000502) - #define STATUS_CALLBACK_BYPASS cpu_to_le32(0xC0000503) -+#define STATUS_SERVER_UNAVAILABLE cpu_to_le32(0xC0000466) -+#define STATUS_FILE_NOT_AVAILABLE cpu_to_le32(0xC0000467) - #define STATUS_PORT_CLOSED cpu_to_le32(0xC0000700) - #define STATUS_MESSAGE_LOST cpu_to_le32(0xC0000701) - #define STATUS_INVALID_MESSAGE cpu_to_le32(0xC0000702) -diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c -index 5a3ca62d2f07f..8f346aafc4cf8 100644 ---- a/fs/smb/client/smb2transport.c -+++ b/fs/smb/client/smb2transport.c -@@ -189,6 +189,8 @@ smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid) - if (tcon->tid != tid) - continue; - ++tcon->tc_count; -+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, -+ netfs_trace_tcon_ref_get_find_sess_tcon); - return tcon; - } - -diff --git a/fs/smb/client/smbdirect.c b/fs/smb/client/smbdirect.c -index 94df9eec3d8d1..d74e829de51c2 100644 ---- a/fs/smb/client/smbdirect.c -+++ b/fs/smb/client/smbdirect.c -@@ -2136,7 +2136,7 @@ static int allocate_mr_list(struct smbd_connection *info) - for (i = 0; i < info->responder_resources * 2; i++) { - smbdirect_mr = kzalloc(sizeof(*smbdirect_mr), GFP_KERNEL); - if (!smbdirect_mr) -- goto out; -+ goto cleanup_entries; - smbdirect_mr->mr = ib_alloc_mr(info->pd, info->mr_type, - info->max_frmr_depth); - if (IS_ERR(smbdirect_mr->mr)) { -@@ -2162,7 +2162,7 @@ static int allocate_mr_list(struct smbd_connection *info) - - out: - kfree(smbdirect_mr); -- -+cleanup_entries: - list_for_each_entry_safe(smbdirect_mr, tmp, &info->mr_list, list) { - list_del(&smbdirect_mr->list); - ib_dereg_mr(smbdirect_mr->mr); -diff --git a/fs/smb/client/smbencrypt.c b/fs/smb/client/smbencrypt.c -index f0ce26414f173..1d1ee9f18f373 100644 ---- a/fs/smb/client/smbencrypt.c -+++ b/fs/smb/client/smbencrypt.c -@@ -26,13 +26,6 @@ - #include "cifsproto.h" - #include "../common/md4.h" - --#ifndef false --#define false 0 --#endif --#ifndef true --#define true 1 --#endif -- - /* following came from the other byteorder.h to avoid include conflicts */ - #define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) - #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) -diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h -index de199ec9f7263..604e52876cd2d 100644 ---- a/fs/smb/client/trace.h -+++ b/fs/smb/client/trace.h -@@ -3,6 +3,9 @@ - * Copyright (C) 2018, Microsoft Corporation. - * - * Author(s): Steve French -+ * -+ * Please use this 3-part article as a reference for writing new tracepoints: -+ * https://lwn.net/Articles/379903/ - */ - #undef TRACE_SYSTEM - #define TRACE_SYSTEM cifs -@@ -15,9 +18,70 @@ - #include - - /* -- * Please use this 3-part article as a reference for writing new tracepoints: -- * https://lwn.net/Articles/379903/ -+ * Specify enums for tracing information. -+ */ -+#define smb3_tcon_ref_traces \ -+ EM(netfs_trace_tcon_ref_dec_dfs_refer, "DEC DfsRef") \ -+ EM(netfs_trace_tcon_ref_free, "FRE ") \ -+ EM(netfs_trace_tcon_ref_free_fail, "FRE Fail ") \ -+ EM(netfs_trace_tcon_ref_free_ipc, "FRE Ipc ") \ -+ EM(netfs_trace_tcon_ref_free_ipc_fail, "FRE Ipc-F ") \ -+ EM(netfs_trace_tcon_ref_free_reconnect_server, "FRE Reconn") \ -+ EM(netfs_trace_tcon_ref_get_cancelled_close, "GET Cn-Cls") \ -+ EM(netfs_trace_tcon_ref_get_dfs_refer, "GET DfsRef") \ -+ EM(netfs_trace_tcon_ref_get_find, "GET Find ") \ -+ EM(netfs_trace_tcon_ref_get_find_sess_tcon, "GET FndSes") \ -+ EM(netfs_trace_tcon_ref_get_reconnect_server, "GET Reconn") \ -+ EM(netfs_trace_tcon_ref_new, "NEW ") \ -+ EM(netfs_trace_tcon_ref_new_ipc, "NEW Ipc ") \ -+ EM(netfs_trace_tcon_ref_new_reconnect_server, "NEW Reconn") \ -+ EM(netfs_trace_tcon_ref_put_cancelled_close, "PUT Cn-Cls") \ -+ EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \ -+ EM(netfs_trace_tcon_ref_put_cancelled_mid, "PUT Cn-Mid") \ -+ EM(netfs_trace_tcon_ref_put_mnt_ctx, "PUT MntCtx") \ -+ EM(netfs_trace_tcon_ref_put_reconnect_server, "PUT Reconn") \ -+ EM(netfs_trace_tcon_ref_put_tlink, "PUT Tlink ") \ -+ EM(netfs_trace_tcon_ref_see_cancelled_close, "SEE Cn-Cls") \ -+ EM(netfs_trace_tcon_ref_see_fscache_collision, "SEE FV-CO!") \ -+ EM(netfs_trace_tcon_ref_see_fscache_okay, "SEE FV-Ok ") \ -+ EM(netfs_trace_tcon_ref_see_fscache_relinq, "SEE FV-Rlq") \ -+ E_(netfs_trace_tcon_ref_see_umount, "SEE Umount") -+ -+#undef EM -+#undef E_ -+ -+/* -+ * Define those tracing enums. -+ */ -+#ifndef __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY -+#define __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY -+ -+#define EM(a, b) a, -+#define E_(a, b) a -+ -+enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte); -+ -+#undef EM -+#undef E_ -+#endif -+ -+/* -+ * Export enum symbols via userspace. -+ */ -+#define EM(a, b) TRACE_DEFINE_ENUM(a); -+#define E_(a, b) TRACE_DEFINE_ENUM(a); -+ -+smb3_tcon_ref_traces; -+ -+#undef EM -+#undef E_ -+ -+/* -+ * Now redefine the EM() and E_() macros to map the enums to the strings that -+ * will be printed in the output. - */ -+#define EM(a, b) { a, b }, -+#define E_(a, b) { a, b } - - /* For logging errors in read or write */ - DECLARE_EVENT_CLASS(smb3_rw_err_class, -@@ -370,10 +434,12 @@ DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rmdir_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_eof_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_info_compound_enter); -+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_reparse_compound_enter); -+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(get_reparse_compound_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(delete_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mkdir_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(tdis_enter); -- -+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mknod_enter); - - DECLARE_EVENT_CLASS(smb3_inf_compound_done_class, - TP_PROTO(unsigned int xid, -@@ -408,10 +474,13 @@ DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rmdir_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_eof_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_info_compound_done); -+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_reparse_compound_done); -+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(get_reparse_compound_done); -+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_wsl_ea_compound_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(delete_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mkdir_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(tdis_done); -- -+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mknod_done); - - DECLARE_EVENT_CLASS(smb3_inf_compound_err_class, - TP_PROTO(unsigned int xid, -@@ -451,9 +520,13 @@ DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rmdir_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_eof_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_info_compound_err); -+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_reparse_compound_err); -+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(get_reparse_compound_err); -+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_wsl_ea_compound_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mkdir_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(delete_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(tdis_err); -+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mknod_err); - - /* - * For logging SMB3 Status code and Command for responses which return errors -@@ -1025,6 +1098,38 @@ DEFINE_EVENT(smb3_ses_class, smb3_##name, \ - - DEFINE_SMB3_SES_EVENT(ses_not_found); - -+DECLARE_EVENT_CLASS(smb3_ioctl_class, -+ TP_PROTO(unsigned int xid, -+ __u64 fid, -+ unsigned int command), -+ TP_ARGS(xid, fid, command), -+ TP_STRUCT__entry( -+ __field(unsigned int, xid) -+ __field(__u64, fid) -+ __field(unsigned int, command) -+ ), -+ TP_fast_assign( -+ __entry->xid = xid; -+ __entry->fid = fid; -+ __entry->command = command; -+ ), -+ TP_printk("xid=%u fid=0x%llx ioctl cmd=0x%x", -+ __entry->xid, __entry->fid, __entry->command) -+) -+ -+#define DEFINE_SMB3_IOCTL_EVENT(name) \ -+DEFINE_EVENT(smb3_ioctl_class, smb3_##name, \ -+ TP_PROTO(unsigned int xid, \ -+ __u64 fid, \ -+ unsigned int command), \ -+ TP_ARGS(xid, fid, command)) -+ -+DEFINE_SMB3_IOCTL_EVENT(ioctl); -+ -+ -+ -+ -+ - DECLARE_EVENT_CLASS(smb3_credit_class, - TP_PROTO(__u64 currmid, - __u64 conn_id, -@@ -1084,6 +1189,30 @@ DEFINE_SMB3_CREDIT_EVENT(waitff_credits); - DEFINE_SMB3_CREDIT_EVENT(overflow_credits); - DEFINE_SMB3_CREDIT_EVENT(set_credits); - -+ -+TRACE_EVENT(smb3_tcon_ref, -+ TP_PROTO(unsigned int tcon_debug_id, int ref, -+ enum smb3_tcon_ref_trace trace), -+ TP_ARGS(tcon_debug_id, ref, trace), -+ TP_STRUCT__entry( -+ __field(unsigned int, tcon) -+ __field(int, ref) -+ __field(enum smb3_tcon_ref_trace, trace) -+ ), -+ TP_fast_assign( -+ __entry->tcon = tcon_debug_id; -+ __entry->ref = ref; -+ __entry->trace = trace; -+ ), -+ TP_printk("TC=%08x %s r=%u", -+ __entry->tcon, -+ __print_symbolic(__entry->trace, smb3_tcon_ref_traces), -+ __entry->ref) -+ ); -+ -+ -+#undef EM -+#undef E_ - #endif /* _CIFS_TRACE_H */ - - #undef TRACE_INCLUDE_PATH -diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h -index 22c94dea52116..8d10be1fe18a8 100644 ---- a/fs/smb/common/smb2pdu.h -+++ b/fs/smb/common/smb2pdu.h -@@ -34,6 +34,7 @@ - #define SMB2_QUERY_INFO_HE 0x0010 - #define SMB2_SET_INFO_HE 0x0011 - #define SMB2_OPLOCK_BREAK_HE 0x0012 -+#define SMB2_SERVER_TO_CLIENT_NOTIFICATION 0x0013 - - /* The same list in little endian */ - #define SMB2_NEGOTIATE cpu_to_le16(SMB2_NEGOTIATE_HE) -@@ -207,38 +208,45 @@ struct smb2_transform_hdr { - __le64 SessionId; - } __packed; - -+/* -+ * These are simplified versions from the spec, as we don't need a fully fledged -+ * form of both unchained and chained structs. -+ * -+ * Moreover, even in chained compressed payloads, the initial compression header -+ * has the form of the unchained one -- i.e. it never has the -+ * OriginalPayloadSize field and ::Offset field always represent an offset -+ * (instead of a length, as it is in the chained header). -+ * -+ * See MS-SMB2 2.2.42 for more details. -+ */ -+#define SMB2_COMPRESSION_FLAG_NONE 0x0000 -+#define SMB2_COMPRESSION_FLAG_CHAINED 0x0001 - --/* See MS-SMB2 2.2.42 */ --struct smb2_compression_transform_hdr_unchained { -- __le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */ -+struct smb2_compression_hdr { -+ __le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */ - __le32 OriginalCompressedSegmentSize; - __le16 CompressionAlgorithm; - __le16 Flags; -- __le16 Length; /* if chained it is length, else offset */ -+ __le32 Offset; /* this is the size of the uncompressed SMB2 header below */ -+ /* uncompressed SMB2 header (READ or WRITE) goes here */ -+ /* compressed data goes here */ - } __packed; - --/* See MS-SMB2 2.2.42.1 */ --#define SMB2_COMPRESSION_FLAG_NONE 0x0000 --#define SMB2_COMPRESSION_FLAG_CHAINED 0x0001 -- --struct compression_payload_header { -+/* -+ * ... OTOH, set compression payload header to always have OriginalPayloadSize -+ * as it's easier to pass the struct size minus sizeof(OriginalPayloadSize) -+ * than to juggle around the header/data memory. -+ */ -+struct smb2_compression_payload_hdr { - __le16 CompressionAlgorithm; - __le16 Flags; - __le32 Length; /* length of compressed playload including field below if present */ -- /* __le32 OriginalPayloadSize; */ /* optional, present when LZNT1, LZ77, LZ77+Huffman */ --} __packed; -- --/* See MS-SMB2 2.2.42.2 */ --struct smb2_compression_transform_hdr_chained { -- __le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */ -- __le32 OriginalCompressedSegmentSize; -- /* struct compression_payload_header[] */ -+ __le32 OriginalPayloadSize; /* accounted when LZNT1, LZ77, LZ77+Huffman */ - } __packed; - --/* See MS-SMB2 2.2.42.2.2 */ --struct compression_pattern_payload_v1 { -- __le16 Pattern; -- __le16 Reserved1; -+struct smb2_compression_pattern_v1 { -+ __u8 Pattern; -+ __u8 Reserved1; - __le16 Reserved2; - __le32 Repetitions; - } __packed; -@@ -272,15 +280,16 @@ struct smb3_blob_data { - #define SE_GROUP_RESOURCE 0x20000000 - #define SE_GROUP_LOGON_ID 0xC0000000 - --/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */ -- - struct sid_array_data { - __le16 SidAttrCount; - /* SidAttrList - array of sid_attr_data structs */ - } __packed; - --struct luid_attr_data { -- -+/* struct sid_attr_data is SidData array in BlobData format then le32 Attr */ -+struct sid_attr_data { -+ __le16 BlobSize; -+ __u8 BlobData[]; -+ /* __le32 Attr */ - } __packed; - - /* -@@ -411,6 +420,7 @@ struct smb2_tree_disconnect_rsp { - #define SMB2_GLOBAL_CAP_PERSISTENT_HANDLES 0x00000010 /* New to SMB3 */ - #define SMB2_GLOBAL_CAP_DIRECTORY_LEASING 0x00000020 /* New to SMB3 */ - #define SMB2_GLOBAL_CAP_ENCRYPTION 0x00000040 /* New to SMB3 */ -+#define SMB2_GLOBAL_CAP_NOTIFICATIONS 0x00000080 /* New to SMB3.1.1 */ - /* Internal types */ - #define SMB2_NT_FIND 0x00100000 - #define SMB2_LARGE_FILES 0x00200000 -@@ -493,6 +503,7 @@ struct smb2_encryption_neg_context { - #define SMB3_COMPRESS_LZ77_HUFF cpu_to_le16(0x0003) - /* Pattern scanning algorithm See MS-SMB2 3.1.4.4.1 */ - #define SMB3_COMPRESS_PATTERN cpu_to_le16(0x0004) /* Pattern_V1 */ -+#define SMB3_COMPRESS_LZ4 cpu_to_le16(0x0005) - - /* Compression Flags */ - #define SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE cpu_to_le32(0x00000000) -@@ -984,6 +995,19 @@ struct smb2_change_notify_rsp { - __u8 Buffer[]; /* array of file notify structs */ - } __packed; - -+/* -+ * SMB2_SERVER_TO_CLIENT_NOTIFICATION: See MS-SMB2 section 2.2.44 -+ */ -+ -+#define SMB2_NOTIFY_SESSION_CLOSED 0x0000 -+ -+struct smb2_server_client_notification { -+ struct smb2_hdr hdr; -+ __le16 StructureSize; -+ __u16 Reserved; /* MBZ */ -+ __le32 NotificationType; -+ __u8 NotificationBuffer[4]; /* MBZ */ -+} __packed; - - /* - * SMB2_CREATE See MS-SMB2 section 2.2.13 -@@ -1100,16 +1124,23 @@ struct smb2_change_notify_rsp { - #define FILE_WRITE_THROUGH_LE cpu_to_le32(0x00000002) - #define FILE_SEQUENTIAL_ONLY_LE cpu_to_le32(0x00000004) - #define FILE_NO_INTERMEDIATE_BUFFERING_LE cpu_to_le32(0x00000008) -+/* FILE_SYNCHRONOUS_IO_ALERT_LE cpu_to_le32(0x00000010) should be zero, ignored */ -+/* FILE_SYNCHRONOUS_IO_NONALERT cpu_to_le32(0x00000020) should be zero, ignored */ - #define FILE_NON_DIRECTORY_FILE_LE cpu_to_le32(0x00000040) - #define FILE_COMPLETE_IF_OPLOCKED_LE cpu_to_le32(0x00000100) - #define FILE_NO_EA_KNOWLEDGE_LE cpu_to_le32(0x00000200) -+/* FILE_OPEN_REMOTE_INSTANCE cpu_to_le32(0x00000400) should be zero, ignored */ - #define FILE_RANDOM_ACCESS_LE cpu_to_le32(0x00000800) --#define FILE_DELETE_ON_CLOSE_LE cpu_to_le32(0x00001000) -+#define FILE_DELETE_ON_CLOSE_LE cpu_to_le32(0x00001000) /* MBZ */ - #define FILE_OPEN_BY_FILE_ID_LE cpu_to_le32(0x00002000) - #define FILE_OPEN_FOR_BACKUP_INTENT_LE cpu_to_le32(0x00004000) - #define FILE_NO_COMPRESSION_LE cpu_to_le32(0x00008000) -+/* FILE_OPEN_REQUIRING_OPLOCK cpu_to_le32(0x00010000) should be zero, ignored */ -+/* FILE_DISALLOW_EXCLUSIVE cpu_to_le32(0x00020000) should be zero, ignored */ -+/* FILE_RESERVE_OPFILTER cpu_to_le32(0x00100000) MBZ */ - #define FILE_OPEN_REPARSE_POINT_LE cpu_to_le32(0x00200000) - #define FILE_OPEN_NO_RECALL_LE cpu_to_le32(0x00400000) -+/* #define FILE_OPEN_FOR_FREE_SPACE_QUERY cpu_to_le32(0x00800000) should be zero, ignored */ - #define CREATE_OPTIONS_MASK_LE cpu_to_le32(0x00FFFFFF) - - #define FILE_READ_RIGHTS_LE (FILE_READ_DATA_LE | FILE_READ_EA_LE \ -@@ -1140,12 +1171,15 @@ struct smb2_change_notify_rsp { - #define SMB2_CREATE_FLAG_REPARSEPOINT 0x01 - - struct create_context { -- __le32 Next; -- __le16 NameOffset; -- __le16 NameLength; -- __le16 Reserved; -- __le16 DataOffset; -- __le32 DataLength; -+ /* New members must be added within the struct_group() macro below. */ -+ __struct_group(create_context_hdr, hdr, __packed, -+ __le32 Next; -+ __le16 NameOffset; -+ __le16 NameLength; -+ __le16 Reserved; -+ __le16 DataOffset; -+ __le32 DataLength; -+ ); - __u8 Buffer[]; - } __packed; - -@@ -1191,7 +1225,7 @@ struct smb2_create_rsp { - } __packed; - - struct create_posix { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[16]; - __le32 Mode; - __u32 Reserved; -@@ -1199,7 +1233,7 @@ struct create_posix { - - /* See MS-SMB2 2.2.13.2.3 and MS-SMB2 2.2.13.2.4 */ - struct create_durable { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - union { - __u8 Reserved[16]; -@@ -1212,14 +1246,14 @@ struct create_durable { - - /* See MS-SMB2 2.2.13.2.5 */ - struct create_mxac_req { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - __le64 Timestamp; - } __packed; - - /* See MS-SMB2 2.2.14.2.5 */ - struct create_mxac_rsp { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - __le32 QueryStatus; - __le32 MaximalAccess; -@@ -1255,13 +1289,13 @@ struct lease_context_v2 { - } __packed; - - struct create_lease { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - struct lease_context lcontext; - } __packed; - - struct create_lease_v2 { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - struct lease_context_v2 lcontext; - __u8 Pad[4]; -@@ -1269,7 +1303,7 @@ struct create_lease_v2 { - - /* See MS-SMB2 2.2.14.2.9 */ - struct create_disk_id_rsp { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - __le64 DiskFileId; - __le64 VolumeId; -@@ -1278,7 +1312,7 @@ struct create_disk_id_rsp { - - /* See MS-SMB2 2.2.13.2.13 */ - struct create_app_inst_id { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[16]; - __le32 StructureSize; /* Must be 20 */ - __u16 Reserved; -@@ -1287,7 +1321,7 @@ struct create_app_inst_id { - - /* See MS-SMB2 2.2.13.2.15 */ - struct create_app_inst_id_vers { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[16]; - __le32 StructureSize; /* Must be 24 */ - __u16 Reserved; -diff --git a/fs/smb/common/smbfsctl.h b/fs/smb/common/smbfsctl.h -index edd7fc2a7921b..a94d658b88e86 100644 ---- a/fs/smb/common/smbfsctl.h -+++ b/fs/smb/common/smbfsctl.h -@@ -158,12 +158,6 @@ - #define IO_REPARSE_TAG_LX_CHR 0x80000025 - #define IO_REPARSE_TAG_LX_BLK 0x80000026 - --#define IO_REPARSE_TAG_LX_SYMLINK_LE cpu_to_le32(0xA000001D) --#define IO_REPARSE_TAG_AF_UNIX_LE cpu_to_le32(0x80000023) --#define IO_REPARSE_TAG_LX_FIFO_LE cpu_to_le32(0x80000024) --#define IO_REPARSE_TAG_LX_CHR_LE cpu_to_le32(0x80000025) --#define IO_REPARSE_TAG_LX_BLK_LE cpu_to_le32(0x80000026) -- - /* fsctl flags */ - /* If Flags is set to this value, the request is an FSCTL not ioctl request */ - #define SMB2_0_IOCTL_IS_FSCTL 0x00000001 -diff --git a/fs/smb/server/auth.c b/fs/smb/server/auth.c -index 229a6527870d0..09b20039636e7 100644 ---- a/fs/smb/server/auth.c -+++ b/fs/smb/server/auth.c -@@ -208,10 +208,12 @@ static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess, - - /** - * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler -- * @sess: session of connection -+ * @conn: connection -+ * @sess: session of connection - * @ntlmv2: NTLMv2 challenge response - * @blen: NTLMv2 blob length - * @domain_name: domain name -+ * @cryptkey: session crypto key - * - * Return: 0 on success, error number on error - */ -@@ -294,7 +296,8 @@ int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess, - * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct - * authenticate blob - * @authblob: authenticate blob source pointer -- * @usr: user details -+ * @blob_len: length of the @authblob message -+ * @conn: connection - * @sess: session of connection - * - * Return: 0 on success, error number on error -@@ -376,8 +379,8 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, - * ksmbd_decode_ntlmssp_neg_blob() - helper function to construct - * negotiate blob - * @negblob: negotiate blob source pointer -- * @rsp: response header pointer to be updated -- * @sess: session of connection -+ * @blob_len: length of the @authblob message -+ * @conn: connection - * - */ - int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob, -@@ -403,8 +406,7 @@ int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob, - * ksmbd_build_ntlmssp_challenge_blob() - helper function to construct - * challenge blob - * @chgblob: challenge blob source pointer to initialize -- * @rsp: response header pointer to be updated -- * @sess: session of connection -+ * @conn: connection - * - */ - unsigned int -diff --git a/fs/smb/server/ksmbd_netlink.h b/fs/smb/server/ksmbd_netlink.h -index 4464a62228cf3..f4e55199938d5 100644 ---- a/fs/smb/server/ksmbd_netlink.h -+++ b/fs/smb/server/ksmbd_netlink.h -@@ -75,6 +75,7 @@ struct ksmbd_heartbeat { - #define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION BIT(1) - #define KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL BIT(2) - #define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF BIT(3) -+#define KSMBD_GLOBAL_FLAG_DURABLE_HANDLE BIT(4) - - /* - * IPC request for ksmbd server startup -@@ -339,23 +340,24 @@ enum KSMBD_TREE_CONN_STATUS { - /* - * Share config flags. - */ --#define KSMBD_SHARE_FLAG_INVALID (0) --#define KSMBD_SHARE_FLAG_AVAILABLE BIT(0) --#define KSMBD_SHARE_FLAG_BROWSEABLE BIT(1) --#define KSMBD_SHARE_FLAG_WRITEABLE BIT(2) --#define KSMBD_SHARE_FLAG_READONLY BIT(3) --#define KSMBD_SHARE_FLAG_GUEST_OK BIT(4) --#define KSMBD_SHARE_FLAG_GUEST_ONLY BIT(5) --#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS BIT(6) --#define KSMBD_SHARE_FLAG_OPLOCKS BIT(7) --#define KSMBD_SHARE_FLAG_PIPE BIT(8) --#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES BIT(9) --#define KSMBD_SHARE_FLAG_INHERIT_OWNER BIT(10) --#define KSMBD_SHARE_FLAG_STREAMS BIT(11) --#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12) --#define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13) --#define KSMBD_SHARE_FLAG_UPDATE BIT(14) --#define KSMBD_SHARE_FLAG_CROSSMNT BIT(15) -+#define KSMBD_SHARE_FLAG_INVALID (0) -+#define KSMBD_SHARE_FLAG_AVAILABLE BIT(0) -+#define KSMBD_SHARE_FLAG_BROWSEABLE BIT(1) -+#define KSMBD_SHARE_FLAG_WRITEABLE BIT(2) -+#define KSMBD_SHARE_FLAG_READONLY BIT(3) -+#define KSMBD_SHARE_FLAG_GUEST_OK BIT(4) -+#define KSMBD_SHARE_FLAG_GUEST_ONLY BIT(5) -+#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS BIT(6) -+#define KSMBD_SHARE_FLAG_OPLOCKS BIT(7) -+#define KSMBD_SHARE_FLAG_PIPE BIT(8) -+#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES BIT(9) -+#define KSMBD_SHARE_FLAG_INHERIT_OWNER BIT(10) -+#define KSMBD_SHARE_FLAG_STREAMS BIT(11) -+#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12) -+#define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13) -+#define KSMBD_SHARE_FLAG_UPDATE BIT(14) -+#define KSMBD_SHARE_FLAG_CROSSMNT BIT(15) -+#define KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY BIT(16) - - /* - * Tree connect request flags. -diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c -index 15f68ee050894..aec0a7a124052 100644 ---- a/fs/smb/server/mgmt/user_session.c -+++ b/fs/smb/server/mgmt/user_session.c -@@ -156,7 +156,7 @@ void ksmbd_session_destroy(struct ksmbd_session *sess) - kfree(sess); - } - --static struct ksmbd_session *__session_lookup(unsigned long long id) -+struct ksmbd_session *__session_lookup(unsigned long long id) - { - struct ksmbd_session *sess; - -@@ -305,6 +305,32 @@ struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn, - return sess; - } - -+void destroy_previous_session(struct ksmbd_conn *conn, -+ struct ksmbd_user *user, u64 id) -+{ -+ struct ksmbd_session *prev_sess; -+ struct ksmbd_user *prev_user; -+ -+ down_write(&sessions_table_lock); -+ down_write(&conn->session_lock); -+ prev_sess = __session_lookup(id); -+ if (!prev_sess || prev_sess->state == SMB2_SESSION_EXPIRED) -+ goto out; -+ -+ prev_user = prev_sess->user; -+ if (!prev_user || -+ strcmp(user->name, prev_user->name) || -+ user->passkey_sz != prev_user->passkey_sz || -+ memcmp(user->passkey, prev_user->passkey, user->passkey_sz)) -+ goto out; -+ -+ ksmbd_destroy_file_table(&prev_sess->file_table); -+ prev_sess->state = SMB2_SESSION_EXPIRED; -+out: -+ up_write(&conn->session_lock); -+ up_write(&sessions_table_lock); -+} -+ - static bool ksmbd_preauth_session_id_match(struct preauth_session *sess, - unsigned long long id) - { -diff --git a/fs/smb/server/mgmt/user_session.h b/fs/smb/server/mgmt/user_session.h -index 63cb08fffde84..dc9fded2cd437 100644 ---- a/fs/smb/server/mgmt/user_session.h -+++ b/fs/smb/server/mgmt/user_session.h -@@ -88,8 +88,11 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, - int ksmbd_session_register(struct ksmbd_conn *conn, - struct ksmbd_session *sess); - void ksmbd_sessions_deregister(struct ksmbd_conn *conn); -+struct ksmbd_session *__session_lookup(unsigned long long id); - struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn, - unsigned long long id); -+void destroy_previous_session(struct ksmbd_conn *conn, -+ struct ksmbd_user *user, u64 id); - struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn, - u64 sess_id); - struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn, -diff --git a/fs/smb/server/misc.c b/fs/smb/server/misc.c -index 9e8afaa686e3a..1a5faa6f6e7bc 100644 ---- a/fs/smb/server/misc.c -+++ b/fs/smb/server/misc.c -@@ -261,6 +261,7 @@ char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name) - - /** - * ksmbd_extract_sharename() - get share name from tree connect request -+ * @um: pointer to a unicode_map structure for character encoding handling - * @treename: buffer containing tree name and share name - * - * Return: share name on success, otherwise error -diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c -index dc729ab980dc0..b7adb6549aa0f 100644 ---- a/fs/smb/server/oplock.c -+++ b/fs/smb/server/oplock.c -@@ -159,7 +159,8 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci) - opinfo = list_first_or_null_rcu(&ci->m_op_list, struct oplock_info, - op_entry); - if (opinfo) { -- if (!atomic_inc_not_zero(&opinfo->refcount)) -+ if (opinfo->conn == NULL || -+ !atomic_inc_not_zero(&opinfo->refcount)) - opinfo = NULL; - else { - atomic_inc(&opinfo->conn->r_count); -@@ -527,7 +528,7 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci, - */ - read_lock(&ci->m_lock); - list_for_each_entry(opinfo, &ci->m_op_list, op_entry) { -- if (!opinfo->is_lease) -+ if (!opinfo->is_lease || !opinfo->conn) - continue; - read_unlock(&ci->m_lock); - lease = opinfo->o_lease; -@@ -651,7 +652,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) - struct smb2_hdr *rsp_hdr; - struct ksmbd_file *fp; - -- fp = ksmbd_lookup_durable_fd(br_info->fid); -+ fp = ksmbd_lookup_global_fd(br_info->fid); - if (!fp) - goto out; - -@@ -1115,7 +1116,7 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, - - read_lock(&p_ci->m_lock); - list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) { -- if (!opinfo->is_lease) -+ if (opinfo->conn == NULL || !opinfo->is_lease) - continue; - - if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE && -@@ -1151,7 +1152,7 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp) - opinfo = rcu_dereference(fp->f_opinfo); - rcu_read_unlock(); - -- if (!opinfo->is_lease || opinfo->o_lease->version != 2) -+ if (!opinfo || !opinfo->is_lease || opinfo->o_lease->version != 2) - return; - - p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent); -@@ -1160,7 +1161,7 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp) - - read_lock(&p_ci->m_lock); - list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) { -- if (!opinfo->is_lease) -+ if (opinfo->conn == NULL || !opinfo->is_lease) - continue; - - if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE) { -@@ -1372,6 +1373,9 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp, - - rcu_read_lock(); - list_for_each_entry_rcu(brk_op, &ci->m_op_list, op_entry) { -+ if (brk_op->conn == NULL) -+ continue; -+ - if (!atomic_inc_not_zero(&brk_op->refcount)) - continue; - -@@ -1508,11 +1512,10 @@ void create_lease_buf(u8 *rbuf, struct lease *lease) - /** - * parse_lease_state() - parse lease context containted in file open request - * @open_req: buffer containing smb2 file open(create) request -- * @is_dir: whether leasing file is directory - * - * Return: oplock state, -ENOENT if create lease context not found - */ --struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir) -+struct lease_ctx_info *parse_lease_state(void *open_req) - { - struct create_context *cc; - struct smb2_create_req *req = (struct smb2_create_req *)open_req; -@@ -1530,12 +1533,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir) - struct create_lease_v2 *lc = (struct create_lease_v2 *)cc; - - memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); -- if (is_dir) { -- lreq->req_state = lc->lcontext.LeaseState & -- ~SMB2_LEASE_WRITE_CACHING_LE; -- lreq->is_dir = true; -- } else -- lreq->req_state = lc->lcontext.LeaseState; -+ lreq->req_state = lc->lcontext.LeaseState; - lreq->flags = lc->lcontext.LeaseFlags; - lreq->epoch = lc->lcontext.Epoch; - lreq->duration = lc->lcontext.LeaseDuration; -@@ -1659,6 +1657,8 @@ void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp) - buf->Name[3] = 'Q'; - - buf->Timeout = cpu_to_le32(fp->durable_timeout); -+ if (fp->is_persistent) -+ buf->Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT); - } - - /** -@@ -1826,3 +1826,71 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn, - read_unlock(&lease_list_lock); - return ret_op; - } -+ -+int smb2_check_durable_oplock(struct ksmbd_conn *conn, -+ struct ksmbd_share_config *share, -+ struct ksmbd_file *fp, -+ struct lease_ctx_info *lctx, -+ char *name) -+{ -+ struct oplock_info *opinfo = opinfo_get(fp); -+ int ret = 0; -+ -+ if (!opinfo) -+ return 0; -+ -+ if (opinfo->is_lease == false) { -+ if (lctx) { -+ pr_err("create context include lease\n"); -+ ret = -EBADF; -+ goto out; -+ } -+ -+ if (opinfo->level != SMB2_OPLOCK_LEVEL_BATCH) { -+ pr_err("oplock level is not equal to SMB2_OPLOCK_LEVEL_BATCH\n"); -+ ret = -EBADF; -+ } -+ -+ goto out; -+ } -+ -+ if (memcmp(conn->ClientGUID, fp->client_guid, -+ SMB2_CLIENT_GUID_SIZE)) { -+ ksmbd_debug(SMB, "Client guid of fp is not equal to the one of connection\n"); -+ ret = -EBADF; -+ goto out; -+ } -+ -+ if (!lctx) { -+ ksmbd_debug(SMB, "create context does not include lease\n"); -+ ret = -EBADF; -+ goto out; -+ } -+ -+ if (memcmp(opinfo->o_lease->lease_key, lctx->lease_key, -+ SMB2_LEASE_KEY_SIZE)) { -+ ksmbd_debug(SMB, -+ "lease key of fp does not match lease key in create context\n"); -+ ret = -EBADF; -+ goto out; -+ } -+ -+ if (!(opinfo->o_lease->state & SMB2_LEASE_HANDLE_CACHING_LE)) { -+ ksmbd_debug(SMB, "lease state does not contain SMB2_LEASE_HANDLE_CACHING\n"); -+ ret = -EBADF; -+ goto out; -+ } -+ -+ if (opinfo->o_lease->version != lctx->version) { -+ ksmbd_debug(SMB, -+ "lease version of fp does not match the one in create context\n"); -+ ret = -EBADF; -+ goto out; -+ } -+ -+ if (!ksmbd_inode_pending_delete(fp)) -+ ret = ksmbd_validate_name_reconnect(share, fp, name); -+out: -+ opinfo_put(opinfo); -+ return ret; -+} -diff --git a/fs/smb/server/oplock.h b/fs/smb/server/oplock.h -index 5b93ea9196c01..e9da63f25b206 100644 ---- a/fs/smb/server/oplock.h -+++ b/fs/smb/server/oplock.h -@@ -111,7 +111,7 @@ void opinfo_put(struct oplock_info *opinfo); - - /* Lease related functions */ - void create_lease_buf(u8 *rbuf, struct lease *lease); --struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir); -+struct lease_ctx_info *parse_lease_state(void *open_req); - __u8 smb2_map_lease_to_oplock(__le32 lease_state); - int lease_read_to_write(struct oplock_info *opinfo); - -@@ -130,4 +130,9 @@ void destroy_lease_table(struct ksmbd_conn *conn); - void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, - struct lease_ctx_info *lctx); - void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp); -+int smb2_check_durable_oplock(struct ksmbd_conn *conn, -+ struct ksmbd_share_config *share, -+ struct ksmbd_file *fp, -+ struct lease_ctx_info *lctx, -+ char *name); - #endif /* __KSMBD_OPLOCK_H */ -diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c -index 03dded29a9804..727cb49926ee5 100644 ---- a/fs/smb/server/smb2misc.c -+++ b/fs/smb/server/smb2misc.c -@@ -101,13 +101,17 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len, - *len = le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBufferLength); - break; - case SMB2_TREE_CONNECT: -- *off = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset); -+ *off = max_t(unsigned short int, -+ le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset), -+ offsetof(struct smb2_tree_connect_req, Buffer)); - *len = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathLength); - break; - case SMB2_CREATE: - { - unsigned short int name_off = -- le16_to_cpu(((struct smb2_create_req *)hdr)->NameOffset); -+ max_t(unsigned short int, -+ le16_to_cpu(((struct smb2_create_req *)hdr)->NameOffset), -+ offsetof(struct smb2_create_req, Buffer)); - unsigned short int name_len = - le16_to_cpu(((struct smb2_create_req *)hdr)->NameLength); - -@@ -128,11 +132,15 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len, - break; - } - case SMB2_QUERY_INFO: -- *off = le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset); -+ *off = max_t(unsigned int, -+ le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset), -+ offsetof(struct smb2_query_info_req, Buffer)); - *len = le32_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferLength); - break; - case SMB2_SET_INFO: -- *off = le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset); -+ *off = max_t(unsigned int, -+ le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset), -+ offsetof(struct smb2_set_info_req, Buffer)); - *len = le32_to_cpu(((struct smb2_set_info_req *)hdr)->BufferLength); - break; - case SMB2_READ: -@@ -142,7 +150,7 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len, - case SMB2_WRITE: - if (((struct smb2_write_req *)hdr)->DataOffset || - ((struct smb2_write_req *)hdr)->Length) { -- *off = max_t(unsigned int, -+ *off = max_t(unsigned short int, - le16_to_cpu(((struct smb2_write_req *)hdr)->DataOffset), - offsetof(struct smb2_write_req, Buffer)); - *len = le32_to_cpu(((struct smb2_write_req *)hdr)->Length); -@@ -153,7 +161,9 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len, - *len = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoLength); - break; - case SMB2_QUERY_DIRECTORY: -- *off = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset); -+ *off = max_t(unsigned short int, -+ le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset), -+ offsetof(struct smb2_query_directory_req, Buffer)); - *len = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameLength); - break; - case SMB2_LOCK: -@@ -168,7 +178,9 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len, - break; - } - case SMB2_IOCTL: -- *off = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset); -+ *off = max_t(unsigned int, -+ le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset), -+ offsetof(struct smb2_ioctl_req, Buffer)); - *len = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputCount); - break; - default: -diff --git a/fs/smb/server/smb2ops.c b/fs/smb/server/smb2ops.c -index 8600f32c981a1..606aa3c5189a2 100644 ---- a/fs/smb/server/smb2ops.c -+++ b/fs/smb/server/smb2ops.c -@@ -261,6 +261,9 @@ void init_smb3_02_server(struct ksmbd_conn *conn) - - if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) - conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL; -+ -+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE) -+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES; - } - - /** -@@ -283,6 +286,9 @@ int init_smb3_11_server(struct ksmbd_conn *conn) - if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) - conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL; - -+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE) -+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES; -+ - INIT_LIST_HEAD(&conn->preauth_sess_table); - return 0; - } -diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c -index fb9eea631069e..1e536ae277618 100644 ---- a/fs/smb/server/smb2pdu.c -+++ b/fs/smb/server/smb2pdu.c -@@ -611,30 +611,6 @@ int smb2_check_user_session(struct ksmbd_work *work) - return -ENOENT; - } - --static void destroy_previous_session(struct ksmbd_conn *conn, -- struct ksmbd_user *user, u64 id) --{ -- struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id); -- struct ksmbd_user *prev_user; -- struct channel *chann; -- long index; -- -- if (!prev_sess) -- return; -- -- prev_user = prev_sess->user; -- -- if (!prev_user || -- strcmp(user->name, prev_user->name) || -- user->passkey_sz != prev_user->passkey_sz || -- memcmp(user->passkey, prev_user->passkey, user->passkey_sz)) -- return; -- -- prev_sess->state = SMB2_SESSION_EXPIRED; -- xa_for_each(&prev_sess->ksmbd_chann_list, index, chann) -- ksmbd_conn_set_exiting(chann->conn); --} -- - /** - * smb2_get_name() - get filename string from on the wire smb format - * @src: source buffer -@@ -1955,7 +1931,7 @@ int smb2_tree_connect(struct ksmbd_work *work) - - WORK_BUFFERS(work, req, rsp); - -- treename = smb_strndup_from_utf16(req->Buffer, -+ treename = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->PathOffset), - le16_to_cpu(req->PathLength), true, - conn->local_nls); - if (IS_ERR(treename)) { -@@ -2012,7 +1988,12 @@ int smb2_tree_connect(struct ksmbd_work *work) - write_unlock(&sess->tree_conns_lock); - rsp->StructureSize = cpu_to_le16(16); - out_err1: -- rsp->Capabilities = 0; -+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE && -+ test_share_config_flag(share, -+ KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY)) -+ rsp->Capabilities = SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY; -+ else -+ rsp->Capabilities = 0; - rsp->Reserved = 0; - /* default manual caching */ - rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING; -@@ -2646,6 +2627,165 @@ static void ksmbd_acls_fattr(struct smb_fattr *fattr, - } - } - -+enum { -+ DURABLE_RECONN_V2 = 1, -+ DURABLE_RECONN, -+ DURABLE_REQ_V2, -+ DURABLE_REQ, -+}; -+ -+struct durable_info { -+ struct ksmbd_file *fp; -+ unsigned short int type; -+ bool persistent; -+ bool reconnected; -+ unsigned int timeout; -+ char *CreateGuid; -+}; -+ -+static int parse_durable_handle_context(struct ksmbd_work *work, -+ struct smb2_create_req *req, -+ struct lease_ctx_info *lc, -+ struct durable_info *dh_info) -+{ -+ struct ksmbd_conn *conn = work->conn; -+ struct create_context *context; -+ int dh_idx, err = 0; -+ u64 persistent_id = 0; -+ int req_op_level; -+ static const char * const durable_arr[] = {"DH2C", "DHnC", "DH2Q", "DHnQ"}; -+ -+ req_op_level = req->RequestedOplockLevel; -+ for (dh_idx = DURABLE_RECONN_V2; dh_idx <= ARRAY_SIZE(durable_arr); -+ dh_idx++) { -+ context = smb2_find_context_vals(req, durable_arr[dh_idx - 1], 4); -+ if (IS_ERR(context)) { -+ err = PTR_ERR(context); -+ goto out; -+ } -+ if (!context) -+ continue; -+ -+ switch (dh_idx) { -+ case DURABLE_RECONN_V2: -+ { -+ struct create_durable_reconn_v2_req *recon_v2; -+ -+ if (dh_info->type == DURABLE_RECONN || -+ dh_info->type == DURABLE_REQ_V2) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ recon_v2 = (struct create_durable_reconn_v2_req *)context; -+ persistent_id = recon_v2->Fid.PersistentFileId; -+ dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); -+ if (!dh_info->fp) { -+ ksmbd_debug(SMB, "Failed to get durable handle state\n"); -+ err = -EBADF; -+ goto out; -+ } -+ -+ if (memcmp(dh_info->fp->create_guid, recon_v2->CreateGuid, -+ SMB2_CREATE_GUID_SIZE)) { -+ err = -EBADF; -+ ksmbd_put_durable_fd(dh_info->fp); -+ goto out; -+ } -+ -+ dh_info->type = dh_idx; -+ dh_info->reconnected = true; -+ ksmbd_debug(SMB, -+ "reconnect v2 Persistent-id from reconnect = %llu\n", -+ persistent_id); -+ break; -+ } -+ case DURABLE_RECONN: -+ { -+ struct create_durable_reconn_req *recon; -+ -+ if (dh_info->type == DURABLE_RECONN_V2 || -+ dh_info->type == DURABLE_REQ_V2) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ recon = (struct create_durable_reconn_req *)context; -+ persistent_id = recon->Data.Fid.PersistentFileId; -+ dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); -+ if (!dh_info->fp) { -+ ksmbd_debug(SMB, "Failed to get durable handle state\n"); -+ err = -EBADF; -+ goto out; -+ } -+ -+ dh_info->type = dh_idx; -+ dh_info->reconnected = true; -+ ksmbd_debug(SMB, "reconnect Persistent-id from reconnect = %llu\n", -+ persistent_id); -+ break; -+ } -+ case DURABLE_REQ_V2: -+ { -+ struct create_durable_req_v2 *durable_v2_blob; -+ -+ if (dh_info->type == DURABLE_RECONN || -+ dh_info->type == DURABLE_RECONN_V2) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ durable_v2_blob = -+ (struct create_durable_req_v2 *)context; -+ ksmbd_debug(SMB, "Request for durable v2 open\n"); -+ dh_info->fp = ksmbd_lookup_fd_cguid(durable_v2_blob->CreateGuid); -+ if (dh_info->fp) { -+ if (!memcmp(conn->ClientGUID, dh_info->fp->client_guid, -+ SMB2_CLIENT_GUID_SIZE)) { -+ if (!(req->hdr.Flags & SMB2_FLAGS_REPLAY_OPERATION)) { -+ err = -ENOEXEC; -+ goto out; -+ } -+ -+ dh_info->fp->conn = conn; -+ dh_info->reconnected = true; -+ goto out; -+ } -+ } -+ -+ if (((lc && (lc->req_state & SMB2_LEASE_HANDLE_CACHING_LE)) || -+ req_op_level == SMB2_OPLOCK_LEVEL_BATCH)) { -+ dh_info->CreateGuid = -+ durable_v2_blob->CreateGuid; -+ dh_info->persistent = -+ le32_to_cpu(durable_v2_blob->Flags); -+ dh_info->timeout = -+ le32_to_cpu(durable_v2_blob->Timeout); -+ dh_info->type = dh_idx; -+ } -+ break; -+ } -+ case DURABLE_REQ: -+ if (dh_info->type == DURABLE_RECONN) -+ goto out; -+ if (dh_info->type == DURABLE_RECONN_V2 || -+ dh_info->type == DURABLE_REQ_V2) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ if (((lc && (lc->req_state & SMB2_LEASE_HANDLE_CACHING_LE)) || -+ req_op_level == SMB2_OPLOCK_LEVEL_BATCH)) { -+ ksmbd_debug(SMB, "Request for durable open\n"); -+ dh_info->type = dh_idx; -+ } -+ } -+ } -+ -+out: -+ return err; -+} -+ - /** - * smb2_open() - handler for smb file open request - * @work: smb work containing request buffer -@@ -2669,6 +2809,7 @@ int smb2_open(struct ksmbd_work *work) - struct lease_ctx_info *lc = NULL; - struct create_ea_buf_req *ea_buf = NULL; - struct oplock_info *opinfo; -+ struct durable_info dh_info = {0}; - __le32 *next_ptr = NULL; - int req_op_level = 0, open_flags = 0, may_flags = 0, file_info = 0; - int rc = 0; -@@ -2708,7 +2849,7 @@ int smb2_open(struct ksmbd_work *work) - goto err_out2; - } - -- name = smb2_get_name(req->Buffer, -+ name = smb2_get_name((char *)req + le16_to_cpu(req->NameOffset), - le16_to_cpu(req->NameLength), - work->conn->local_nls); - if (IS_ERR(name)) { -@@ -2749,6 +2890,49 @@ int smb2_open(struct ksmbd_work *work) - } - } - -+ req_op_level = req->RequestedOplockLevel; -+ -+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE && -+ req->CreateContextsOffset) { -+ lc = parse_lease_state(req); -+ rc = parse_durable_handle_context(work, req, lc, &dh_info); -+ if (rc) { -+ ksmbd_debug(SMB, "error parsing durable handle context\n"); -+ goto err_out2; -+ } -+ -+ if (dh_info.reconnected == true) { -+ rc = smb2_check_durable_oplock(conn, share, dh_info.fp, lc, name); -+ if (rc) { -+ ksmbd_put_durable_fd(dh_info.fp); -+ goto err_out2; -+ } -+ -+ rc = ksmbd_reopen_durable_fd(work, dh_info.fp); -+ if (rc) { -+ ksmbd_put_durable_fd(dh_info.fp); -+ goto err_out2; -+ } -+ -+ if (ksmbd_override_fsids(work)) { -+ rc = -ENOMEM; -+ ksmbd_put_durable_fd(dh_info.fp); -+ goto err_out2; -+ } -+ -+ fp = dh_info.fp; -+ file_info = FILE_OPENED; -+ -+ rc = ksmbd_vfs_getattr(&fp->filp->f_path, &stat); -+ if (rc) -+ goto err_out2; -+ -+ ksmbd_put_durable_fd(fp); -+ goto reconnected_fp; -+ } -+ } else if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) -+ lc = parse_lease_state(req); -+ - if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE)) { - pr_err("Invalid impersonationlevel : 0x%x\n", - le32_to_cpu(req->ImpersonationLevel)); -@@ -3211,10 +3395,6 @@ int smb2_open(struct ksmbd_work *work) - need_truncate = 1; - } - -- req_op_level = req->RequestedOplockLevel; -- if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) -- lc = parse_lease_state(req, S_ISDIR(file_inode(filp)->i_mode)); -- - share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp); - if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) || - (req_op_level == SMB2_OPLOCK_LEVEL_LEASE && -@@ -3225,6 +3405,11 @@ int smb2_open(struct ksmbd_work *work) - } - } else { - if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) { -+ if (S_ISDIR(file_inode(filp)->i_mode)) { -+ lc->req_state &= ~SMB2_LEASE_WRITE_CACHING_LE; -+ lc->is_dir = true; -+ } -+ - /* - * Compare parent lease using parent key. If there is no - * a lease that has same parent key, Send lease break -@@ -3321,6 +3506,26 @@ int smb2_open(struct ksmbd_work *work) - - memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); - -+ if (dh_info.type == DURABLE_REQ_V2 || dh_info.type == DURABLE_REQ) { -+ if (dh_info.type == DURABLE_REQ_V2 && dh_info.persistent && -+ test_share_config_flag(work->tcon->share_conf, -+ KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY)) -+ fp->is_persistent = true; -+ else -+ fp->is_durable = true; -+ -+ if (dh_info.type == DURABLE_REQ_V2) { -+ memcpy(fp->create_guid, dh_info.CreateGuid, -+ SMB2_CREATE_GUID_SIZE); -+ if (dh_info.timeout) -+ fp->durable_timeout = min(dh_info.timeout, -+ 300000); -+ else -+ fp->durable_timeout = 60; -+ } -+ } -+ -+reconnected_fp: - rsp->StructureSize = cpu_to_le16(89); - rcu_read_lock(); - opinfo = rcu_dereference(fp->f_opinfo); -@@ -3407,6 +3612,33 @@ int smb2_open(struct ksmbd_work *work) - next_off = conn->vals->create_disk_id_size; - } - -+ if (dh_info.type == DURABLE_REQ || dh_info.type == DURABLE_REQ_V2) { -+ struct create_context *durable_ccontext; -+ -+ durable_ccontext = (struct create_context *)(rsp->Buffer + -+ le32_to_cpu(rsp->CreateContextsLength)); -+ contxt_cnt++; -+ if (dh_info.type == DURABLE_REQ) { -+ create_durable_rsp_buf(rsp->Buffer + -+ le32_to_cpu(rsp->CreateContextsLength)); -+ le32_add_cpu(&rsp->CreateContextsLength, -+ conn->vals->create_durable_size); -+ iov_len += conn->vals->create_durable_size; -+ } else { -+ create_durable_v2_rsp_buf(rsp->Buffer + -+ le32_to_cpu(rsp->CreateContextsLength), -+ fp); -+ le32_add_cpu(&rsp->CreateContextsLength, -+ conn->vals->create_durable_v2_size); -+ iov_len += conn->vals->create_durable_v2_size; -+ } -+ -+ if (next_ptr) -+ *next_ptr = cpu_to_le32(next_off); -+ next_ptr = &durable_ccontext->Next; -+ next_off = conn->vals->create_durable_size; -+ } -+ - if (posix_ctxt) { - contxt_cnt++; - create_posix_rsp_buf(rsp->Buffer + -@@ -4084,7 +4316,7 @@ int smb2_query_dir(struct ksmbd_work *work) - } - - srch_flag = req->Flags; -- srch_ptr = smb_strndup_from_utf16(req->Buffer, -+ srch_ptr = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->FileNameOffset), - le16_to_cpu(req->FileNameLength), 1, - conn->local_nls); - if (IS_ERR(srch_ptr)) { -@@ -4344,7 +4576,8 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp, - sizeof(struct smb2_ea_info_req)) - return -EINVAL; - -- ea_req = (struct smb2_ea_info_req *)req->Buffer; -+ ea_req = (struct smb2_ea_info_req *)((char *)req + -+ le16_to_cpu(req->InputBufferOffset)); - } else { - /* need to send all EAs, if no specific EA is requested*/ - if (le32_to_cpu(req->Flags) & SL_RETURN_SINGLE_ENTRY) -@@ -5991,6 +6224,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, - struct ksmbd_share_config *share) - { - unsigned int buf_len = le32_to_cpu(req->BufferLength); -+ char *buffer = (char *)req + le16_to_cpu(req->BufferOffset); - - switch (req->FileInfoClass) { - case FILE_BASIC_INFORMATION: -@@ -5998,7 +6232,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, - if (buf_len < sizeof(struct smb2_file_basic_info)) - return -EINVAL; - -- return set_file_basic_info(fp, (struct smb2_file_basic_info *)req->Buffer, share); -+ return set_file_basic_info(fp, (struct smb2_file_basic_info *)buffer, share); - } - case FILE_ALLOCATION_INFORMATION: - { -@@ -6006,7 +6240,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, - return -EINVAL; - - return set_file_allocation_info(work, fp, -- (struct smb2_file_alloc_info *)req->Buffer); -+ (struct smb2_file_alloc_info *)buffer); - } - case FILE_END_OF_FILE_INFORMATION: - { -@@ -6014,7 +6248,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, - return -EINVAL; - - return set_end_of_file_info(work, fp, -- (struct smb2_file_eof_info *)req->Buffer); -+ (struct smb2_file_eof_info *)buffer); - } - case FILE_RENAME_INFORMATION: - { -@@ -6022,7 +6256,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, - return -EINVAL; - - return set_rename_info(work, fp, -- (struct smb2_file_rename_info *)req->Buffer, -+ (struct smb2_file_rename_info *)buffer, - buf_len); - } - case FILE_LINK_INFORMATION: -@@ -6031,7 +6265,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, - return -EINVAL; - - return smb2_create_link(work, work->tcon->share_conf, -- (struct smb2_file_link_info *)req->Buffer, -+ (struct smb2_file_link_info *)buffer, - buf_len, fp->filp, - work->conn->local_nls); - } -@@ -6041,7 +6275,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, - return -EINVAL; - - return set_file_disposition_info(fp, -- (struct smb2_file_disposition_info *)req->Buffer); -+ (struct smb2_file_disposition_info *)buffer); - } - case FILE_FULL_EA_INFORMATION: - { -@@ -6054,7 +6288,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, - if (buf_len < sizeof(struct smb2_ea_info)) - return -EINVAL; - -- return smb2_set_ea((struct smb2_ea_info *)req->Buffer, -+ return smb2_set_ea((struct smb2_ea_info *)buffer, - buf_len, &fp->filp->f_path, true); - } - case FILE_POSITION_INFORMATION: -@@ -6062,14 +6296,14 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, - if (buf_len < sizeof(struct smb2_file_pos_info)) - return -EINVAL; - -- return set_file_position_info(fp, (struct smb2_file_pos_info *)req->Buffer); -+ return set_file_position_info(fp, (struct smb2_file_pos_info *)buffer); - } - case FILE_MODE_INFORMATION: - { - if (buf_len < sizeof(struct smb2_file_mode_info)) - return -EINVAL; - -- return set_file_mode_info(fp, (struct smb2_file_mode_info *)req->Buffer); -+ return set_file_mode_info(fp, (struct smb2_file_mode_info *)buffer); - } - } - -@@ -6150,7 +6384,7 @@ int smb2_set_info(struct ksmbd_work *work) - } - rc = smb2_set_info_sec(fp, - le32_to_cpu(req->AdditionalInformation), -- req->Buffer, -+ (char *)req + le16_to_cpu(req->BufferOffset), - le32_to_cpu(req->BufferLength)); - ksmbd_revert_fsids(work); - break; -@@ -7596,7 +7830,7 @@ static int fsctl_pipe_transceive(struct ksmbd_work *work, u64 id, - struct smb2_ioctl_rsp *rsp) - { - struct ksmbd_rpc_command *rpc_resp; -- char *data_buf = (char *)&req->Buffer[0]; -+ char *data_buf = (char *)req + le32_to_cpu(req->InputOffset); - int nbytes = 0; - - rpc_resp = ksmbd_rpc_ioctl(work->sess, id, data_buf, -@@ -7709,6 +7943,7 @@ int smb2_ioctl(struct ksmbd_work *work) - u64 id = KSMBD_NO_FID; - struct ksmbd_conn *conn = work->conn; - int ret = 0; -+ char *buffer; - - if (work->next_smb2_rcv_hdr_off) { - req = ksmbd_req_buf_next(work); -@@ -7731,6 +7966,8 @@ int smb2_ioctl(struct ksmbd_work *work) - goto out; - } - -+ buffer = (char *)req + le32_to_cpu(req->InputOffset); -+ - cnt_code = le32_to_cpu(req->CtlCode); - ret = smb2_calc_max_out_buf_len(work, 48, - le32_to_cpu(req->MaxOutputResponse)); -@@ -7788,7 +8025,7 @@ int smb2_ioctl(struct ksmbd_work *work) - } - - ret = fsctl_validate_negotiate_info(conn, -- (struct validate_negotiate_info_req *)&req->Buffer[0], -+ (struct validate_negotiate_info_req *)buffer, - (struct validate_negotiate_info_rsp *)&rsp->Buffer[0], - in_buf_len); - if (ret < 0) -@@ -7841,7 +8078,7 @@ int smb2_ioctl(struct ksmbd_work *work) - rsp->VolatileFileId = req->VolatileFileId; - rsp->PersistentFileId = req->PersistentFileId; - fsctl_copychunk(work, -- (struct copychunk_ioctl_req *)&req->Buffer[0], -+ (struct copychunk_ioctl_req *)buffer, - le32_to_cpu(req->CtlCode), - le32_to_cpu(req->InputCount), - req->VolatileFileId, -@@ -7854,8 +8091,7 @@ int smb2_ioctl(struct ksmbd_work *work) - goto out; - } - -- ret = fsctl_set_sparse(work, id, -- (struct file_sparse *)&req->Buffer[0]); -+ ret = fsctl_set_sparse(work, id, (struct file_sparse *)buffer); - if (ret < 0) - goto out; - break; -@@ -7878,7 +8114,7 @@ int smb2_ioctl(struct ksmbd_work *work) - } - - zero_data = -- (struct file_zero_data_information *)&req->Buffer[0]; -+ (struct file_zero_data_information *)buffer; - - off = le64_to_cpu(zero_data->FileOffset); - bfz = le64_to_cpu(zero_data->BeyondFinalZero); -@@ -7909,7 +8145,7 @@ int smb2_ioctl(struct ksmbd_work *work) - } - - ret = fsctl_query_allocated_ranges(work, id, -- (struct file_allocated_range_buffer *)&req->Buffer[0], -+ (struct file_allocated_range_buffer *)buffer, - (struct file_allocated_range_buffer *)&rsp->Buffer[0], - out_buf_len / - sizeof(struct file_allocated_range_buffer), &nbytes); -@@ -7953,7 +8189,7 @@ int smb2_ioctl(struct ksmbd_work *work) - goto out; - } - -- dup_ext = (struct duplicate_extents_to_file *)&req->Buffer[0]; -+ dup_ext = (struct duplicate_extents_to_file *)buffer; - - fp_in = ksmbd_lookup_fd_slow(work, dup_ext->VolatileFileHandle, - dup_ext->PersistentFileHandle); -diff --git a/fs/smb/server/smb2pdu.h b/fs/smb/server/smb2pdu.h -index d12cfd3b09278..643f5e1cfe357 100644 ---- a/fs/smb/server/smb2pdu.h -+++ b/fs/smb/server/smb2pdu.h -@@ -64,7 +64,7 @@ struct preauth_integrity_info { - #define SMB2_SESSION_TIMEOUT (10 * HZ) - - struct create_durable_req_v2 { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - __le32 Timeout; - __le32 Flags; -@@ -72,8 +72,20 @@ struct create_durable_req_v2 { - __u8 CreateGuid[16]; - } __packed; - -+struct create_durable_reconn_req { -+ struct create_context_hdr ccontext; -+ __u8 Name[8]; -+ union { -+ __u8 Reserved[16]; -+ struct { -+ __u64 PersistentFileId; -+ __u64 VolatileFileId; -+ } Fid; -+ } Data; -+} __packed; -+ - struct create_durable_reconn_v2_req { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - struct { - __u64 PersistentFileId; -@@ -84,13 +96,13 @@ struct create_durable_reconn_v2_req { - } __packed; - - struct create_alloc_size_req { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - __le64 AllocationSize; - } __packed; - - struct create_durable_rsp { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - union { - __u8 Reserved[8]; -@@ -98,8 +110,11 @@ struct create_durable_rsp { - } Data; - } __packed; - -+/* See MS-SMB2 2.2.13.2.11 */ -+/* Flags */ -+#define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002 - struct create_durable_v2_rsp { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - __le32 Timeout; - __le32 Flags; -@@ -107,7 +122,7 @@ struct create_durable_v2_rsp { - - /* equivalent of the contents of SMB3.1.1 POSIX open context response */ - struct create_posix_rsp { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[16]; - __le32 nlink; - __le32 reparse_tag; -@@ -366,13 +381,13 @@ struct smb2_ea_info { - } __packed; /* level 15 Query */ - - struct create_ea_buf_req { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - struct smb2_ea_info ea; - } __packed; - - struct create_sd_buf_req { -- struct create_context ccontext; -+ struct create_context_hdr ccontext; - __u8 Name[8]; - struct smb_ntsd ntsd; - } __packed; -diff --git a/fs/smb/server/transport_tcp.c b/fs/smb/server/transport_tcp.c -index 0012919309f11..6633fa78e9b96 100644 ---- a/fs/smb/server/transport_tcp.c -+++ b/fs/smb/server/transport_tcp.c -@@ -365,6 +365,7 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig, - * @t: TCP transport instance - * @buf: buffer to store read data from socket - * @to_read: number of bytes to read from socket -+ * @max_retries: number of retries if reading from socket fails - * - * Return: on success return number of bytes read from socket, - * otherwise return error number -@@ -416,6 +417,7 @@ static void tcp_destroy_socket(struct socket *ksmbd_socket) - - /** - * create_socket - create socket for ksmbd/0 -+ * @iface: interface to bind the created socket to - * - * Return: 0 on success, error number otherwise - */ -diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c -index 626406b0cf4ac..2558119969359 100644 ---- a/fs/smb/server/vfs.c -+++ b/fs/smb/server/vfs.c -@@ -49,6 +49,10 @@ static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work, - - /** - * ksmbd_vfs_lock_parent() - lock parent dentry if it is stable -+ * @parent: parent dentry -+ * @child: child dentry -+ * -+ * Returns: %0 on success, %-ENOENT if the parent dentry is not stable - */ - int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child) - { -@@ -360,7 +364,7 @@ static int check_lock_range(struct file *filp, loff_t start, loff_t end, - /** - * ksmbd_vfs_read() - vfs helper for smb file read - * @work: smb work -- * @fid: file id of open file -+ * @fp: ksmbd file pointer - * @count: read byte count - * @pos: file pos - * @rbuf: read data buffer -@@ -474,7 +478,7 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos, - /** - * ksmbd_vfs_write() - vfs helper for smb file write - * @work: work -- * @fid: file id of open file -+ * @fp: ksmbd file pointer - * @buf: buf containing data for writing - * @count: read byte count - * @pos: file pos -@@ -545,10 +549,8 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, - - /** - * ksmbd_vfs_getattr() - vfs helper for smb getattr -- * @work: work -- * @fid: file id of open file -- * @attrs: inode attributes -- * -+ * @path: path of dentry -+ * @stat: pointer to returned kernel stat structure - * Return: 0 on success, otherwise error - */ - int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat) -@@ -565,6 +567,7 @@ int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat) - * ksmbd_vfs_fsync() - vfs helper for smb fsync - * @work: work - * @fid: file id of open file -+ * @p_id: persistent file id - * - * Return: 0 on success, otherwise error - */ -@@ -587,7 +590,8 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id) - - /** - * ksmbd_vfs_remove_file() - vfs helper for smb rmdir or unlink -- * @name: directory or file name that is relative to share -+ * @work: work -+ * @path: path of dentry - * - * Return: 0 on success, otherwise error - */ -@@ -623,6 +627,7 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path) - - /** - * ksmbd_vfs_link() - vfs helper for creating smb hardlink -+ * @work: work - * @oldname: source file name - * @newname: hardlink name that is relative to share - * -@@ -800,7 +805,7 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path, - /** - * ksmbd_vfs_truncate() - vfs helper for smb file truncate - * @work: work -- * @fid: file id of old file -+ * @fp: ksmbd file pointer - * @size: truncate to given size - * - * Return: 0 on success, otherwise error -@@ -843,7 +848,6 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work, - * ksmbd_vfs_listxattr() - vfs helper for smb list extended attributes - * @dentry: dentry of file for listing xattrs - * @list: destination buffer -- * @size: destination buffer length - * - * Return: xattr list length on success, otherwise error - */ -@@ -952,7 +956,7 @@ int ksmbd_vfs_setxattr(struct mnt_idmap *idmap, - /** - * ksmbd_vfs_set_fadvise() - convert smb IO caching options to linux options - * @filp: file pointer for IO -- * @options: smb IO options -+ * @option: smb IO options - */ - void ksmbd_vfs_set_fadvise(struct file *filp, __le32 option) - { -@@ -1164,6 +1168,7 @@ static bool __caseless_lookup(struct dir_context *ctx, const char *name, - * @dir: path info - * @name: filename to lookup - * @namelen: filename length -+ * @um: &struct unicode_map to use - * - * Return: 0 on success, otherwise error - */ -@@ -1194,6 +1199,7 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name, - - /** - * ksmbd_vfs_kern_path_locked() - lookup a file and get path info -+ * @work: work - * @name: file path that is relative to share - * @flags: lookup flags - * @parent_path: if lookup succeed, return parent_path info -@@ -1641,6 +1647,8 @@ int ksmbd_vfs_get_dos_attrib_xattr(struct mnt_idmap *idmap, - * ksmbd_vfs_init_kstat() - convert unix stat information to smb stat format - * @p: destination buffer - * @ksmbd_kstat: ksmbd kstat wrapper -+ * -+ * Returns: pointer to the converted &struct file_directory_info - */ - void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat) - { -diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c -index 4e82ff627d122..030f70700036c 100644 ---- a/fs/smb/server/vfs_cache.c -+++ b/fs/smb/server/vfs_cache.c -@@ -305,7 +305,8 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp) - - fd_limit_close(); - __ksmbd_remove_durable_fd(fp); -- __ksmbd_remove_fd(ft, fp); -+ if (ft) -+ __ksmbd_remove_fd(ft, fp); - - close_id_del_oplock(fp); - filp = fp->filp; -@@ -465,11 +466,32 @@ struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id, - return fp; - } - --struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id) -+struct ksmbd_file *ksmbd_lookup_global_fd(unsigned long long id) - { - return __ksmbd_lookup_fd(&global_ft, id); - } - -+struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id) -+{ -+ struct ksmbd_file *fp; -+ -+ fp = __ksmbd_lookup_fd(&global_ft, id); -+ if (fp && fp->conn) { -+ ksmbd_put_durable_fd(fp); -+ fp = NULL; -+ } -+ -+ return fp; -+} -+ -+void ksmbd_put_durable_fd(struct ksmbd_file *fp) -+{ -+ if (!atomic_dec_and_test(&fp->refcount)) -+ return; -+ -+ __ksmbd_close_fd(NULL, fp); -+} -+ - struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid) - { - struct ksmbd_file *fp = NULL; -@@ -639,6 +661,32 @@ __close_file_table_ids(struct ksmbd_file_table *ft, - return num; - } - -+static inline bool is_reconnectable(struct ksmbd_file *fp) -+{ -+ struct oplock_info *opinfo = opinfo_get(fp); -+ bool reconn = false; -+ -+ if (!opinfo) -+ return false; -+ -+ if (opinfo->op_state != OPLOCK_STATE_NONE) { -+ opinfo_put(opinfo); -+ return false; -+ } -+ -+ if (fp->is_resilient || fp->is_persistent) -+ reconn = true; -+ else if (fp->is_durable && opinfo->is_lease && -+ opinfo->o_lease->state & SMB2_LEASE_HANDLE_CACHING_LE) -+ reconn = true; -+ -+ else if (fp->is_durable && opinfo->level == SMB2_OPLOCK_LEVEL_BATCH) -+ reconn = true; -+ -+ opinfo_put(opinfo); -+ return reconn; -+} -+ - static bool tree_conn_fd_check(struct ksmbd_tree_connect *tcon, - struct ksmbd_file *fp) - { -@@ -648,7 +696,28 @@ static bool tree_conn_fd_check(struct ksmbd_tree_connect *tcon, - static bool session_fd_check(struct ksmbd_tree_connect *tcon, - struct ksmbd_file *fp) - { -- return false; -+ struct ksmbd_inode *ci; -+ struct oplock_info *op; -+ struct ksmbd_conn *conn; -+ -+ if (!is_reconnectable(fp)) -+ return false; -+ -+ conn = fp->conn; -+ ci = fp->f_ci; -+ write_lock(&ci->m_lock); -+ list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) { -+ if (op->conn != conn) -+ continue; -+ op->conn = NULL; -+ } -+ write_unlock(&ci->m_lock); -+ -+ fp->conn = NULL; -+ fp->tcon = NULL; -+ fp->volatile_id = KSMBD_NO_FID; -+ -+ return true; - } - - void ksmbd_close_tree_conn_fds(struct ksmbd_work *work) -@@ -687,6 +756,68 @@ void ksmbd_free_global_file_table(void) - ksmbd_destroy_file_table(&global_ft); - } - -+int ksmbd_validate_name_reconnect(struct ksmbd_share_config *share, -+ struct ksmbd_file *fp, char *name) -+{ -+ char *pathname, *ab_pathname; -+ int ret = 0; -+ -+ pathname = kmalloc(PATH_MAX, GFP_KERNEL); -+ if (!pathname) -+ return -EACCES; -+ -+ ab_pathname = d_path(&fp->filp->f_path, pathname, PATH_MAX); -+ if (IS_ERR(ab_pathname)) { -+ kfree(pathname); -+ return -EACCES; -+ } -+ -+ if (name && strcmp(&ab_pathname[share->path_sz + 1], name)) { -+ ksmbd_debug(SMB, "invalid name reconnect %s\n", name); -+ ret = -EINVAL; -+ } -+ -+ kfree(pathname); -+ -+ return ret; -+} -+ -+int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp) -+{ -+ struct ksmbd_inode *ci; -+ struct oplock_info *op; -+ -+ if (!fp->is_durable || fp->conn || fp->tcon) { -+ pr_err("Invalid durable fd [%p:%p]\n", fp->conn, fp->tcon); -+ return -EBADF; -+ } -+ -+ if (has_file_id(fp->volatile_id)) { -+ pr_err("Still in use durable fd: %llu\n", fp->volatile_id); -+ return -EBADF; -+ } -+ -+ fp->conn = work->conn; -+ fp->tcon = work->tcon; -+ -+ ci = fp->f_ci; -+ write_lock(&ci->m_lock); -+ list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) { -+ if (op->conn) -+ continue; -+ op->conn = fp->conn; -+ } -+ write_unlock(&ci->m_lock); -+ -+ __open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID); -+ if (!has_file_id(fp->volatile_id)) { -+ fp->conn = NULL; -+ fp->tcon = NULL; -+ return -EBADF; -+ } -+ return 0; -+} -+ - int ksmbd_init_file_table(struct ksmbd_file_table *ft) - { - ft->idr = kzalloc(sizeof(struct idr), GFP_KERNEL); -diff --git a/fs/smb/server/vfs_cache.h b/fs/smb/server/vfs_cache.h -index a528f0cc775ae..ed44fb4e18e79 100644 ---- a/fs/smb/server/vfs_cache.h -+++ b/fs/smb/server/vfs_cache.h -@@ -14,6 +14,7 @@ - #include - - #include "vfs.h" -+#include "mgmt/share_config.h" - - /* Windows style file permissions for extended response */ - #define FILE_GENERIC_ALL 0x1F01FF -@@ -106,6 +107,9 @@ struct ksmbd_file { - int dot_dotdot[2]; - unsigned int f_state; - bool reserve_lease_break; -+ bool is_durable; -+ bool is_persistent; -+ bool is_resilient; - }; - - static inline void set_ctx_actor(struct dir_context *ctx, -@@ -141,7 +145,9 @@ struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id, - void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp); - struct ksmbd_inode *ksmbd_inode_lookup_lock(struct dentry *d); - void ksmbd_inode_put(struct ksmbd_inode *ci); -+struct ksmbd_file *ksmbd_lookup_global_fd(unsigned long long id); - struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id); -+void ksmbd_put_durable_fd(struct ksmbd_file *fp); - struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid); - struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry); - unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp); -@@ -173,6 +179,9 @@ void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp); - void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp); - void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp, - int file_info); -+int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp); -+int ksmbd_validate_name_reconnect(struct ksmbd_share_config *share, -+ struct ksmbd_file *fp, char *name); - int ksmbd_init_file_cache(void); - void ksmbd_exit_file_cache(void); - #endif /* __VFS_CACHE_H__ */ -diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h -index 5b6e86b2c37a5..a7b65d4ab616e 100644 ---- a/include/linux/blkdev.h -+++ b/include/linux/blkdev.h -@@ -229,6 +229,19 @@ static inline unsigned int disk_openers(struct gendisk *disk) - return atomic_read(&disk->part0->bd_openers); - } - -+/** -+ * disk_has_partscan - return %true if partition scanning is enabled on a disk -+ * @disk: disk to check -+ * -+ * Returns %true if partitions scanning is enabled for @disk, or %false if -+ * partition scanning is disabled either permanently or temporarily. -+ */ -+static inline bool disk_has_partscan(struct gendisk *disk) -+{ -+ return !(disk->flags & (GENHD_FL_NO_PART | GENHD_FL_HIDDEN)) && -+ !test_bit(GD_SUPPRESS_PART_SCAN, &disk->state); -+} -+ - /* - * The gendisk is refcounted by the part0 block_device, and the bd_device - * therein is also used for device model presentation in sysfs. -diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h -index fc0d6f32c6876..dfaae3e3ec153 100644 ---- a/include/linux/bpf_types.h -+++ b/include/linux/bpf_types.h -@@ -142,9 +142,12 @@ BPF_LINK_TYPE(BPF_LINK_TYPE_ITER, iter) - #ifdef CONFIG_NET - BPF_LINK_TYPE(BPF_LINK_TYPE_NETNS, netns) - BPF_LINK_TYPE(BPF_LINK_TYPE_XDP, xdp) -+BPF_LINK_TYPE(BPF_LINK_TYPE_NETFILTER, netfilter) -+BPF_LINK_TYPE(BPF_LINK_TYPE_TCX, tcx) - #endif - #ifdef CONFIG_PERF_EVENTS - BPF_LINK_TYPE(BPF_LINK_TYPE_PERF_EVENT, perf) - #endif - BPF_LINK_TYPE(BPF_LINK_TYPE_KPROBE_MULTI, kprobe_multi) - BPF_LINK_TYPE(BPF_LINK_TYPE_STRUCT_OPS, struct_ops) -+BPF_LINK_TYPE(BPF_LINK_TYPE_UPROBE_MULTI, uprobe_multi) -diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h -index 35c5f75a3a5ee..7367ef7e92f52 100644 ---- a/include/net/bluetooth/hci.h -+++ b/include/net/bluetooth/hci.h -@@ -1662,6 +1662,15 @@ struct hci_cp_le_set_event_mask { - __u8 mask[8]; - } __packed; - -+/* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E -+ * 7.8.2 LE Read Buffer Size command -+ * MAX_LE_MTU is 0xffff. -+ * 0 is also valid. It means that no dedicated LE Buffer exists. -+ * It should use the HCI_Read_Buffer_Size command and mtu is shared -+ * between BR/EDR and LE. -+ */ -+#define HCI_MIN_LE_MTU 0x001b -+ - #define HCI_OP_LE_READ_BUFFER_SIZE 0x2002 - struct hci_rp_le_read_buffer_size { - __u8 status; -diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h -index e6f659ce534e6..b5b0a1e1bba02 100644 ---- a/include/net/bluetooth/hci_core.h -+++ b/include/net/bluetooth/hci_core.h -@@ -707,6 +707,7 @@ struct hci_conn { - __u16 handle; - __u16 sync_handle; - __u16 state; -+ __u16 mtu; - __u8 mode; - __u8 type; - __u8 role; -diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c -index 1f8c8d65350c8..aea7f06c107eb 100644 ---- a/net/bluetooth/hci_conn.c -+++ b/net/bluetooth/hci_conn.c -@@ -939,11 +939,37 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, - { - struct hci_conn *conn; - -+ switch (type) { -+ case ACL_LINK: -+ if (!hdev->acl_mtu) -+ return ERR_PTR(-ECONNREFUSED); -+ break; -+ case ISO_LINK: -+ if (hdev->iso_mtu) -+ /* Dedicated ISO Buffer exists */ -+ break; -+ fallthrough; -+ case LE_LINK: -+ if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU) -+ return ERR_PTR(-ECONNREFUSED); -+ if (!hdev->le_mtu && hdev->acl_mtu < HCI_MIN_LE_MTU) -+ return ERR_PTR(-ECONNREFUSED); -+ break; -+ case SCO_LINK: -+ case ESCO_LINK: -+ if (!hdev->sco_pkts) -+ /* Controller does not support SCO or eSCO over HCI */ -+ return ERR_PTR(-ECONNREFUSED); -+ break; -+ default: -+ return ERR_PTR(-ECONNREFUSED); -+ } -+ - bt_dev_dbg(hdev, "dst %pMR handle 0x%4.4x", dst, handle); - - conn = kzalloc(sizeof(*conn), GFP_KERNEL); - if (!conn) -- return NULL; -+ return ERR_PTR(-ENOMEM); - - bacpy(&conn->dst, dst); - bacpy(&conn->src, &hdev->bdaddr); -@@ -974,10 +1000,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, - switch (type) { - case ACL_LINK: - conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK; -+ conn->mtu = hdev->acl_mtu; - break; - case LE_LINK: - /* conn->src should reflect the local identity address */ - hci_copy_identity_address(hdev, &conn->src, &conn->src_type); -+ conn->mtu = hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu; - break; - case ISO_LINK: - /* conn->src should reflect the local identity address */ -@@ -989,6 +1017,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, - else if (conn->role == HCI_ROLE_MASTER) - conn->cleanup = cis_cleanup; - -+ conn->mtu = hdev->iso_mtu ? hdev->iso_mtu : -+ hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu; - break; - case SCO_LINK: - if (lmp_esco_capable(hdev)) -@@ -996,9 +1026,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, - (hdev->esco_type & EDR_ESCO_MASK); - else - conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK; -+ -+ conn->mtu = hdev->sco_mtu; - break; - case ESCO_LINK: - conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK; -+ conn->mtu = hdev->sco_mtu; - break; - } - -@@ -1041,7 +1074,7 @@ struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type, - - handle = hci_conn_hash_alloc_unset(hdev); - if (unlikely(handle < 0)) -- return NULL; -+ return ERR_PTR(-ECONNREFUSED); - - return hci_conn_add(hdev, type, dst, role, handle); - } -@@ -1384,8 +1417,8 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, - bacpy(&conn->dst, dst); - } else { - conn = hci_conn_add_unset(hdev, LE_LINK, dst, role); -- if (!conn) -- return ERR_PTR(-ENOMEM); -+ if (IS_ERR(conn)) -+ return conn; - hci_conn_hold(conn); - conn->pending_sec_level = sec_level; - } -@@ -1549,8 +1582,8 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst, - return ERR_PTR(-EADDRINUSE); - - conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER); -- if (!conn) -- return ERR_PTR(-ENOMEM); -+ if (IS_ERR(conn)) -+ return conn; - - conn->state = BT_CONNECT; - -@@ -1593,8 +1626,8 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst, - BT_DBG("requesting refresh of dst_addr"); - - conn = hci_conn_add_unset(hdev, LE_LINK, dst, HCI_ROLE_MASTER); -- if (!conn) -- return ERR_PTR(-ENOMEM); -+ if (IS_ERR(conn)) -+ return conn; - - if (hci_explicit_conn_params_set(hdev, dst, dst_type) < 0) { - hci_conn_del(conn); -@@ -1641,8 +1674,8 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, - acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); - if (!acl) { - acl = hci_conn_add_unset(hdev, ACL_LINK, dst, HCI_ROLE_MASTER); -- if (!acl) -- return ERR_PTR(-ENOMEM); -+ if (IS_ERR(acl)) -+ return acl; - } - - hci_conn_hold(acl); -@@ -1701,9 +1734,9 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, - sco = hci_conn_hash_lookup_ba(hdev, type, dst); - if (!sco) { - sco = hci_conn_add_unset(hdev, type, dst, HCI_ROLE_MASTER); -- if (!sco) { -+ if (IS_ERR(sco)) { - hci_conn_drop(acl); -- return ERR_PTR(-ENOMEM); -+ return sco; - } - } - -@@ -1893,8 +1926,8 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst, - qos->ucast.cis); - if (!cis) { - cis = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER); -- if (!cis) -- return ERR_PTR(-ENOMEM); -+ if (IS_ERR(cis)) -+ return cis; - cis->cleanup = cis_cleanup; - cis->dst_type = dst_type; - cis->iso_qos.ucast.cig = BT_ISO_QOS_CIG_UNSET; -@@ -2029,14 +2062,8 @@ static void hci_iso_qos_setup(struct hci_dev *hdev, struct hci_conn *conn, - struct bt_iso_io_qos *qos, __u8 phy) - { - /* Only set MTU if PHY is enabled */ -- if (!qos->sdu && qos->phy) { -- if (hdev->iso_mtu > 0) -- qos->sdu = hdev->iso_mtu; -- else if (hdev->le_mtu > 0) -- qos->sdu = hdev->le_mtu; -- else -- qos->sdu = hdev->acl_mtu; -- } -+ if (!qos->sdu && qos->phy) -+ qos->sdu = conn->mtu; - - /* Use the same PHY as ACL if set to any */ - if (qos->phy == BT_ISO_PHY_ANY) -diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c -index 9274d32550493..361e2c68a51a1 100644 ---- a/net/bluetooth/hci_event.c -+++ b/net/bluetooth/hci_event.c -@@ -958,6 +958,9 @@ static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data, - BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, - hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); - -+ if (!hdev->acl_mtu || !hdev->acl_pkts) -+ return HCI_ERROR_INVALID_PARAMETERS; -+ - return rp->status; - } - -@@ -1267,6 +1270,9 @@ static u8 hci_cc_le_read_buffer_size(struct hci_dev *hdev, void *data, - - BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); - -+ if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU) -+ return HCI_ERROR_INVALID_PARAMETERS; -+ - return rp->status; - } - -@@ -2351,8 +2357,8 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) - if (!conn) { - conn = hci_conn_add_unset(hdev, ACL_LINK, &cp->bdaddr, - HCI_ROLE_MASTER); -- if (!conn) -- bt_dev_err(hdev, "no memory for new connection"); -+ if (IS_ERR(conn)) -+ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn)); - } - } - -@@ -3165,8 +3171,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, - BDADDR_BREDR)) { - conn = hci_conn_add_unset(hdev, ev->link_type, - &ev->bdaddr, HCI_ROLE_SLAVE); -- if (!conn) { -- bt_dev_err(hdev, "no memory for new conn"); -+ if (IS_ERR(conn)) { -+ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn)); - goto unlock; - } - } else { -@@ -3356,8 +3362,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data, - if (!conn) { - conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr, - HCI_ROLE_SLAVE); -- if (!conn) { -- bt_dev_err(hdev, "no memory for new connection"); -+ if (IS_ERR(conn)) { -+ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn)); - goto unlock; - } - } -@@ -3834,6 +3840,9 @@ static u8 hci_cc_le_read_buffer_size_v2(struct hci_dev *hdev, void *data, - BT_DBG("%s acl mtu %d:%d iso mtu %d:%d", hdev->name, hdev->acl_mtu, - hdev->acl_pkts, hdev->iso_mtu, hdev->iso_pkts); - -+ if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU) -+ return HCI_ERROR_INVALID_PARAMETERS; -+ - return rp->status; - } - -@@ -5925,8 +5934,8 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, - goto unlock; - - conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, role); -- if (!conn) { -- bt_dev_err(hdev, "no memory for new connection"); -+ if (IS_ERR(conn)) { -+ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn)); - goto unlock; - } - -@@ -7051,7 +7060,7 @@ static void hci_le_cis_req_evt(struct hci_dev *hdev, void *data, - if (!cis) { - cis = hci_conn_add(hdev, ISO_LINK, &acl->dst, HCI_ROLE_SLAVE, - cis_handle); -- if (!cis) { -+ if (IS_ERR(cis)) { - hci_le_reject_cis(hdev, ev->cis_handle); - goto unlock; - } -@@ -7170,7 +7179,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data, - if (!bis) { - bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY, - HCI_ROLE_SLAVE, handle); -- if (!bis) -+ if (IS_ERR(bis)) - continue; - } - -@@ -7242,7 +7251,7 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data, - pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY, - HCI_ROLE_SLAVE); - -- if (!pa_sync) -+ if (IS_ERR(pa_sync)) - goto unlock; - - pa_sync->sync_handle = le16_to_cpu(ev->sync_handle); -diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c -index 2f63ea9e62ecd..05b9edb480f09 100644 ---- a/net/bluetooth/iso.c -+++ b/net/bluetooth/iso.c -@@ -1135,7 +1135,7 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg, - return -ENOTCONN; - } - -- mtu = iso_pi(sk)->conn->hcon->hdev->iso_mtu; -+ mtu = iso_pi(sk)->conn->hcon->mtu; - - release_sock(sk); - -diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c -index 1e961cfaa07b3..ab5d0204086fb 100644 ---- a/net/bluetooth/l2cap_core.c -+++ b/net/bluetooth/l2cap_core.c -@@ -3905,13 +3905,12 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, - return 0; - } - --static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, -- struct l2cap_cmd_hdr *cmd, -- u8 *data, u8 rsp_code, u8 amp_id) -+static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, -+ u8 *data, u8 rsp_code, u8 amp_id) - { - struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; - struct l2cap_conn_rsp rsp; -- struct l2cap_chan *chan = NULL, *pchan; -+ struct l2cap_chan *chan = NULL, *pchan = NULL; - int result, status = L2CAP_CS_NO_INFO; - - u16 dcid = 0, scid = __le16_to_cpu(req->scid); -@@ -3924,7 +3923,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, - &conn->hcon->dst, ACL_LINK); - if (!pchan) { - result = L2CAP_CR_BAD_PSM; -- goto sendresp; -+ goto response; - } - - mutex_lock(&conn->chan_lock); -@@ -4011,17 +4010,15 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, - } - - response: -- l2cap_chan_unlock(pchan); -- mutex_unlock(&conn->chan_lock); -- l2cap_chan_put(pchan); -- --sendresp: - rsp.scid = cpu_to_le16(scid); - rsp.dcid = cpu_to_le16(dcid); - rsp.result = cpu_to_le16(result); - rsp.status = cpu_to_le16(status); - l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); - -+ if (!pchan) -+ return; -+ - if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { - struct l2cap_info_req info; - info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); -@@ -4044,7 +4041,9 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, - chan->num_conf_req++; - } - -- return chan; -+ l2cap_chan_unlock(pchan); -+ mutex_unlock(&conn->chan_lock); -+ l2cap_chan_put(pchan); - } - - static int l2cap_connect_req(struct l2cap_conn *conn, -@@ -6242,7 +6241,7 @@ static int l2cap_finish_move(struct l2cap_chan *chan) - BT_DBG("chan %p", chan); - - chan->rx_state = L2CAP_RX_STATE_RECV; -- chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; -+ chan->conn->mtu = chan->conn->hcon->mtu; - - return l2cap_resegment(chan); - } -@@ -6309,7 +6308,7 @@ static int l2cap_rx_state_wait_f(struct l2cap_chan *chan, - */ - chan->next_tx_seq = control->reqseq; - chan->unacked_frames = 0; -- chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu; -+ chan->conn->mtu = chan->conn->hcon->mtu; - - err = l2cap_resegment(chan); - -@@ -6849,18 +6848,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) - - BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); - -- switch (hcon->type) { -- case LE_LINK: -- if (hcon->hdev->le_mtu) { -- conn->mtu = hcon->hdev->le_mtu; -- break; -- } -- fallthrough; -- default: -- conn->mtu = hcon->hdev->acl_mtu; -- break; -- } -- -+ conn->mtu = hcon->mtu; - conn->feat_mask = 0; - - conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS; -diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c -index ede7391f3aa98..3c3650902c839 100644 ---- a/net/bluetooth/sco.c -+++ b/net/bluetooth/sco.c -@@ -126,7 +126,6 @@ static void sco_sock_clear_timer(struct sock *sk) - /* ---- SCO connections ---- */ - static struct sco_conn *sco_conn_add(struct hci_conn *hcon) - { -- struct hci_dev *hdev = hcon->hdev; - struct sco_conn *conn = hcon->sco_data; - - if (conn) { -@@ -144,9 +143,10 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon) - - hcon->sco_data = conn; - conn->hcon = hcon; -+ conn->mtu = hcon->mtu; - -- if (hdev->sco_mtu > 0) -- conn->mtu = hdev->sco_mtu; -+ if (hcon->mtu > 0) -+ conn->mtu = hcon->mtu; - else - conn->mtu = 60; - -diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c -index bc700f85f80be..ea277c55a38db 100644 ---- a/security/keys/trusted-keys/trusted_tpm2.c -+++ b/security/keys/trusted-keys/trusted_tpm2.c -@@ -38,6 +38,7 @@ static int tpm2_key_encode(struct trusted_key_payload *payload, - u8 *end_work = scratch + SCRATCH_SIZE; - u8 *priv, *pub; - u16 priv_len, pub_len; -+ int ret; - - priv_len = get_unaligned_be16(src) + 2; - priv = src; -@@ -57,8 +58,10 @@ static int tpm2_key_encode(struct trusted_key_payload *payload, - unsigned char bool[3], *w = bool; - /* tag 0 is emptyAuth */ - w = asn1_encode_boolean(w, w + sizeof(bool), true); -- if (WARN(IS_ERR(w), "BUG: Boolean failed to encode")) -- return PTR_ERR(w); -+ if (WARN(IS_ERR(w), "BUG: Boolean failed to encode")) { -+ ret = PTR_ERR(w); -+ goto err; -+ } - work = asn1_encode_tag(work, end_work, 0, bool, w - bool); - } - -@@ -69,8 +72,10 @@ static int tpm2_key_encode(struct trusted_key_payload *payload, - * trigger, so if it does there's something nefarious going on - */ - if (WARN(work - scratch + pub_len + priv_len + 14 > SCRATCH_SIZE, -- "BUG: scratch buffer is too small")) -- return -EINVAL; -+ "BUG: scratch buffer is too small")) { -+ ret = -EINVAL; -+ goto err; -+ } - - work = asn1_encode_integer(work, end_work, options->keyhandle); - work = asn1_encode_octet_string(work, end_work, pub, pub_len); -@@ -79,10 +84,18 @@ static int tpm2_key_encode(struct trusted_key_payload *payload, - work1 = payload->blob; - work1 = asn1_encode_sequence(work1, work1 + sizeof(payload->blob), - scratch, work - scratch); -- if (WARN(IS_ERR(work1), "BUG: ASN.1 encoder failed")) -- return PTR_ERR(work1); -+ if (IS_ERR(work1)) { -+ ret = PTR_ERR(work1); -+ pr_err("BUG: ASN.1 encoder failed with %d\n", ret); -+ goto err; -+ } - -+ kfree(scratch); - return work1 - payload->blob; -+ -+err: -+ kfree(scratch); -+ return ret; - } - - struct tpm2_key_context { -diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h -index e8eecbc83a60e..ad7b97e16f37e 100644 ---- a/tools/testing/selftests/kselftest.h -+++ b/tools/testing/selftests/kselftest.h -@@ -48,6 +48,7 @@ - #include - #include - #include -+#include - #include - #include - #endif -@@ -156,6 +157,19 @@ static inline void ksft_print_msg(const char *msg, ...) - va_end(args); - } - -+static inline void ksft_perror(const char *msg) -+{ -+#ifndef NOLIBC -+ ksft_print_msg("%s: %s (%d)\n", msg, strerror(errno), errno); -+#else -+ /* -+ * nolibc doesn't provide strerror() and it seems -+ * inappropriate to add one, just print the errno. -+ */ -+ ksft_print_msg("%s: %d)\n", msg, errno); -+#endif -+} -+ - static inline void ksft_test_result_pass(const char *msg, ...) - { - int saved_errno = errno; From 40ae7ac87765d9c4796eeaaf8069c17067f08150 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Wed, 5 Jun 2024 23:28:34 +0200 Subject: [PATCH 21/53] rk3588: edge: Bump kernel from 6.8 to 6.10 - Bump mainline kernel from 6.10-rc1 to 6.10-rc2 - Remove patches which are now mainlined - Re-number "fix-initial-PERST-GPIO-value" patch as per number ordering seen in 0000.patching_config.yaml - Rewrite kernel config --- .../kernel/linux-rockchip-rk3588-edge.config | 237 +- config/sources/families/rockchip-rk3588.conf | 2 +- config/sources/mainline-kernel.conf.sh | 2 +- .../0000.patching_config.yaml | 11 +- ...Makefile-delete-missing-cgroup_clean.patch | 34 - ...> 0012-fix-initial-PERST-GPIO-value.patch} | 0 .../0021-RK3588-Add-USB3-DRD-Support.patch | 2602 --- ...dd-Samsung-HDMI-eDP-Combo-PHY-driver.patch | 1091 -- ...dts-rockchip-Add-HDMI0-PHY-to-rk3588.patch | 54 - .../0141-panthor-v6.patch | 14855 ---------------- ...64-dts-rockchip-rk3588-Add-GPU-nodes.patch | 151 - ...-rockchip-rk3588-rock5b-Add-GPU-node.patch | 38 - .../1040-board-khadas-edge2-add-nodes.patch | 1464 -- 13 files changed, 173 insertions(+), 20368 deletions(-) delete mode 100644 patch/kernel/rockchip-rk3588-edge/0005-tools-Makefile-delete-missing-cgroup_clean.patch rename patch/kernel/rockchip-rk3588-edge/{1047-fix-initial-PERST#-GPIO-value.patch => 0012-fix-initial-PERST-GPIO-value.patch} (100%) delete mode 100644 patch/kernel/rockchip-rk3588-edge/0021-RK3588-Add-USB3-DRD-Support.patch delete mode 100644 patch/kernel/rockchip-rk3588-edge/0135-phy-rockchip-Add-Samsung-HDMI-eDP-Combo-PHY-driver.patch delete mode 100644 patch/kernel/rockchip-rk3588-edge/0136-arm64-dts-rockchip-Add-HDMI0-PHY-to-rk3588.patch delete mode 100644 patch/kernel/rockchip-rk3588-edge/0141-panthor-v6.patch delete mode 100644 patch/kernel/rockchip-rk3588-edge/0142-arm64-dts-rockchip-rk3588-Add-GPU-nodes.patch delete mode 100644 patch/kernel/rockchip-rk3588-edge/1013-arm64-dts-rockchip-rk3588-rock5b-Add-GPU-node.patch delete mode 100644 patch/kernel/rockchip-rk3588-edge/1040-board-khadas-edge2-add-nodes.patch diff --git a/config/kernel/linux-rockchip-rk3588-edge.config b/config/kernel/linux-rockchip-rk3588-edge.config index 6e4aac52f13b..bd394fa65291 100644 --- a/config/kernel/linux-rockchip-rk3588-edge.config +++ b/config/kernel/linux-rockchip-rk3588-edge.config @@ -1,15 +1,15 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 6.8.12 Kernel Configuration +# Linux/arm64 6.10.0-rc2 Kernel Configuration # -CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0" +CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0" CONFIG_CC_IS_GCC=y -CONFIG_GCC_VERSION=110400 +CONFIG_GCC_VERSION=130200 CONFIG_CLANG_VERSION=0 CONFIG_AS_IS_GNU=y -CONFIG_AS_VERSION=23800 +CONFIG_AS_VERSION=24200 CONFIG_LD_IS_BFD=y -CONFIG_LD_VERSION=23800 +CONFIG_LD_VERSION=24200 CONFIG_LLD_VERSION=0 CONFIG_CC_CAN_LINK=y CONFIG_CC_CAN_LINK_STATIC=y @@ -122,7 +122,7 @@ CONFIG_TICK_CPU_ACCOUNTING=y # CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set CONFIG_IRQ_TIME_ACCOUNTING=y CONFIG_HAVE_SCHED_AVG_IRQ=y -CONFIG_SCHED_THERMAL_PRESSURE=y +CONFIG_SCHED_HW_PRESSURE=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_TASKSTATS=y @@ -142,6 +142,7 @@ CONFIG_PREEMPT_RCU=y # CONFIG_RCU_EXPERT is not set CONFIG_TREE_SRCU=y CONFIG_TASKS_RCU_GENERIC=y +CONFIG_NEED_TASKS_RCU=y CONFIG_TASKS_RCU=y CONFIG_TASKS_TRACE_RCU=y CONFIG_RCU_STALL_COMMON=y @@ -173,6 +174,7 @@ CONFIG_CC_NO_STRINGOP_OVERFLOW=y CONFIG_ARCH_SUPPORTS_INT128=y CONFIG_NUMA_BALANCING=y CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y +CONFIG_SLAB_OBJ_EXT=y CONFIG_CGROUPS=y CONFIG_PAGE_COUNTER=y # CONFIG_CGROUP_FAVOR_DYNMODS is not set @@ -238,7 +240,7 @@ CONFIG_POSIX_TIMERS=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y +# CONFIG_BASE_SMALL is not set CONFIG_FUTEX=y CONFIG_FUTEX_PI=y CONFIG_EPOLL=y @@ -277,7 +279,6 @@ CONFIG_TRACEPOINTS=y # # Kexec and crash features # -CONFIG_CRASH_CORE=y CONFIG_KEXEC_CORE=y CONFIG_HAVE_IMA_KEXEC=y CONFIG_KEXEC=y @@ -291,7 +292,6 @@ CONFIG_ARM64=y CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y CONFIG_64BIT=y CONFIG_MMU=y -CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_CONT_PTE_SHIFT=4 CONFIG_ARM64_CONT_PMD_SHIFT=4 CONFIG_ARCH_MMAP_RND_BITS_MIN=18 @@ -318,6 +318,7 @@ CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y # Platform selection # # CONFIG_ARCH_ACTIONS is not set +# CONFIG_ARCH_AIROHA is not set # CONFIG_ARCH_SUNXI is not set # CONFIG_ARCH_ALPINE is not set # CONFIG_ARCH_APPLE is not set @@ -399,6 +400,9 @@ CONFIG_ARM64_ERRATUM_2645198=y CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD=y CONFIG_ARM64_ERRATUM_2966298=y CONFIG_ARM64_ERRATUM_3117295=y +CONFIG_ARM64_WORKAROUND_SPECULATIVE_SSBS=y +CONFIG_ARM64_ERRATUM_3194386=y +CONFIG_ARM64_ERRATUM_3312417=y CONFIG_CAVIUM_ERRATUM_22375=y CONFIG_CAVIUM_ERRATUM_23144=y CONFIG_CAVIUM_ERRATUM_23154=y @@ -421,6 +425,7 @@ CONFIG_ARM64_4K_PAGES=y # CONFIG_ARM64_64K_PAGES is not set # CONFIG_ARM64_VA_BITS_39 is not set CONFIG_ARM64_VA_BITS_48=y +# CONFIG_ARM64_VA_BITS_52 is not set CONFIG_ARM64_VA_BITS=48 CONFIG_ARM64_PA_BITS_48=y CONFIG_ARM64_PA_BITS=48 @@ -441,6 +446,7 @@ CONFIG_HZ=300 CONFIG_SCHED_HRTICK=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_HW_PERF_EVENTS=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y CONFIG_PARAVIRT=y CONFIG_PARAVIRT_TIME_ACCOUNTING=y CONFIG_ARCH_SUPPORTS_KEXEC=y @@ -450,7 +456,6 @@ CONFIG_ARCH_SUPPORTS_KEXEC_SIG=y CONFIG_ARCH_SUPPORTS_KEXEC_IMAGE_VERIFY_SIG=y CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y CONFIG_ARCH_SUPPORTS_CRASH_DUMP=y -CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION=y CONFIG_TRANS_TABLE=y CONFIG_XEN_DOM0=y CONFIG_XEN=y @@ -534,6 +539,7 @@ CONFIG_RANDOMIZE_BASE=y CONFIG_RANDOMIZE_MODULE_REGION_FULL=y CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y CONFIG_STACKPROTECTOR_PER_TASK=y +CONFIG_ARM64_CONTPTE=y # end of Kernel Features # @@ -555,6 +561,9 @@ CONFIG_SUSPEND_FREEZER=y CONFIG_HIBERNATE_CALLBACKS=y CONFIG_HIBERNATION=y CONFIG_HIBERNATION_SNAPSHOT_DEV=y +CONFIG_HIBERNATION_COMP_LZO=y +# CONFIG_HIBERNATION_COMP_LZ4 is not set +CONFIG_HIBERNATION_DEF_COMP="lzo" CONFIG_PM_STD_PARTITION="" CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y @@ -623,8 +632,8 @@ CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y # CONFIG_CPUFREQ_DT=y CONFIG_CPUFREQ_DT_PLATDEV=y -# CONFIG_ACPI_CPPC_CPUFREQ is not set # CONFIG_ARM_SCMI_CPUFREQ is not set +# CONFIG_ACPI_CPPC_CPUFREQ is not set # end of CPU Frequency scaling # end of CPU Power Management @@ -657,9 +666,9 @@ CONFIG_ACPI_TABLE_UPGRADE=y CONFIG_ACPI_PCI_SLOT=y CONFIG_ACPI_CONTAINER=y CONFIG_ACPI_HED=y -CONFIG_ACPI_CUSTOM_METHOD=m # CONFIG_ACPI_BGRT is not set CONFIG_ACPI_REDUCED_HARDWARE_ONLY=y +CONFIG_ACPI_NHLT=y CONFIG_ACPI_NUMA=y CONFIG_ACPI_HMAT=y CONFIG_HAVE_ACPI_APEI=y @@ -669,6 +678,7 @@ CONFIG_ACPI_APEI_GHES=y CONFIG_ACPI_APEI_SEA=y CONFIG_ACPI_APEI_MEMORY_FAILURE=y CONFIG_ACPI_APEI_EINJ=y +CONFIG_ACPI_APEI_EINJ_CXL=y # CONFIG_ACPI_APEI_ERST_DEBUG is not set CONFIG_ACPI_WATCHDOG=y CONFIG_ACPI_CONFIGFS=m @@ -683,7 +693,6 @@ CONFIG_ACPI_PCC=y CONFIG_PMIC_OPREGION=y CONFIG_ACPI_VIOT=y CONFIG_ACPI_PRMT=y -CONFIG_HAVE_KVM=y CONFIG_KVM_COMMON=y CONFIG_HAVE_KVM_IRQCHIP=y CONFIG_HAVE_KVM_IRQ_ROUTING=y @@ -692,6 +701,7 @@ CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL=y CONFIG_NEED_KVM_DIRTY_RING_WITH_BITMAP=y CONFIG_KVM_MMIO=y CONFIG_HAVE_KVM_MSI=y +CONFIG_HAVE_KVM_READONLY_MEM=y CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y CONFIG_KVM_VFIO=y CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y @@ -738,6 +748,7 @@ CONFIG_ARCH_WANTS_NO_INSTR=y CONFIG_HAVE_ASM_MODVERSIONS=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_RSEQ=y +CONFIG_HAVE_RUST=y CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y CONFIG_HAVE_HW_BREAKPOINT=y CONFIG_HAVE_PERF_EVENTS_NMI=y @@ -764,6 +775,8 @@ CONFIG_HAVE_ARCH_STACKLEAK=y CONFIG_HAVE_STACKPROTECTOR=y CONFIG_STACKPROTECTOR=y CONFIG_STACKPROTECTOR_STRONG=y +CONFIG_ARCH_SUPPORTS_SHADOW_CALL_STACK=y +# CONFIG_SHADOW_CALL_STACK is not set CONFIG_ARCH_SUPPORTS_LTO_CLANG=y CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y CONFIG_LTO_NONE=y @@ -780,6 +793,7 @@ CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y CONFIG_ARCH_WANT_PMD_MKWRITE=y CONFIG_HAVE_MOD_ARCH_SPECIFIC=y CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_WANTS_EXECMEM_LATE=y CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y CONFIG_SOFTIRQ_ON_OWN_STACK=y CONFIG_ARCH_HAS_ELF_RANDOMIZE=y @@ -787,8 +801,11 @@ CONFIG_HAVE_ARCH_MMAP_RND_BITS=y CONFIG_ARCH_MMAP_RND_BITS=18 CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +CONFIG_HAVE_PAGE_SIZE_4KB=y +CONFIG_PAGE_SIZE_4KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SHIFT=12 CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y CONFIG_CLONE_BACKWARDS=y CONFIG_OLD_SIGSUSPEND3=y @@ -815,6 +832,7 @@ CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y CONFIG_ARCH_SUPPORTS_PAGE_TABLE_CHECK=y CONFIG_ARCH_HAVE_TRACE_MMIO_ACCESS=y CONFIG_ARCH_HAS_HW_PTE_YOUNG=y +CONFIG_ARCH_HAS_KERNEL_FPU_SUPPORT=y # # GCOV-based kernel profiling @@ -829,7 +847,6 @@ CONFIG_FUNCTION_ALIGNMENT=4 # end of General architecture-dependent options CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_DEBUG is not set CONFIG_MODULE_FORCE_LOAD=y @@ -860,7 +877,6 @@ CONFIG_BLK_DEV_INTEGRITY_T10=y CONFIG_BLK_DEV_WRITE_MOUNTED=y CONFIG_BLK_DEV_ZONED=y CONFIG_BLK_DEV_THROTTLING=y -CONFIG_BLK_DEV_THROTTLING_LOW=y CONFIG_BLK_WBT=y CONFIG_BLK_WBT_MQ=y CONFIG_BLK_CGROUP_IOLATENCY=y @@ -868,7 +884,6 @@ CONFIG_BLK_CGROUP_IOLATENCY=y # CONFIG_BLK_CGROUP_IOCOST is not set # CONFIG_BLK_CGROUP_IOPRIO is not set CONFIG_BLK_DEBUG_FS=y -CONFIG_BLK_DEBUG_FS_ZONED=y CONFIG_BLK_SED_OPAL=y # CONFIG_BLK_INLINE_ENCRYPTION is not set @@ -953,7 +968,6 @@ CONFIG_ZPOOL=y CONFIG_SWAP=y CONFIG_ZSWAP=y CONFIG_ZSWAP_DEFAULT_ON=y -# CONFIG_ZSWAP_EXCLUSIVE_LOADS_DEFAULT_ON is not set # CONFIG_ZSWAP_SHRINKER_DEFAULT_ON is not set # CONFIG_ZSWAP_COMPRESSOR_DEFAULT_DEFLATE is not set # CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZO is not set @@ -991,7 +1005,7 @@ CONFIG_SPARSEMEM=y CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_HAVE_FAST_GUP=y +CONFIG_HAVE_GUP_FAST=y CONFIG_ARCH_KEEP_MEMBLOCK=y CONFIG_MEMORY_ISOLATION=y CONFIG_EXCLUSIVE_SYSTEM_RAM=y @@ -1025,6 +1039,7 @@ CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y # CONFIG_TRANSPARENT_HUGEPAGE_NEVER is not set CONFIG_THP_SWAP=y # CONFIG_READ_ONLY_THP_FOR_FS is not set +CONFIG_PGTABLE_HAS_HUGE_LEAVES=y CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y CONFIG_USE_PERCPU_NUMA_NODE_ID=y @@ -1065,6 +1080,7 @@ CONFIG_ARCH_SUPPORTS_PER_VMA_LOCK=y CONFIG_PER_VMA_LOCK=y CONFIG_LOCK_MM_AND_FIND_VMA=y CONFIG_IOMMU_MM_DATA=y +CONFIG_EXECMEM=y # # Data Access Monitoring @@ -1079,6 +1095,7 @@ CONFIG_NET_INGRESS=y CONFIG_NET_EGRESS=y CONFIG_NET_XGRESS=y CONFIG_NET_REDIRECT=y +CONFIG_SKB_DECRYPTED=y CONFIG_SKB_EXTENSIONS=y # @@ -1087,7 +1104,6 @@ CONFIG_SKB_EXTENSIONS=y CONFIG_PACKET=y CONFIG_PACKET_DIAG=m CONFIG_UNIX=y -CONFIG_UNIX_SCM=y CONFIG_AF_UNIX_OOB=y CONFIG_UNIX_DIAG=m CONFIG_TLS=m @@ -1467,6 +1483,7 @@ CONFIG_IP_VS_PE_SIP=m # IP: Netfilter Configuration # CONFIG_NF_DEFRAG_IPV4=m +CONFIG_IP_NF_IPTABLES_LEGACY=m CONFIG_NF_SOCKET_IPV4=m CONFIG_NF_TPROXY_IPV4=m CONFIG_NF_TABLES_IPV4=y @@ -1499,6 +1516,7 @@ CONFIG_IP_NF_TARGET_TTL=m CONFIG_IP_NF_RAW=m CONFIG_IP_NF_SECURITY=m CONFIG_IP_NF_ARPTABLES=m +CONFIG_NFT_COMPAT_ARP=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m # end of IP: Netfilter Configuration @@ -1506,6 +1524,7 @@ CONFIG_IP_NF_ARP_MANGLE=m # # IPv6: Netfilter Configuration # +CONFIG_IP6_NF_IPTABLES_LEGACY=m CONFIG_NF_SOCKET_IPV6=m CONFIG_NF_TPROXY_IPV6=m CONFIG_NF_TABLES_IPV6=y @@ -1543,6 +1562,7 @@ CONFIG_NF_TABLES_BRIDGE=m CONFIG_NFT_BRIDGE_META=m CONFIG_NFT_BRIDGE_REJECT=m CONFIG_NF_CONNTRACK_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES_LEGACY=m CONFIG_BRIDGE_NF_EBTABLES=m CONFIG_BRIDGE_EBT_BROUTE=m CONFIG_BRIDGE_EBT_T_FILTER=m @@ -1746,7 +1766,6 @@ CONFIG_NET_ACT_GACT=m CONFIG_GACT_PROB=y CONFIG_NET_ACT_MIRRED=m CONFIG_NET_ACT_SAMPLE=m -CONFIG_NET_ACT_IPT=m CONFIG_NET_ACT_NAT=m CONFIG_NET_ACT_PEDIT=m CONFIG_NET_ACT_SIMP=m @@ -1904,6 +1923,7 @@ CONFIG_BT_MTKUART=m CONFIG_BT_HCIRSI=m CONFIG_BT_VIRTIO=m # CONFIG_BT_NXPUART is not set +# CONFIG_BT_INTEL_PCIE is not set # end of Bluetooth device drivers CONFIG_AF_RXRPC=m @@ -2017,6 +2037,7 @@ CONFIG_LWTUNNEL_BPF=y CONFIG_DST_CACHE=y CONFIG_GRO_CELLS=y CONFIG_SOCK_VALIDATE_XMIT=y +CONFIG_NET_IEEE8021Q_HELPERS=y CONFIG_NET_SELFTESTS=y CONFIG_NET_SOCK_MSG=y CONFIG_NET_DEVLINK=y @@ -2032,6 +2053,7 @@ CONFIG_ETHTOOL_NETLINK=y # CONFIG_ARM_AMBA=y CONFIG_HAVE_PCI=y +CONFIG_GENERIC_PCI_IOMAP=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y CONFIG_PCI_DOMAINS_GENERIC=y @@ -2150,7 +2172,6 @@ CONFIG_CXL_PORT=m CONFIG_CXL_SUSPEND=y CONFIG_CXL_REGION=y # CONFIG_CXL_REGION_INVALIDATION_TEST is not set -CONFIG_CXL_PMU=m # CONFIG_PCCARD is not set # CONFIG_RAPIDIO is not set @@ -2391,7 +2412,6 @@ CONFIG_MTD_PHYSMAP_OF=y # CONFIG_MTD_PHYSMAP_GEMINI is not set CONFIG_MTD_PHYSMAP_GPIO_ADDR=y CONFIG_MTD_PCI=m -# CONFIG_MTD_INTEL_VR_NOR is not set # CONFIG_MTD_PLATRAM is not set # end of Mapping drivers for chip access @@ -2479,10 +2499,12 @@ CONFIG_MTD_UBI_BEB_LIMIT=20 # CONFIG_MTD_UBI_FASTMAP is not set # CONFIG_MTD_UBI_GLUEBI is not set # CONFIG_MTD_UBI_BLOCK is not set +# CONFIG_MTD_UBI_NVMEM is not set CONFIG_MTD_HYPERBUS=m CONFIG_DTC=y CONFIG_OF=y # CONFIG_OF_UNITTEST is not set +# CONFIG_OF_KUNIT_TEST is not set CONFIG_OF_FLATTREE=y CONFIG_OF_EARLY_FLATTREE=y CONFIG_OF_KOBJ=y @@ -2641,6 +2663,7 @@ CONFIG_SCSI=y CONFIG_SCSI_DMA=y CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y +# CONFIG_SCSI_LIB_KUNIT_TEST is not set # # SCSI support type (disk, tape, CD-ROM) @@ -2655,6 +2678,7 @@ CONFIG_SCSI_ENCLOSURE=m CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_PROTO_TEST is not set # # SCSI Transports @@ -2903,6 +2927,7 @@ CONFIG_DM_LOG_WRITES=m CONFIG_DM_INTEGRITY=m CONFIG_DM_ZONED=m CONFIG_DM_AUDIT=y +# CONFIG_DM_VDO is not set CONFIG_TARGET_CORE=m CONFIG_TCM_IBLOCK=m CONFIG_TCM_FILEIO=m @@ -2953,6 +2978,7 @@ CONFIG_VXLAN=m CONFIG_GENEVE=m CONFIG_BAREUDP=m CONFIG_GTP=m +# CONFIG_PFCP is not set CONFIG_AMT=m CONFIG_MACSEC=m CONFIG_NETCONSOLE=y @@ -3032,10 +3058,8 @@ CONFIG_NET_DSA_XRS700X=m CONFIG_NET_DSA_XRS700X_I2C=m CONFIG_NET_DSA_XRS700X_MDIO=m CONFIG_NET_DSA_REALTEK=m -CONFIG_NET_DSA_REALTEK_MDIO=m -CONFIG_NET_DSA_REALTEK_SMI=m -CONFIG_NET_DSA_REALTEK_RTL8365MB=m -CONFIG_NET_DSA_REALTEK_RTL8366RB=m +# CONFIG_NET_DSA_REALTEK_MDIO is not set +# CONFIG_NET_DSA_REALTEK_SMI is not set CONFIG_NET_DSA_SMSC_LAN9303=m CONFIG_NET_DSA_SMSC_LAN9303_I2C=m CONFIG_NET_DSA_SMSC_LAN9303_MDIO=m @@ -3154,6 +3178,8 @@ CONFIG_NET_VENDOR_HUAWEI=y # CONFIG_HINIC is not set CONFIG_NET_VENDOR_I825XX=y CONFIG_NET_VENDOR_INTEL=y +CONFIG_LIBETH=m +CONFIG_LIBIE=m CONFIG_E100=m CONFIG_E1000=m CONFIG_E1000E=m @@ -3191,6 +3217,7 @@ CONFIG_OCTEONTX2_MBOX=m CONFIG_OCTEONTX2_PF=m CONFIG_OCTEONTX2_VF=m # CONFIG_OCTEON_EP is not set +# CONFIG_OCTEON_EP_VF is not set # CONFIG_PRESTERA is not set CONFIG_NET_VENDOR_MELLANOX=y CONFIG_MLX4_EN=m @@ -3339,7 +3366,6 @@ CONFIG_XILINX_EMACLITE=m CONFIG_XILINX_LL_TEMAC=m # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -CONFIG_NET_SB1000=y CONFIG_PHYLINK=y CONFIG_PHYLIB=y CONFIG_SWPHY=y @@ -3351,6 +3377,7 @@ CONFIG_SFP=m # # MII PHY device drivers # +# CONFIG_AIR_EN8811H_PHY is not set CONFIG_AMD_PHY=m CONFIG_ADIN_PHY=m CONFIG_ADIN1100_PHY=m @@ -3388,7 +3415,11 @@ CONFIG_NATIONAL_PHY=m CONFIG_NXP_C45_TJA11XX_PHY=m # CONFIG_NXP_TJA11XX_PHY is not set # CONFIG_NCN26000_PHY is not set +CONFIG_QCOM_NET_PHYLIB=m CONFIG_AT803X_PHY=m +# CONFIG_QCA83XX_PHY is not set +# CONFIG_QCA808X_PHY is not set +# CONFIG_QCA807X_PHY is not set CONFIG_QSEMI_PHY=m CONFIG_REALTEK_PHY=y # CONFIG_RENESAS_PHY is not set @@ -3408,6 +3439,8 @@ CONFIG_VITESSE_PHY=m # CONFIG_MICREL_KS8995MA is not set CONFIG_PSE_CONTROLLER=y CONFIG_PSE_REGULATOR=m +# CONFIG_PSE_PD692X0 is not set +# CONFIG_PSE_TPS23881 is not set CONFIG_CAN_DEV=m CONFIG_CAN_VCAN=m CONFIG_CAN_VXCAN=m @@ -3424,10 +3457,10 @@ CONFIG_CAN_C_CAN=m CONFIG_CAN_C_CAN_PLATFORM=m CONFIG_CAN_C_CAN_PCI=m CONFIG_CAN_CC770=m -CONFIG_CAN_CC770_ISA=m CONFIG_CAN_CC770_PLATFORM=m # CONFIG_CAN_CTUCANFD_PCI is not set # CONFIG_CAN_CTUCANFD_PLATFORM is not set +# CONFIG_CAN_ESD_402_PCI is not set # CONFIG_CAN_IFI_CANFD is not set CONFIG_CAN_M_CAN=m CONFIG_CAN_M_CAN_PCI=m @@ -3441,7 +3474,6 @@ CONFIG_CAN_KVASER_PCI=m CONFIG_CAN_PEAK_PCI=m CONFIG_CAN_PEAK_PCIEC=y CONFIG_CAN_PLX_PCI=m -CONFIG_CAN_SJA1000_ISA=m CONFIG_CAN_SJA1000_PLATFORM=m CONFIG_CAN_SOFTING=m @@ -3817,6 +3849,7 @@ CONFIG_RTLWIFI_PCI=m CONFIG_RTLWIFI_USB=m # CONFIG_RTLWIFI_DEBUG is not set CONFIG_RTL8192C_COMMON=m +CONFIG_RTL8192D_COMMON=m CONFIG_RTL8723_COMMON=m CONFIG_RTLBTCOEXIST=m CONFIG_RTL8XXXU=m @@ -3827,6 +3860,7 @@ CONFIG_RTW88_PCI=m CONFIG_RTW88_USB=m CONFIG_RTW88_8822B=m CONFIG_RTW88_8822C=m +CONFIG_RTW88_8723X=m CONFIG_RTW88_8723D=m CONFIG_RTW88_8821C=m CONFIG_RTW88_8822BE=m @@ -3837,6 +3871,7 @@ CONFIG_RTW88_8822CE=m CONFIG_RTW88_8822CU=m CONFIG_RTW88_8723DE=m # CONFIG_RTW88_8723DS is not set +# CONFIG_RTW88_8723CS is not set CONFIG_RTW88_8723DU=m CONFIG_RTW88_8821CE=m # CONFIG_RTW88_8821CS is not set @@ -3854,6 +3889,7 @@ CONFIG_RTW89_8851BE=m CONFIG_RTW89_8852AE=m CONFIG_RTW89_8852BE=m CONFIG_RTW89_8852CE=m +# CONFIG_RTW89_8922AE is not set # CONFIG_RTW89_DEBUGMSG is not set # CONFIG_RTW89_DEBUGFS is not set CONFIG_WLAN_VENDOR_RSI=y @@ -4093,6 +4129,8 @@ CONFIG_TOUCHSCREEN_EGALAX_SERIAL=m CONFIG_TOUCHSCREEN_EXC3000=m CONFIG_TOUCHSCREEN_FUJITSU=m CONFIG_TOUCHSCREEN_GOODIX=m +# CONFIG_TOUCHSCREEN_GOODIX_BERLIN_I2C is not set +# CONFIG_TOUCHSCREEN_GOODIX_BERLIN_SPI is not set CONFIG_TOUCHSCREEN_HIDEEP=m CONFIG_TOUCHSCREEN_HYCON_HY46XX=m # CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX is not set @@ -4247,7 +4285,6 @@ CONFIG_VT=y CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_VT_CONSOLE_SLEEP=y -CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y @@ -4302,9 +4339,8 @@ CONFIG_SERIAL_SIFIVE=m CONFIG_SERIAL_SCCNXP=y CONFIG_SERIAL_SCCNXP_CONSOLE=y CONFIG_SERIAL_SC16IS7XX_CORE=m -CONFIG_SERIAL_SC16IS7XX=m -CONFIG_SERIAL_SC16IS7XX_I2C=y -CONFIG_SERIAL_SC16IS7XX_SPI=y +CONFIG_SERIAL_SC16IS7XX_I2C=m +CONFIG_SERIAL_SC16IS7XX_SPI=m CONFIG_SERIAL_ALTERA_JTAGUART=m CONFIG_SERIAL_ALTERA_UART=m CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4 @@ -4367,6 +4403,7 @@ CONFIG_HW_RANDOM_CN10K=y CONFIG_DEVMEM=y CONFIG_DEVPORT=y CONFIG_TCG_TPM=y +# CONFIG_TCG_TPM2_HMAC is not set CONFIG_HW_RANDOM_TPM=y # CONFIG_TCG_TIS is not set # CONFIG_TCG_TIS_SPI is not set @@ -4442,6 +4479,7 @@ CONFIG_I2C_CCGX_UCSI=m # CONFIG_I2C_SIS96X is not set # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_ZHAOXIN is not set # # ACPI drivers @@ -4530,7 +4568,6 @@ CONFIG_SPI_MICROCHIP_CORE_QSPI=m CONFIG_SPI_OC_TINY=m # CONFIG_SPI_PCI1XXXX is not set CONFIG_SPI_PL022=y -# CONFIG_SPI_PXA2XX is not set CONFIG_SPI_ROCKCHIP=y CONFIG_SPI_ROCKCHIP_SFC=y # CONFIG_SPI_SC18IS602 is not set @@ -4585,6 +4622,7 @@ CONFIG_PTP_1588_CLOCK_INES=m CONFIG_PTP_1588_CLOCK_KVM=m CONFIG_PTP_1588_CLOCK_IDT82P33=m CONFIG_PTP_1588_CLOCK_IDTCM=m +# CONFIG_PTP_1588_CLOCK_FC3W is not set # CONFIG_PTP_1588_CLOCK_MOCK is not set CONFIG_PTP_1588_CLOCK_OCP=m # end of PTP clock support @@ -4597,12 +4635,14 @@ CONFIG_PINCONF=y CONFIG_GENERIC_PINCONF=y # CONFIG_DEBUG_PINCTRL is not set # CONFIG_PINCTRL_AMD is not set +# CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_CY8C95X0=m # CONFIG_PINCTRL_MCP23S08 is not set # CONFIG_PINCTRL_MICROCHIP_SGPIO is not set # CONFIG_PINCTRL_OCELOT is not set CONFIG_PINCTRL_RK805=m CONFIG_PINCTRL_ROCKCHIP=y +# CONFIG_PINCTRL_SCMI is not set CONFIG_PINCTRL_SINGLE=y CONFIG_PINCTRL_STMFX=m CONFIG_PINCTRL_SX150X=y @@ -4671,6 +4711,7 @@ CONFIG_GPIO_TPIC2810=m # # MFD GPIO expanders # +# CONFIG_GPIO_CROS_EC is not set # end of MFD GPIO expanders # @@ -4719,6 +4760,7 @@ CONFIG_W1_MASTER_DS2490=m CONFIG_W1_MASTER_DS2482=m CONFIG_W1_MASTER_GPIO=m CONFIG_W1_MASTER_SGI=m +# CONFIG_W1_MASTER_UART is not set # end of 1-wire Bus Masters # @@ -4840,10 +4882,12 @@ CONFIG_SENSORS_AHT10=m CONFIG_SENSORS_AQUACOMPUTER_D5NEXT=m CONFIG_SENSORS_AS370=m CONFIG_SENSORS_ASC7621=m +# CONFIG_SENSORS_ASUS_ROG_RYUJIN is not set CONFIG_SENSORS_AXI_FAN_CONTROL=m CONFIG_SENSORS_ARM_SCMI=m CONFIG_SENSORS_ARM_SCPI=m CONFIG_SENSORS_ATXP1=m +# CONFIG_SENSORS_CHIPCAP2 is not set # CONFIG_SENSORS_CORSAIR_CPRO is not set CONFIG_SENSORS_CORSAIR_PSU=m CONFIG_SENSORS_DRIVETEMP=m @@ -4883,6 +4927,7 @@ CONFIG_SENSORS_LTC4222=m CONFIG_SENSORS_LTC4245=m CONFIG_SENSORS_LTC4260=m CONFIG_SENSORS_LTC4261=m +# CONFIG_SENSORS_LTC4282 is not set CONFIG_SENSORS_MAX1111=m CONFIG_SENSORS_MAX127=m CONFIG_SENSORS_MAX16065=m @@ -4932,6 +4977,7 @@ CONFIG_SENSORS_NCT7802=m CONFIG_SENSORS_NCT7904=m CONFIG_SENSORS_NPCM7XX=m CONFIG_SENSORS_NZXT_KRAKEN2=m +# CONFIG_SENSORS_NZXT_KRAKEN3 is not set # CONFIG_SENSORS_NZXT_SMART2 is not set CONFIG_SENSORS_OCC_P8_I2C=m CONFIG_SENSORS_OCC=m @@ -4941,6 +4987,7 @@ CONFIG_SENSORS_PMBUS=m # CONFIG_SENSORS_ACBEL_FSG032 is not set # CONFIG_SENSORS_ADM1266 is not set CONFIG_SENSORS_ADM1275=m +# CONFIG_SENSORS_ADP1050 is not set CONFIG_SENSORS_BEL_PFE=m CONFIG_SENSORS_BPA_RS600=m # CONFIG_SENSORS_DELTA_AHE50DC_FAN is not set @@ -4975,6 +5022,7 @@ CONFIG_SENSORS_MP2888=m # CONFIG_SENSORS_MP5023 is not set # CONFIG_SENSORS_MP5990 is not set # CONFIG_SENSORS_MPQ7932 is not set +# CONFIG_SENSORS_MPQ8785 is not set CONFIG_SENSORS_PIM4328=m # CONFIG_SENSORS_PLI1209BC is not set CONFIG_SENSORS_PM6764TR=m @@ -4987,10 +5035,12 @@ CONFIG_SENSORS_TPS53679=m CONFIG_SENSORS_TPS546D24=m CONFIG_SENSORS_UCD9000=m CONFIG_SENSORS_UCD9200=m +# CONFIG_SENSORS_XDP710 is not set CONFIG_SENSORS_XDPE152=m CONFIG_SENSORS_XDPE122=m # CONFIG_SENSORS_XDPE122_REGULATOR is not set CONFIG_SENSORS_ZL6100=m +# CONFIG_SENSORS_PT5161L is not set CONFIG_SENSORS_PWM_FAN=m CONFIG_SENSORS_SBTSI=m CONFIG_SENSORS_SBRMI=m @@ -5057,7 +5107,6 @@ CONFIG_THERMAL_STATISTICS=y CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 CONFIG_THERMAL_HWMON=y CONFIG_THERMAL_OF=y -CONFIG_THERMAL_WRITABLE_TRIPS=y CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y # CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set # CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set @@ -5093,6 +5142,7 @@ CONFIG_WATCHDOG_SYSFS=y # Watchdog Device Drivers # CONFIG_SOFT_WATCHDOG=m +# CONFIG_CROS_EC_WATCHDOG is not set CONFIG_GPIO_WATCHDOG=m CONFIG_WDAT_WDT=m # CONFIG_XILINX_WATCHDOG is not set @@ -6335,12 +6385,13 @@ CONFIG_DVB_DUMMY_FE=m # Graphics support # CONFIG_APERTURE_HELPERS=y -CONFIG_VIDEO_CMDLINE=y -CONFIG_VIDEO_NOMODESET=y +CONFIG_SCREEN_INFO=y +CONFIG_VIDEO=y # CONFIG_AUXDISPLAY is not set CONFIG_DRM=m CONFIG_DRM_MIPI_DBI=m CONFIG_DRM_MIPI_DSI=y +# CONFIG_DRM_DEBUG_MM is not set CONFIG_DRM_KUNIT_TEST_HELPERS=m CONFIG_DRM_KUNIT_TEST=m CONFIG_DRM_KMS_HELPER=m @@ -6350,13 +6401,13 @@ CONFIG_DRM_FBDEV_EMULATION=y CONFIG_DRM_FBDEV_OVERALLOC=100 # CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set CONFIG_DRM_LOAD_EDID_FIRMWARE=y -CONFIG_DRM_DP_AUX_BUS=m CONFIG_DRM_DISPLAY_HELPER=m +CONFIG_DRM_DISPLAY_DP_AUX_BUS=m +# CONFIG_DRM_DISPLAY_DP_AUX_CEC is not set +# CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV is not set CONFIG_DRM_DISPLAY_DP_HELPER=y CONFIG_DRM_DISPLAY_HDCP_HELPER=y CONFIG_DRM_DISPLAY_HDMI_HELPER=y -# CONFIG_DRM_DP_AUX_CHARDEV is not set -CONFIG_DRM_DP_CEC=y CONFIG_DRM_TTM=m CONFIG_DRM_EXEC=m CONFIG_DRM_GPUVM=m @@ -6420,15 +6471,15 @@ CONFIG_DRM_PANEL_ARM_VERSATILE=m # CONFIG_DRM_PANEL_AUO_A030JTN01 is not set # CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0 is not set CONFIG_DRM_PANEL_BOE_HIMAX8279D=m +# CONFIG_DRM_PANEL_BOE_TH101MB31UIG002_28A is not set CONFIG_DRM_PANEL_BOE_TV101WUM_NL6=m -CONFIG_DRM_PANEL_DSI_CM=m -CONFIG_DRM_PANEL_LVDS=m -CONFIG_DRM_PANEL_SIMPLE=m -CONFIG_DRM_PANEL_EDP=m # CONFIG_DRM_PANEL_EBBG_FT8719 is not set CONFIG_DRM_PANEL_ELIDA_KD35T133=m CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02=m CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D=m +CONFIG_DRM_PANEL_DSI_CM=m +CONFIG_DRM_PANEL_LVDS=m +# CONFIG_DRM_PANEL_HIMAX_HX83112A is not set # CONFIG_DRM_PANEL_HIMAX_HX8394 is not set CONFIG_DRM_PANEL_ILITEK_IL9322=m CONFIG_DRM_PANEL_ILITEK_ILI9341=m @@ -6438,17 +6489,18 @@ CONFIG_DRM_PANEL_ILITEK_ILI9881C=m CONFIG_DRM_PANEL_INNOLUX_EJ030NA=m CONFIG_DRM_PANEL_INNOLUX_P079ZCA=m # CONFIG_DRM_PANEL_JADARD_JD9365DA_H3 is not set -CONFIG_DRM_PANEL_JDI_LT070ME05000=m # CONFIG_DRM_PANEL_JDI_LPM102A188A is not set +CONFIG_DRM_PANEL_JDI_LT070ME05000=m # CONFIG_DRM_PANEL_JDI_R63452 is not set CONFIG_DRM_PANEL_KHADAS_TS050=m CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04=m # CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W is not set CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829=m -# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set CONFIG_DRM_PANEL_LG_LB035Q02=m # CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_LG_SW43408 is not set # CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966 is not set +# CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set CONFIG_DRM_PANEL_NEC_NL8048HL11=m # CONFIG_DRM_PANEL_NEWVISION_NV3051D is not set CONFIG_DRM_PANEL_NEWVISION_NV3052C=m @@ -6457,8 +6509,8 @@ CONFIG_DRM_PANEL_NOVATEK_NT35560=m # CONFIG_DRM_PANEL_NOVATEK_NT35950 is not set # CONFIG_DRM_PANEL_NOVATEK_NT36523 is not set CONFIG_DRM_PANEL_NOVATEK_NT36672A=m +# CONFIG_DRM_PANEL_NOVATEK_NT36672E is not set CONFIG_DRM_PANEL_NOVATEK_NT39016=m -# CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO=m # CONFIG_DRM_PANEL_ORISETECH_OTA5601A is not set CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m @@ -6468,16 +6520,19 @@ CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m CONFIG_DRM_PANEL_RAYDIUM_RM67191=m CONFIG_DRM_PANEL_RAYDIUM_RM68200=m # CONFIG_DRM_PANEL_RAYDIUM_RM692E5 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM69380 is not set CONFIG_DRM_PANEL_RONBO_RB070D30=m +CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01=m CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20=m CONFIG_DRM_PANEL_SAMSUNG_DB7430=m +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E3FA7 is not set CONFIG_DRM_PANEL_SAMSUNG_S6D16D0=m CONFIG_DRM_PANEL_SAMSUNG_S6D27A1=m # CONFIG_DRM_PANEL_SAMSUNG_S6D7AA0 is not set CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2=m CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=m # CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set -CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01=m # CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set CONFIG_DRM_PANEL_SAMSUNG_SOFEF00=m CONFIG_DRM_PANEL_SEIKO_43WVF1G=m @@ -6488,19 +6543,21 @@ CONFIG_DRM_PANEL_SHARP_LS060T1SX01=m CONFIG_DRM_PANEL_SITRONIX_ST7701=m # CONFIG_DRM_PANEL_SITRONIX_ST7703 is not set # CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set -# CONFIG_DRM_PANEL_SYNAPTICS_R63353 is not set CONFIG_DRM_PANEL_SONY_ACX565AKM=m # CONFIG_DRM_PANEL_SONY_TD4353_JDI is not set # CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521 is not set # CONFIG_DRM_PANEL_STARTEK_KD070FHFID015 is not set +CONFIG_DRM_PANEL_EDP=m +CONFIG_DRM_PANEL_SIMPLE=m +# CONFIG_DRM_PANEL_SYNAPTICS_R63353 is not set CONFIG_DRM_PANEL_TDO_TL070WSH30=m CONFIG_DRM_PANEL_TPO_TD028TTEC1=m CONFIG_DRM_PANEL_TPO_TD043MTEA1=m CONFIG_DRM_PANEL_TPO_TPG110=m CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m +# CONFIG_DRM_PANEL_VISIONOX_R66451 is not set # CONFIG_DRM_PANEL_VISIONOX_RM69299 is not set # CONFIG_DRM_PANEL_VISIONOX_VTDR6130 is not set -# CONFIG_DRM_PANEL_VISIONOX_R66451 is not set CONFIG_DRM_PANEL_WIDECHIPS_WS2401=m CONFIG_DRM_PANEL_XINPENG_XPP055C272=m # end of Display Panels @@ -6594,8 +6651,9 @@ CONFIG_DRM_SSD130X_I2C=m CONFIG_DRM_SSD130X_SPI=m # CONFIG_DRM_POWERVR is not set CONFIG_DRM_EXPORT_FOR_TESTS=y -CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y CONFIG_DRM_LIB_RANDOM=y +# CONFIG_DRM_WERROR is not set +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y # # Frame buffer Devices @@ -6680,6 +6738,7 @@ CONFIG_LCD_PLATFORM=m CONFIG_LCD_OTM3225A=m CONFIG_BACKLIGHT_CLASS_DEVICE=y # CONFIG_BACKLIGHT_KTD253 is not set +# CONFIG_BACKLIGHT_KTD2801 is not set # CONFIG_BACKLIGHT_KTZ8866 is not set CONFIG_BACKLIGHT_PWM=m CONFIG_BACKLIGHT_MT6370=m @@ -6730,6 +6789,7 @@ CONFIG_SND_DMAENGINE_PCM=m CONFIG_SND_HWDEP=m CONFIG_SND_SEQ_DEVICE=m CONFIG_SND_RAWMIDI=m +# CONFIG_SND_CORE_TEST is not set CONFIG_SND_COMPRESS_OFFLOAD=m CONFIG_SND_JACK=y CONFIG_SND_JACK_INPUT_DEV=y @@ -6856,6 +6916,7 @@ CONFIG_SND_HDA_PATCH_LOADER=y # CONFIG_SND_HDA_CIRRUS_SCODEC_KUNIT_TEST is not set CONFIG_SND_HDA_SCODEC_CS35L41=m CONFIG_SND_HDA_CS_DSP_CONTROLS=m +CONFIG_SND_HDA_SCODEC_COMPONENT=m CONFIG_SND_HDA_SCODEC_CS35L41_I2C=m CONFIG_SND_HDA_SCODEC_CS35L41_SPI=m # CONFIG_SND_HDA_SCODEC_CS35L56_I2C is not set @@ -6908,6 +6969,7 @@ CONFIG_SND_SOC_AC97_BUS=y CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y CONFIG_SND_SOC_COMPRESS=y # CONFIG_SND_SOC_TOPOLOGY_BUILD is not set +# CONFIG_SND_SOC_CARD_KUNIT_TEST is not set CONFIG_SND_SOC_UTILS_KUNIT_TEST=m CONFIG_SND_SOC_ACPI=m CONFIG_SND_SOC_ADI=m @@ -7021,6 +7083,8 @@ CONFIG_SND_SOC_BD28623=m CONFIG_SND_SOC_BT_SCO=m # CONFIG_SND_SOC_CHV3_CODEC is not set CONFIG_SND_SOC_CROS_EC_CODEC=m +CONFIG_SND_SOC_CS_AMP_LIB=m +# CONFIG_SND_SOC_CS_AMP_LIB_TEST is not set CONFIG_SND_SOC_CS35L32=m CONFIG_SND_SOC_CS35L33=m CONFIG_SND_SOC_CS35L34=m @@ -7110,7 +7174,9 @@ CONFIG_SND_SOC_PCM5102A=m CONFIG_SND_SOC_PCM512x=m CONFIG_SND_SOC_PCM512x_I2C=m CONFIG_SND_SOC_PCM512x_SPI=m +# CONFIG_SND_SOC_PCM6240 is not set # CONFIG_SND_SOC_PEB2466 is not set +# CONFIG_SND_SOC_RK3308 is not set CONFIG_SND_SOC_RK3328=m # CONFIG_SND_SOC_RK817 is not set CONFIG_SND_SOC_RL6231=m @@ -7197,6 +7263,7 @@ CONFIG_SND_SOC_WCD9335=m CONFIG_SND_SOC_WCD_MBHC=m CONFIG_SND_SOC_WCD938X=m CONFIG_SND_SOC_WCD938X_SDW=m +# CONFIG_SND_SOC_WCD939X_SDW is not set CONFIG_SND_SOC_WM8510=m CONFIG_SND_SOC_WM8523=m CONFIG_SND_SOC_WM8524=m @@ -7387,6 +7454,7 @@ CONFIG_HID_UDRAW_PS3=m CONFIG_HID_U2FZERO=m CONFIG_HID_WACOM=m CONFIG_HID_WIIMOTE=m +# CONFIG_HID_WINWING is not set CONFIG_HID_XINMO=m CONFIG_HID_ZEROPLUS=m CONFIG_ZEROPLUS_FF=y @@ -7442,6 +7510,7 @@ CONFIG_USB_OTG=y CONFIG_USB_OTG_FSM=m CONFIG_USB_LEDS_TRIGGER_USBPORT=y CONFIG_USB_AUTOSUSPEND_DELAY=2 +CONFIG_USB_DEFAULT_AUTHORIZATION_MODE=1 CONFIG_USB_MON=m # @@ -7672,7 +7741,7 @@ CONFIG_USB_HSIC_USB3503=y CONFIG_USB_HSIC_USB4604=m CONFIG_USB_LINK_LAYER_TEST=m CONFIG_USB_CHAOSKEY=m -CONFIG_USB_ONBOARD_HUB=m +# CONFIG_USB_ONBOARD_DEV is not set CONFIG_USB_ATM=m CONFIG_USB_SPEEDTOUCH=m CONFIG_USB_CXACRU=m @@ -7826,6 +7895,7 @@ CONFIG_TYPEC_WUSB3801=m CONFIG_TYPEC_MUX_FSA4480=m # CONFIG_TYPEC_MUX_GPIO_SBU is not set CONFIG_TYPEC_MUX_PI3USB30532=m +# CONFIG_TYPEC_MUX_IT5205 is not set # CONFIG_TYPEC_MUX_NB7VPQ904M is not set # CONFIG_TYPEC_MUX_PTN36502 is not set # CONFIG_TYPEC_MUX_WCD939X_USBSS is not set @@ -7875,6 +7945,7 @@ CONFIG_MMC_DW_PLTFM=y CONFIG_MMC_DW_BLUEFIELD=m CONFIG_MMC_DW_EXYNOS=y CONFIG_MMC_DW_HI3798CV200=y +# CONFIG_MMC_DW_HI3798MV200 is not set CONFIG_MMC_DW_K3=y # CONFIG_MMC_DW_PCI is not set CONFIG_MMC_DW_ROCKCHIP=y @@ -7922,8 +7993,6 @@ CONFIG_LEDS_LM3692X=m CONFIG_LEDS_GPIO=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP3952 is not set -# CONFIG_LEDS_LP50XX is not set -# CONFIG_LEDS_LP55XX_COMMON is not set # CONFIG_LEDS_LP8860 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA963X is not set @@ -7990,7 +8059,6 @@ CONFIG_LEDS_TRIGGER_CAMERA=m CONFIG_LEDS_TRIGGER_PANIC=y CONFIG_LEDS_TRIGGER_NETDEV=m CONFIG_LEDS_TRIGGER_PATTERN=m -CONFIG_LEDS_TRIGGER_AUDIO=m CONFIG_LEDS_TRIGGER_TTY=m # @@ -8054,6 +8122,7 @@ CONFIG_RTC_DRV_RK808=m # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_RX8010 is not set +# CONFIG_RTC_DRV_RX8111 is not set # CONFIG_RTC_DRV_RX8581 is not set # CONFIG_RTC_DRV_RX8025 is not set # CONFIG_RTC_DRV_EM3027 is not set @@ -8188,7 +8257,6 @@ CONFIG_UIO_AEC=m CONFIG_UIO_SERCOS3=m CONFIG_UIO_PCI_GENERIC=m # CONFIG_UIO_NETX is not set -# CONFIG_UIO_PRUSS is not set # CONFIG_UIO_MF624 is not set CONFIG_VFIO=y CONFIG_VFIO_GROUP=y @@ -8207,6 +8275,7 @@ CONFIG_VFIO_PCI_INTX=y CONFIG_VFIO_PCI=y CONFIG_MLX5_VFIO_PCI=m # CONFIG_HISI_ACC_VFIO_PCI is not set +# CONFIG_NVGRACE_GPU_VFIO_PCI is not set # end of VFIO support for PCI devices # @@ -8233,6 +8302,7 @@ CONFIG_VIRTIO_INPUT=m CONFIG_VIRTIO_MMIO=y # CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set CONFIG_VIRTIO_DMA_SHARED_BUFFER=m +# CONFIG_VIRTIO_DEBUG is not set CONFIG_VDPA=m CONFIG_VDPA_SIM=m CONFIG_VDPA_SIM_NET=m @@ -8291,7 +8361,6 @@ CONFIG_XEN_FRONT_PGDIR_SHBUF=m # CONFIG_GREYBUS is not set # CONFIG_COMEDI is not set CONFIG_STAGING=y -# CONFIG_PRISM2_USB is not set CONFIG_RTLLIB=m CONFIG_RTLLIB_CRYPTO_CCMP=m CONFIG_RTLLIB_CRYPTO_TKIP=m @@ -8358,7 +8427,6 @@ CONFIG_STAGING_MEDIA_DEPRECATED=y # # Atmel media platform drivers # -# CONFIG_STAGING_BOARD is not set # CONFIG_LTE_GDM724X is not set CONFIG_FB_TFT=m CONFIG_FB_TFT_AGM1264K_FL=m @@ -8394,7 +8462,6 @@ CONFIG_FB_TFT_UC1701=m CONFIG_FB_TFT_UPD161704=m # CONFIG_MOST_COMPONENTS is not set # CONFIG_KS7010 is not set -# CONFIG_PI433 is not set # CONFIG_XIL_AXIS_FIFO is not set CONFIG_FIELDBUS_DEV=m CONFIG_HMS_ANYBUSS_BUS=m @@ -8432,6 +8499,8 @@ CONFIG_SURFACE_PLATFORMS=y # CONFIG_SURFACE_HOTPLUG is not set # CONFIG_SURFACE_PRO3_BUTTON is not set # CONFIG_SURFACE_AGGREGATOR is not set +CONFIG_ARM64_PLATFORM_DEVICES=y +# CONFIG_EC_ACER_ASPIRE1 is not set CONFIG_HAVE_CLK=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -8500,6 +8569,7 @@ CONFIG_ARM64_ERRATUM_858921=y CONFIG_MAILBOX=y CONFIG_ARM_MHU=y CONFIG_ARM_MHU_V2=m +# CONFIG_ARM_MHU_V3 is not set CONFIG_PLATFORM_MHU=y # CONFIG_PL320_MBOX is not set CONFIG_ROCKCHIP_MBOX=y @@ -8529,6 +8599,7 @@ CONFIG_IOMMU_DEFAULT_DMA_STRICT=y CONFIG_OF_IOMMU=y CONFIG_IOMMU_DMA=y CONFIG_IOMMU_SVA=y +CONFIG_IOMMU_IOPF=y # CONFIG_IOMMUFD is not set CONFIG_ROCKCHIP_IOMMU=y CONFIG_ARM_SMMU=y @@ -8536,6 +8607,7 @@ CONFIG_ARM_SMMU=y CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y CONFIG_ARM_SMMU_V3=y CONFIG_ARM_SMMU_V3_SVA=y +# CONFIG_ARM_SMMU_V3_KUNIT_TEST is not set CONFIG_VIRTIO_IOMMU=m # @@ -8613,6 +8685,7 @@ CONFIG_LITEX_SOC_CONTROLLER=m # CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set # CONFIG_QCOM_PMIC_GLINK is not set CONFIG_QCOM_QMI_HELPERS=m +# CONFIG_QCOM_PBS is not set # end of Qualcomm SoC drivers CONFIG_ROCKCHIP_GRF=y @@ -8734,6 +8807,7 @@ CONFIG_BMC150_ACCEL=m CONFIG_BMC150_ACCEL_I2C=m CONFIG_BMC150_ACCEL_SPI=m CONFIG_BMI088_ACCEL=m +CONFIG_BMI088_ACCEL_I2C=m CONFIG_BMI088_ACCEL_SPI=m CONFIG_DA280=m CONFIG_DA311=m @@ -8781,6 +8855,7 @@ CONFIG_AD7091R=m CONFIG_AD7091R5=m # CONFIG_AD7091R8 is not set CONFIG_AD7124=m +# CONFIG_AD7173 is not set # CONFIG_AD7192 is not set CONFIG_AD7266=m # CONFIG_AD7280 is not set @@ -8798,8 +8873,10 @@ CONFIG_AD7791=m CONFIG_AD7793=m CONFIG_AD7887=m CONFIG_AD7923=m +# CONFIG_AD7944 is not set CONFIG_AD7949=m CONFIG_AD799X=m +# CONFIG_AD9467 is not set # CONFIG_ADI_AXI_ADC is not set # CONFIG_CC10001_ADC is not set # CONFIG_ENVELOPE_DETECTOR is not set @@ -8826,6 +8903,7 @@ CONFIG_MCP3422=m CONFIG_MCP3911=m # CONFIG_MEDIATEK_MT6370_ADC is not set # CONFIG_NAU7802 is not set +# CONFIG_PAC1934 is not set # CONFIG_QCOM_SPMI_IADC is not set # CONFIG_QCOM_SPMI_VADC is not set # CONFIG_QCOM_SPMI_ADC5 is not set @@ -8842,6 +8920,7 @@ CONFIG_TI_ADC161S626=m CONFIG_TI_ADS1015=m # CONFIG_TI_ADS7924 is not set # CONFIG_TI_ADS1100 is not set +# CONFIG_TI_ADS1298 is not set CONFIG_TI_ADS7950=m CONFIG_TI_ADS8344=m CONFIG_TI_ADS8688=m @@ -8948,6 +9027,8 @@ CONFIG_IIO_ST_SENSORS_CORE=m # CONFIG_AD5593R is not set # CONFIG_AD5504 is not set # CONFIG_AD5624R_SPI is not set +# CONFIG_AD9739A is not set +# CONFIG_ADI_AXI_DAC is not set # CONFIG_LTC2688 is not set CONFIG_AD5686=m CONFIG_AD5686_SPI=m @@ -9011,6 +9092,7 @@ CONFIG_AD9523=m # CONFIG_ADF4350 is not set CONFIG_ADF4371=m # CONFIG_ADF4377 is not set +# CONFIG_ADMFM2000 is not set # CONFIG_ADMV1013 is not set # CONFIG_ADMV1014 is not set # CONFIG_ADMV4420 is not set @@ -9112,6 +9194,7 @@ CONFIG_ADUX1020=m CONFIG_AL3010=m CONFIG_AL3320A=m CONFIG_APDS9300=m +# CONFIG_APDS9306 is not set CONFIG_APDS9960=m # CONFIG_AS73211 is not set CONFIG_BH1750=m @@ -9170,6 +9253,7 @@ CONFIG_ZOPT2201=m # # Magnetometer sensors # +# CONFIG_AF8133J is not set CONFIG_AK8974=m CONFIG_AK8975=m CONFIG_AK09911=m @@ -9205,6 +9289,7 @@ CONFIG_HID_SENSOR_INCLINOMETER_3D=m CONFIG_HID_SENSOR_DEVICE_ROTATION=m # end of Inclinometer sensors +# CONFIG_IIO_GTS_KUNIT_TEST is not set CONFIG_IIO_FORMAT_KUNIT_TEST=m # @@ -9328,7 +9413,6 @@ CONFIG_MAX31865=m # CONFIG_NTB is not set CONFIG_PWM=y -CONFIG_PWM_SYSFS=y # CONFIG_PWM_DEBUG is not set CONFIG_PWM_ATMEL_TCB=m CONFIG_PWM_CLK=m @@ -9359,6 +9443,7 @@ CONFIG_PARTITION_PERCPU=y # CONFIG_IPACK_BUS is not set CONFIG_ARCH_HAS_RESET_CONTROLLER=y CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_GPIO is not set CONFIG_RESET_SCMI=y # CONFIG_RESET_SIMPLE is not set # CONFIG_RESET_TI_SYSCON is not set @@ -9432,6 +9517,7 @@ CONFIG_HISI_PMU=y CONFIG_HNS3_PMU=m # CONFIG_DWC_PCIE_PMU is not set # CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU is not set +CONFIG_CXL_PMU=m # end of Performance monitor support CONFIG_RAS=y @@ -9481,6 +9567,7 @@ CONFIG_FPGA=y # CONFIG_ALTERA_PR_IP_CORE is not set # CONFIG_FPGA_MGR_ALTERA_PS_SPI is not set # CONFIG_FPGA_MGR_ALTERA_CVP is not set +# CONFIG_FPGA_MGR_XILINX_SELECTMAP is not set # CONFIG_FPGA_MGR_XILINX_SPI is not set # CONFIG_FPGA_MGR_ICE40_SPI is not set # CONFIG_FPGA_MGR_MACHXO2_SPI is not set @@ -9496,6 +9583,7 @@ CONFIG_FPGA_MGR_MICROCHIP_SPI=m CONFIG_TEE=y CONFIG_OPTEE=y # CONFIG_OPTEE_INSECURE_LOAD_IMAGE is not set +# CONFIG_ARM_TSTEE is not set CONFIG_MULTIPLEXER=y # @@ -9633,6 +9721,7 @@ CONFIG_AUTOFS_FS=m CONFIG_FUSE_FS=y CONFIG_CUSE=m CONFIG_VIRTIO_FS=m +CONFIG_FUSE_PASSTHROUGH=y CONFIG_OVERLAY_FS=y # CONFIG_OVERLAY_FS_REDIRECT_DIR is not set CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y @@ -9676,13 +9765,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="utf8" # CONFIG_FAT_KUNIT_TEST is not set CONFIG_EXFAT_FS=y CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" -CONFIG_NTFS_FS=y -# CONFIG_NTFS_DEBUG is not set -CONFIG_NTFS_RW=y CONFIG_NTFS3_FS=y # CONFIG_NTFS3_64BIT_CLUSTER is not set CONFIG_NTFS3_LZX_XPRESS=y CONFIG_NTFS3_FS_POSIX_ACL=y +CONFIG_NTFS_FS=y # end of DOS/FAT/EXFAT/NT Filesystems # @@ -9944,6 +10031,7 @@ CONFIG_KEYS=y CONFIG_KEYS_REQUEST_CACHE=y CONFIG_PERSISTENT_KEYRINGS=y CONFIG_TRUSTED_KEYS=y +CONFIG_HAVE_TRUSTED_KEYS=y CONFIG_TRUSTED_KEYS_TPM=y CONFIG_TRUSTED_KEYS_TEE=y CONFIG_ENCRYPTED_KEYS=y @@ -10042,9 +10130,15 @@ CONFIG_LSM="lockdown,yama,integrity,apparmor" # # Memory initialization # +CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y +CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_BARE=y +CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y CONFIG_INIT_STACK_NONE=y +# CONFIG_INIT_STACK_ALL_PATTERN is not set +# CONFIG_INIT_STACK_ALL_ZERO is not set CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y # CONFIG_INIT_ON_FREE_DEFAULT_ON is not set +# CONFIG_INIT_MLOCKED_ON_FREE_DEFAULT_ON is not set CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y # CONFIG_ZERO_CALL_USED_REGS is not set # end of Memory initialization @@ -10246,7 +10340,6 @@ CONFIG_CRYPTO_USER_API_RNG=m # CONFIG_CRYPTO_USER_API_RNG_CAVP is not set CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE=y -# CONFIG_CRYPTO_STATS is not set # end of Userspace interface CONFIG_CRYPTO_HASH_INFO=y @@ -10352,7 +10445,6 @@ CONFIG_GENERIC_NET_UTILS=y CONFIG_CORDIC=m CONFIG_PRIME_NUMBERS=m CONFIG_RATIONAL=y -CONFIG_GENERIC_PCI_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y @@ -10457,13 +10549,13 @@ CONFIG_NEED_DMA_MAP_STATE=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y CONFIG_DMA_DECLARE_COHERENT=y CONFIG_ARCH_HAS_SETUP_DMA_OPS=y -CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS=y CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y CONFIG_SWIOTLB=y # CONFIG_SWIOTLB_DYNAMIC is not set CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_NEED_SYNC=y CONFIG_DMA_RESTRICTED_POOL=y CONFIG_DMA_NONCOHERENT_MMAP=y CONFIG_DMA_COHERENT_POOL=y @@ -10590,7 +10682,7 @@ CONFIG_DEBUG_FS_ALLOW_ALL=y # CONFIG_DEBUG_FS_ALLOW_NONE is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set -CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y +CONFIG_ARCH_HAS_UBSAN=y # CONFIG_UBSAN is not set CONFIG_HAVE_ARCH_KCSAN=y CONFIG_HAVE_KCSAN_COMPILER=y @@ -10635,6 +10727,7 @@ CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y # CONFIG_DEBUG_VIRTUAL is not set CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_MEM_ALLOC_PROFILING is not set CONFIG_HAVE_ARCH_KASAN=y CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y CONFIG_HAVE_ARCH_KASAN_HW_TAGS=y @@ -10728,6 +10821,7 @@ CONFIG_RCU_TRACE=y # CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set # CONFIG_LATENCYTOP is not set # CONFIG_DEBUG_CGROUP_REF is not set +CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y @@ -10805,6 +10899,7 @@ CONFIG_FUNCTION_ERROR_INJECTION=y # CONFIG_FAULT_INJECTION is not set CONFIG_ARCH_HAS_KCOV=y CONFIG_CC_HAS_SANCOV_TRACE_PC=y +# CONFIG_KCOV is not set CONFIG_RUNTIME_TESTING_MENU=y # CONFIG_TEST_DHRY is not set # CONFIG_LKDTM is not set @@ -10824,8 +10919,8 @@ CONFIG_REED_SOLOMON_TEST=m # CONFIG_ATOMIC64_SELFTEST is not set CONFIG_ASYNC_RAID6_TEST=m # CONFIG_TEST_HEXDUMP is not set -# CONFIG_STRING_SELFTEST is not set -# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_STRING_KUNIT_TEST is not set +# CONFIG_STRING_HELPERS_KUNIT_TEST is not set # CONFIG_TEST_KSTRTOX is not set # CONFIG_TEST_PRINTF is not set CONFIG_TEST_SCANF=m @@ -10857,13 +10952,10 @@ CONFIG_CMDLINE_KUNIT_TEST=m CONFIG_SLUB_KUNIT_TEST=m CONFIG_RATIONAL_KUNIT_TEST=m CONFIG_MEMCPY_KUNIT_TEST=m -CONFIG_MEMCPY_SLOW_KUNIT_TEST=y # CONFIG_IS_SIGNED_TYPE_KUNIT_TEST is not set # CONFIG_OVERFLOW_KUNIT_TEST is not set # CONFIG_STACKINIT_KUNIT_TEST is not set # CONFIG_FORTIFY_KUNIT_TEST is not set -# CONFIG_STRCAT_KUNIT_TEST is not set -# CONFIG_STRSCPY_KUNIT_TEST is not set # CONFIG_SIPHASH_KUNIT_TEST is not set # CONFIG_TEST_UDELAY is not set # CONFIG_TEST_STATIC_KEYS is not set @@ -10872,6 +10964,7 @@ CONFIG_MEMCPY_SLOW_KUNIT_TEST=y CONFIG_TEST_MEMCAT_P=m # CONFIG_TEST_MEMINIT is not set # CONFIG_TEST_FREE_PAGES is not set +# CONFIG_TEST_FPU is not set # CONFIG_TEST_OBJPOOL is not set CONFIG_ARCH_USE_MEMTEST=y CONFIG_MEMTEST=y diff --git a/config/sources/families/rockchip-rk3588.conf b/config/sources/families/rockchip-rk3588.conf index e8aed6de8fc6..0c6436e7c926 100644 --- a/config/sources/families/rockchip-rk3588.conf +++ b/config/sources/families/rockchip-rk3588.conf @@ -42,7 +42,7 @@ case $BRANCH in edge) LINUXFAMILY=rockchip-rk3588 LINUXCONFIG='linux-rockchip-rk3588-'$BRANCH - KERNEL_MAJOR_MINOR="6.8" # Major and minor versions of this kernel. + KERNEL_MAJOR_MINOR="6.10" # Major and minor versions of this kernel. KERNELPATCHDIR='rockchip-rk3588-edge' ;; diff --git a/config/sources/mainline-kernel.conf.sh b/config/sources/mainline-kernel.conf.sh index f9392a440869..d8c2a62200c0 100644 --- a/config/sources/mainline-kernel.conf.sh +++ b/config/sources/mainline-kernel.conf.sh @@ -8,7 +8,7 @@ function mainline_kernel_decide_version__upstream_release_candidate_number() { [[ -n "${KERNELBRANCH}" ]] && return 0 # if already set, don't touch it; that way other hooks can run in any order if [[ "${KERNEL_MAJOR_MINOR}" == "6.10" ]]; then # @TODO: roll over to next MAJOR.MINOR and MAJOR.MINOR-rc1 when it is released - declare -g KERNELBRANCH="tag:v6.10-rc1" + declare -g KERNELBRANCH="tag:v6.10-rc2" display_alert "mainline-kernel: upstream release candidate" "Using KERNELBRANCH='${KERNELBRANCH}' for KERNEL_MAJOR_MINOR='${KERNEL_MAJOR_MINOR}'" "info" fi } diff --git a/patch/kernel/rockchip-rk3588-edge/0000.patching_config.yaml b/patch/kernel/rockchip-rk3588-edge/0000.patching_config.yaml index 742379d54b3b..6815f3cc8af9 100644 --- a/patch/kernel/rockchip-rk3588-edge/0000.patching_config.yaml +++ b/patch/kernel/rockchip-rk3588-edge/0000.patching_config.yaml @@ -2,20 +2,22 @@ config: # This is file 'patch/kernel/rockchip-rk3588-edge/0000.patching_config.y # PATCH NUMBERING INFO # + # Patches should be ordered in such a way that general kernel patches are applied first, then SoC-related patches and at last board-specific patches + # # Patch numbers in this folder are sorted by category: # # 000* for general patches # 01** for GPU/HDMI related patches # 08** for wireless patches - # 1*** for board patches - # 101* for Rock-5B, 1012* for Rock-5A and so on + # 1*** for board specific patches: + # 101* for Rock-5B, 102* for Rock-5A and so on # Just some info stuff; not used by the patching scripts name: rockchip-rk3588-edge kind: kernel type: mainline # or: vendor - branch: linux-6.8.y - last-known-good-tag: v6.8.3 + branch: linux-6.10.y + last-known-good-tag: v6.10-rc2 maintainers: - { github: rpardini, name: Ricardo Pardini, email: ricardo@pardini.net, armbian-forum: rpardini } @@ -43,4 +45,3 @@ config: # This is file 'patch/kernel/rockchip-rk3588-edge/0000.patching_config.y - "Documentation/devicetree/bindings/arm/rockchip.yaml" # constant churn, conflicts on every bump, drop it. sorry. do-not-commit-regexes: # Python-style regexes - "^arch/([a-zA-Z0-9]+)/boot/dts/([a-zA-Z0-9]+)/Makefile$" # ignore DT Makefile patches, we've an auto-patcher now - diff --git a/patch/kernel/rockchip-rk3588-edge/0005-tools-Makefile-delete-missing-cgroup_clean.patch b/patch/kernel/rockchip-rk3588-edge/0005-tools-Makefile-delete-missing-cgroup_clean.patch deleted file mode 100644 index 295c38d575fa..000000000000 --- a/patch/kernel/rockchip-rk3588-edge/0005-tools-Makefile-delete-missing-cgroup_clean.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: amazingfate -Date: Wed, 24 Jan 2024 18:03:52 +0800 -Subject: tools/Makefile: delete missing cgroup_clean - ---- - tools/Makefile | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/tools/Makefile b/tools/Makefile -index 37e9f6804832..9903abe51d5f 100644 ---- a/tools/Makefile -+++ b/tools/Makefile -@@ -169,7 +169,7 @@ acpi_clean: - cpupower_clean: - $(call descend,power/cpupower,clean) - --cgroup_clean counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean mm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: -+counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean mm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: - $(call descend,$(@:_clean=),clean) - - libapi_clean: -@@ -209,7 +209,7 @@ freefall_clean: - build_clean: - $(call descend,build,clean) - --clean: acpi_clean cgroup_clean counter_clean cpupower_clean hv_clean firewire_clean \ -+clean: acpi_clean counter_clean cpupower_clean hv_clean firewire_clean \ - perf_clean selftests_clean turbostat_clean bootconfig_clean spi_clean usb_clean virtio_clean \ - mm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ - freefall_clean build_clean libbpf_clean libsubcmd_clean \ --- -Armbian - diff --git a/patch/kernel/rockchip-rk3588-edge/1047-fix-initial-PERST#-GPIO-value.patch b/patch/kernel/rockchip-rk3588-edge/0012-fix-initial-PERST-GPIO-value.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1047-fix-initial-PERST#-GPIO-value.patch rename to patch/kernel/rockchip-rk3588-edge/0012-fix-initial-PERST-GPIO-value.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0021-RK3588-Add-USB3-DRD-Support.patch b/patch/kernel/rockchip-rk3588-edge/0021-RK3588-Add-USB3-DRD-Support.patch deleted file mode 100644 index fc2cf13fdad8..000000000000 --- a/patch/kernel/rockchip-rk3588-edge/0021-RK3588-Add-USB3-DRD-Support.patch +++ /dev/null @@ -1,2602 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Fri, 16 Feb 2024 18:01:16 +0100 -Subject: dt-bindings: phy: add rockchip usbdp combo phy document - -Add device tree binding document for Rockchip USBDP Combo PHY -with Samsung IP block. - -Co-developed-by: Frank Wang -Signed-off-by: Frank Wang -Reviewed-by: Conor Dooley -Signed-off-by: Sebastian Reichel ---- - Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml | 148 ++++++++++ - 1 file changed, 148 insertions(+) - -diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml -new file mode 100644 -index 000000000000..1f1f8863b80d ---- /dev/null -+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml -@@ -0,0 +1,148 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/phy/phy-rockchip-usbdp.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Rockchip USBDP Combo PHY with Samsung IP block -+ -+maintainers: -+ - Frank Wang -+ - Zhang Yubing -+ -+properties: -+ compatible: -+ enum: -+ - rockchip,rk3588-usbdp-phy -+ -+ reg: -+ maxItems: 1 -+ -+ "#phy-cells": -+ description: | -+ Cell allows setting the type of the PHY. Possible values are: -+ - PHY_TYPE_USB3 -+ - PHY_TYPE_DP -+ const: 1 -+ -+ clocks: -+ maxItems: 4 -+ -+ clock-names: -+ items: -+ - const: refclk -+ - const: immortal -+ - const: pclk -+ - const: utmi -+ -+ resets: -+ maxItems: 5 -+ -+ reset-names: -+ items: -+ - const: init -+ - const: cmn -+ - const: lane -+ - const: pcs_apb -+ - const: pma_apb -+ -+ rockchip,dp-lane-mux: -+ $ref: /schemas/types.yaml#/definitions/uint32-array -+ minItems: 2 -+ maxItems: 4 -+ items: -+ maximum: 3 -+ description: -+ An array of physical Type-C lanes indexes. Position of an entry -+ determines the DisplayPort (DP) lane index, while the value of an entry -+ indicates physical Type-C lane. The supported DP lanes number are 2 or 4. -+ e.g. for 2 lanes DP lanes map, we could have "rockchip,dp-lane-mux = <2, -+ 3>;", assuming DP lane0 on Type-C phy lane2, DP lane1 on Type-C phy -+ lane3. For 4 lanes DP lanes map, we could have "rockchip,dp-lane-mux = -+ <0, 1, 2, 3>;", assuming DP lane0 on Type-C phy lane0, DP lane1 on Type-C -+ phy lane1, DP lane2 on Type-C phy lane2, DP lane3 on Type-C phy lane3. If -+ DP lanes are mapped by DisplayPort Alt mode, this property is not needed. -+ -+ rockchip,u2phy-grf: -+ $ref: /schemas/types.yaml#/definitions/phandle -+ description: -+ Phandle to the syscon managing the 'usb2 phy general register files'. -+ -+ rockchip,usb-grf: -+ $ref: /schemas/types.yaml#/definitions/phandle -+ description: -+ Phandle to the syscon managing the 'usb general register files'. -+ -+ rockchip,usbdpphy-grf: -+ $ref: /schemas/types.yaml#/definitions/phandle -+ description: -+ Phandle to the syscon managing the 'usbdp phy general register files'. -+ -+ rockchip,vo-grf: -+ $ref: /schemas/types.yaml#/definitions/phandle -+ description: -+ Phandle to the syscon managing the 'video output general register files'. -+ When select the DP lane mapping will request its phandle. -+ -+ sbu1-dc-gpios: -+ description: -+ GPIO connected to the SBU1 line of the USB-C connector via a big resistor -+ (~100K) to apply a DC offset for signalling the connector orientation. -+ maxItems: 1 -+ -+ sbu2-dc-gpios: -+ description: -+ GPIO connected to the SBU2 line of the USB-C connector via a big resistor -+ (~100K) to apply a DC offset for signalling the connector orientation. -+ maxItems: 1 -+ -+ orientation-switch: -+ description: Flag the port as possible handler of orientation switching -+ type: boolean -+ -+ mode-switch: -+ description: Flag the port as possible handler of altmode switching -+ type: boolean -+ -+ port: -+ $ref: /schemas/graph.yaml#/properties/port -+ description: -+ A port node to link the PHY to a TypeC controller for the purpose of -+ handling orientation switching. -+ -+required: -+ - compatible -+ - reg -+ - clocks -+ - clock-names -+ - resets -+ - reset-names -+ - "#phy-cells" -+ -+additionalProperties: false -+ -+examples: -+ - | -+ #include -+ #include -+ -+ usbdp_phy0: phy@fed80000 { -+ compatible = "rockchip,rk3588-usbdp-phy"; -+ reg = <0xfed80000 0x10000>; -+ #phy-cells = <1>; -+ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>, -+ <&cru CLK_USBDP_PHY0_IMMORTAL>, -+ <&cru PCLK_USBDPPHY0>, -+ <&u2phy0>; -+ clock-names = "refclk", "immortal", "pclk", "utmi"; -+ resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>, -+ <&cru SRST_USBDP_COMBO_PHY0_CMN>, -+ <&cru SRST_USBDP_COMBO_PHY0_LANE>, -+ <&cru SRST_USBDP_COMBO_PHY0_PCS>, -+ <&cru SRST_P_USBDPPHY0>; -+ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb"; -+ rockchip,u2phy-grf = <&usb2phy0_grf>; -+ rockchip,usb-grf = <&usb_grf>; -+ rockchip,usbdpphy-grf = <&usbdpphy0_grf>; -+ rockchip,vo-grf = <&vo0_grf>; -+ }; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Fri, 16 Feb 2024 18:01:17 +0100 -Subject: phy: rockchip: add usbdp combo phy driver - -This adds a new USBDP combo PHY with Samsung IP block driver. - -The driver get lane mux and mapping info in 2 ways, supporting -DisplayPort alternate mode or parsing from DT. When parsing from DT, -the property "rockchip,dp-lane-mux" provide the DP mux and mapping -info. This is needed when the PHY is not used with TypeC Alt-Mode. -For example if the USB3 interface of the PHY is connected to a USB -Type A connector and the DP interface is connected to a DisplayPort -connector. - -When do DP link training, need to set lane number, link rate, swing, -and pre-emphasis via PHY configure interface. - -Co-developed-by: Heiko Stuebner -Signed-off-by: Heiko Stuebner -Co-developed-by: Zhang Yubing -Signed-off-by: Zhang Yubing -Co-developed-by: Frank Wang -Signed-off-by: Frank Wang -Signed-off-by: Sebastian Reichel ---- - drivers/phy/rockchip/Kconfig | 12 + - drivers/phy/rockchip/Makefile | 1 + - drivers/phy/rockchip/phy-rockchip-usbdp.c | 1612 ++++++++++ - 3 files changed, 1625 insertions(+) - -diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig -index 94360fc96a6f..d21b458c1d18 100644 ---- a/drivers/phy/rockchip/Kconfig -+++ b/drivers/phy/rockchip/Kconfig -@@ -107,3 +107,15 @@ config PHY_ROCKCHIP_USB - select GENERIC_PHY - help - Enable this to support the Rockchip USB 2.0 PHY. -+ -+config PHY_ROCKCHIP_USBDP -+ tristate "Rockchip USBDP COMBO PHY Driver" -+ depends on ARCH_ROCKCHIP && OF -+ select GENERIC_PHY -+ select TYPEC -+ help -+ Enable this to support the Rockchip USB3.0/DP combo PHY with -+ Samsung IP block. This is required for USB3 support on RK3588. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called phy-rockchip-usbdp -diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile -index 7eab129230d1..25d2e1355db7 100644 ---- a/drivers/phy/rockchip/Makefile -+++ b/drivers/phy/rockchip/Makefile -@@ -11,3 +11,4 @@ obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o - obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o - obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o - obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o -+obj-$(CONFIG_PHY_ROCKCHIP_USBDP) += phy-rockchip-usbdp.o -diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c -new file mode 100644 -index 000000000000..1f3b7955c9f3 ---- /dev/null -+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c -@@ -0,0 +1,1612 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * Rockchip USBDP Combo PHY with Samsung IP block driver -+ * -+ * Copyright (C) 2021 Rockchip Electronics Co., Ltd -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* USBDP PHY Register Definitions */ -+#define UDPHY_PCS 0x4000 -+#define UDPHY_PMA 0x8000 -+ -+/* VO0 GRF Registers */ -+#define DP_SINK_HPD_CFG BIT(11) -+#define DP_SINK_HPD_SEL BIT(10) -+#define DP_AUX_DIN_SEL BIT(9) -+#define DP_AUX_DOUT_SEL BIT(8) -+#define DP_LANE_SEL_N(n) GENMASK(2 * (n) + 1, 2 * (n)) -+#define DP_LANE_SEL_ALL GENMASK(7, 0) -+ -+/* PMA CMN Registers */ -+#define CMN_LANE_MUX_AND_EN_OFFSET 0x0288 /* cmn_reg00A2 */ -+#define CMN_DP_LANE_MUX_N(n) BIT((n) + 4) -+#define CMN_DP_LANE_EN_N(n) BIT(n) -+#define CMN_DP_LANE_MUX_ALL GENMASK(7, 4) -+#define CMN_DP_LANE_EN_ALL GENMASK(3, 0) -+ -+#define CMN_DP_LINK_OFFSET 0x28c /* cmn_reg00A3 */ -+#define CMN_DP_TX_LINK_BW GENMASK(6, 5) -+#define CMN_DP_TX_LANE_SWAP_EN BIT(2) -+ -+#define CMN_SSC_EN_OFFSET 0x2d0 /* cmn_reg00B4 */ -+#define CMN_ROPLL_SSC_EN BIT(1) -+#define CMN_LCPLL_SSC_EN BIT(0) -+ -+#define CMN_ANA_LCPLL_DONE_OFFSET 0x0350 /* cmn_reg00D4 */ -+#define CMN_ANA_LCPLL_LOCK_DONE BIT(7) -+#define CMN_ANA_LCPLL_AFC_DONE BIT(6) -+ -+#define CMN_ANA_ROPLL_DONE_OFFSET 0x0354 /* cmn_reg00D5 */ -+#define CMN_ANA_ROPLL_LOCK_DONE BIT(1) -+#define CMN_ANA_ROPLL_AFC_DONE BIT(0) -+ -+#define CMN_DP_RSTN_OFFSET 0x038c /* cmn_reg00E3 */ -+#define CMN_DP_INIT_RSTN BIT(3) -+#define CMN_DP_CMN_RSTN BIT(2) -+#define CMN_CDR_WTCHDG_EN BIT(1) -+#define CMN_CDR_WTCHDG_MSK_CDR_EN BIT(0) -+ -+#define TRSV_ANA_TX_CLK_OFFSET_N(n) (0x854 + (n) * 0x800) /* trsv_reg0215 */ -+#define LN_ANA_TX_SER_TXCLK_INV BIT(1) -+ -+#define TRSV_LN0_MON_RX_CDR_DONE_OFFSET 0x0b84 /* trsv_reg02E1 */ -+#define TRSV_LN0_MON_RX_CDR_LOCK_DONE BIT(0) -+ -+#define TRSV_LN2_MON_RX_CDR_DONE_OFFSET 0x1b84 /* trsv_reg06E1 */ -+#define TRSV_LN2_MON_RX_CDR_LOCK_DONE BIT(0) -+ -+#define BIT_WRITEABLE_SHIFT 16 -+#define PHY_AUX_DP_DATA_POL_NORMAL 0 -+#define PHY_AUX_DP_DATA_POL_INVERT 1 -+#define PHY_LANE_MUX_USB 0 -+#define PHY_LANE_MUX_DP 1 -+ -+enum { -+ DP_BW_RBR, -+ DP_BW_HBR, -+ DP_BW_HBR2, -+ DP_BW_HBR3, -+}; -+ -+enum { -+ UDPHY_MODE_NONE = 0, -+ UDPHY_MODE_USB = BIT(0), -+ UDPHY_MODE_DP = BIT(1), -+ UDPHY_MODE_DP_USB = BIT(1) | BIT(0), -+}; -+ -+struct rk_udphy_grf_reg { -+ unsigned int offset; -+ unsigned int disable; -+ unsigned int enable; -+}; -+ -+#define _RK_UDPHY_GEN_GRF_REG(offset, mask, disable, enable) \ -+{\ -+ offset, \ -+ FIELD_PREP_CONST(mask, disable) | (mask << BIT_WRITEABLE_SHIFT), \ -+ FIELD_PREP_CONST(mask, enable) | (mask << BIT_WRITEABLE_SHIFT), \ -+} -+ -+#define RK_UDPHY_GEN_GRF_REG(offset, bitend, bitstart, disable, enable) \ -+ _RK_UDPHY_GEN_GRF_REG(offset, GENMASK(bitend, bitstart), disable, enable) -+ -+struct rk_udphy_grf_cfg { -+ /* u2phy-grf */ -+ struct rk_udphy_grf_reg bvalid_phy_con; -+ struct rk_udphy_grf_reg bvalid_grf_con; -+ -+ /* usb-grf */ -+ struct rk_udphy_grf_reg usb3otg0_cfg; -+ struct rk_udphy_grf_reg usb3otg1_cfg; -+ -+ /* usbdpphy-grf */ -+ struct rk_udphy_grf_reg low_pwrn; -+ struct rk_udphy_grf_reg rx_lfps; -+}; -+ -+struct rk_udphy_vogrf_cfg { -+ /* vo-grf */ -+ struct rk_udphy_grf_reg hpd_trigger; -+ u32 dp_lane_reg; -+}; -+ -+struct rk_udphy_dp_tx_drv_ctrl { -+ u32 trsv_reg0204; -+ u32 trsv_reg0205; -+ u32 trsv_reg0206; -+ u32 trsv_reg0207; -+}; -+ -+struct rk_udphy_cfg { -+ unsigned int num_phys; -+ unsigned int phy_ids[2]; -+ /* resets to be requested */ -+ const char * const *rst_list; -+ int num_rsts; -+ -+ struct rk_udphy_grf_cfg grfcfg; -+ struct rk_udphy_vogrf_cfg vogrfcfg[2]; -+ const struct rk_udphy_dp_tx_drv_ctrl (*dp_tx_ctrl_cfg[4])[4]; -+ const struct rk_udphy_dp_tx_drv_ctrl (*dp_tx_ctrl_cfg_typec[4])[4]; -+}; -+ -+struct rk_udphy { -+ struct device *dev; -+ struct regmap *pma_regmap; -+ struct regmap *u2phygrf; -+ struct regmap *udphygrf; -+ struct regmap *usbgrf; -+ struct regmap *vogrf; -+ struct typec_switch_dev *sw; -+ struct typec_mux_dev *mux; -+ struct mutex mutex; /* mutex to protect access to individual PHYs */ -+ -+ /* clocks and rests */ -+ int num_clks; -+ struct clk_bulk_data *clks; -+ struct clk *refclk; -+ int num_rsts; -+ struct reset_control_bulk_data *rsts; -+ -+ /* PHY status management */ -+ bool flip; -+ bool mode_change; -+ u8 mode; -+ u8 status; -+ -+ /* utilized for USB */ -+ bool hs; /* flag for high-speed */ -+ -+ /* utilized for DP */ -+ struct gpio_desc *sbu1_dc_gpio; -+ struct gpio_desc *sbu2_dc_gpio; -+ u32 lane_mux_sel[4]; -+ u32 dp_lane_sel[4]; -+ u32 dp_aux_dout_sel; -+ u32 dp_aux_din_sel; -+ bool dp_sink_hpd_sel; -+ bool dp_sink_hpd_cfg; -+ u8 bw; -+ int id; -+ -+ bool dp_in_use; -+ -+ /* PHY const config */ -+ const struct rk_udphy_cfg *cfgs; -+ -+ /* PHY devices */ -+ struct phy *phy_dp; -+ struct phy *phy_u3; -+}; -+ -+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr[4][4] = { -+ /* voltage swing 0, pre-emphasis 0->3 */ -+ { -+ { 0x20, 0x10, 0x42, 0xe5 }, -+ { 0x26, 0x14, 0x42, 0xe5 }, -+ { 0x29, 0x18, 0x42, 0xe5 }, -+ { 0x2b, 0x1c, 0x43, 0xe7 }, -+ }, -+ -+ /* voltage swing 1, pre-emphasis 0->2 */ -+ { -+ { 0x23, 0x10, 0x42, 0xe7 }, -+ { 0x2a, 0x17, 0x43, 0xe7 }, -+ { 0x2b, 0x1a, 0x43, 0xe7 }, -+ }, -+ -+ /* voltage swing 2, pre-emphasis 0->1 */ -+ { -+ { 0x27, 0x10, 0x42, 0xe7 }, -+ { 0x2b, 0x17, 0x43, 0xe7 }, -+ }, -+ -+ /* voltage swing 3, pre-emphasis 0 */ -+ { -+ { 0x29, 0x10, 0x43, 0xe7 }, -+ }, -+}; -+ -+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr_typec[4][4] = { -+ /* voltage swing 0, pre-emphasis 0->3 */ -+ { -+ { 0x20, 0x10, 0x42, 0xe5 }, -+ { 0x26, 0x14, 0x42, 0xe5 }, -+ { 0x29, 0x18, 0x42, 0xe5 }, -+ { 0x2b, 0x1c, 0x43, 0xe7 }, -+ }, -+ -+ /* voltage swing 1, pre-emphasis 0->2 */ -+ { -+ { 0x23, 0x10, 0x42, 0xe7 }, -+ { 0x2a, 0x17, 0x43, 0xe7 }, -+ { 0x2b, 0x1a, 0x43, 0xe7 }, -+ }, -+ -+ /* voltage swing 2, pre-emphasis 0->1 */ -+ { -+ { 0x27, 0x10, 0x43, 0x67 }, -+ { 0x2b, 0x17, 0x43, 0xe7 }, -+ }, -+ -+ /* voltage swing 3, pre-emphasis 0 */ -+ { -+ { 0x29, 0x10, 0x43, 0xe7 }, -+ }, -+}; -+ -+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr2[4][4] = { -+ /* voltage swing 0, pre-emphasis 0->3 */ -+ { -+ { 0x21, 0x10, 0x42, 0xe5 }, -+ { 0x26, 0x14, 0x42, 0xe5 }, -+ { 0x26, 0x16, 0x43, 0xe5 }, -+ { 0x2a, 0x19, 0x43, 0xe7 }, -+ }, -+ -+ /* voltage swing 1, pre-emphasis 0->2 */ -+ { -+ { 0x24, 0x10, 0x42, 0xe7 }, -+ { 0x2a, 0x17, 0x43, 0xe7 }, -+ { 0x2b, 0x1a, 0x43, 0xe7 }, -+ }, -+ -+ /* voltage swing 2, pre-emphasis 0->1 */ -+ { -+ { 0x28, 0x10, 0x42, 0xe7 }, -+ { 0x2b, 0x17, 0x43, 0xe7 }, -+ }, -+ -+ /* voltage swing 3, pre-emphasis 0 */ -+ { -+ { 0x28, 0x10, 0x43, 0xe7 }, -+ }, -+}; -+ -+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr3[4][4] = { -+ /* voltage swing 0, pre-emphasis 0->3 */ -+ { -+ { 0x21, 0x10, 0x42, 0xe5 }, -+ { 0x26, 0x14, 0x42, 0xe5 }, -+ { 0x26, 0x16, 0x43, 0xe5 }, -+ { 0x29, 0x18, 0x43, 0xe7 }, -+ }, -+ -+ /* voltage swing 1, pre-emphasis 0->2 */ -+ { -+ { 0x24, 0x10, 0x42, 0xe7 }, -+ { 0x2a, 0x18, 0x43, 0xe7 }, -+ { 0x2b, 0x1b, 0x43, 0xe7 } -+ }, -+ -+ /* voltage swing 2, pre-emphasis 0->1 */ -+ { -+ { 0x27, 0x10, 0x42, 0xe7 }, -+ { 0x2b, 0x18, 0x43, 0xe7 } -+ }, -+ -+ /* voltage swing 3, pre-emphasis 0 */ -+ { -+ { 0x28, 0x10, 0x43, 0xe7 }, -+ }, -+}; -+ -+static const struct reg_sequence rk_udphy_24m_refclk_cfg[] = { -+ {0x0090, 0x68}, {0x0094, 0x68}, -+ {0x0128, 0x24}, {0x012c, 0x44}, -+ {0x0130, 0x3f}, {0x0134, 0x44}, -+ {0x015c, 0xa9}, {0x0160, 0x71}, -+ {0x0164, 0x71}, {0x0168, 0xa9}, -+ {0x0174, 0xa9}, {0x0178, 0x71}, -+ {0x017c, 0x71}, {0x0180, 0xa9}, -+ {0x018c, 0x41}, {0x0190, 0x00}, -+ {0x0194, 0x05}, {0x01ac, 0x2a}, -+ {0x01b0, 0x17}, {0x01b4, 0x17}, -+ {0x01b8, 0x2a}, {0x01c8, 0x04}, -+ {0x01cc, 0x08}, {0x01d0, 0x08}, -+ {0x01d4, 0x04}, {0x01d8, 0x20}, -+ {0x01dc, 0x01}, {0x01e0, 0x09}, -+ {0x01e4, 0x03}, {0x01f0, 0x29}, -+ {0x01f4, 0x02}, {0x01f8, 0x02}, -+ {0x01fc, 0x29}, {0x0208, 0x2a}, -+ {0x020c, 0x17}, {0x0210, 0x17}, -+ {0x0214, 0x2a}, {0x0224, 0x20}, -+ {0x03f0, 0x0a}, {0x03f4, 0x07}, -+ {0x03f8, 0x07}, {0x03fc, 0x0c}, -+ {0x0404, 0x12}, {0x0408, 0x1a}, -+ {0x040c, 0x1a}, {0x0410, 0x3f}, -+ {0x0ce0, 0x68}, {0x0ce8, 0xd0}, -+ {0x0cf0, 0x87}, {0x0cf8, 0x70}, -+ {0x0d00, 0x70}, {0x0d08, 0xa9}, -+ {0x1ce0, 0x68}, {0x1ce8, 0xd0}, -+ {0x1cf0, 0x87}, {0x1cf8, 0x70}, -+ {0x1d00, 0x70}, {0x1d08, 0xa9}, -+ {0x0a3c, 0xd0}, {0x0a44, 0xd0}, -+ {0x0a48, 0x01}, {0x0a4c, 0x0d}, -+ {0x0a54, 0xe0}, {0x0a5c, 0xe0}, -+ {0x0a64, 0xa8}, {0x1a3c, 0xd0}, -+ {0x1a44, 0xd0}, {0x1a48, 0x01}, -+ {0x1a4c, 0x0d}, {0x1a54, 0xe0}, -+ {0x1a5c, 0xe0}, {0x1a64, 0xa8} -+}; -+ -+static const struct reg_sequence rk_udphy_26m_refclk_cfg[] = { -+ {0x0830, 0x07}, {0x085c, 0x80}, -+ {0x1030, 0x07}, {0x105c, 0x80}, -+ {0x1830, 0x07}, {0x185c, 0x80}, -+ {0x2030, 0x07}, {0x205c, 0x80}, -+ {0x0228, 0x38}, {0x0104, 0x44}, -+ {0x0248, 0x44}, {0x038c, 0x02}, -+ {0x0878, 0x04}, {0x1878, 0x04}, -+ {0x0898, 0x77}, {0x1898, 0x77}, -+ {0x0054, 0x01}, {0x00e0, 0x38}, -+ {0x0060, 0x24}, {0x0064, 0x77}, -+ {0x0070, 0x76}, {0x0234, 0xe8}, -+ {0x0af4, 0x15}, {0x1af4, 0x15}, -+ {0x081c, 0xe5}, {0x181c, 0xe5}, -+ {0x099c, 0x48}, {0x199c, 0x48}, -+ {0x09a4, 0x07}, {0x09a8, 0x22}, -+ {0x19a4, 0x07}, {0x19a8, 0x22}, -+ {0x09b8, 0x3e}, {0x19b8, 0x3e}, -+ {0x09e4, 0x02}, {0x19e4, 0x02}, -+ {0x0a34, 0x1e}, {0x1a34, 0x1e}, -+ {0x0a98, 0x2f}, {0x1a98, 0x2f}, -+ {0x0c30, 0x0e}, {0x0c48, 0x06}, -+ {0x1c30, 0x0e}, {0x1c48, 0x06}, -+ {0x028c, 0x18}, {0x0af0, 0x00}, -+ {0x1af0, 0x00} -+}; -+ -+static const struct reg_sequence rk_udphy_init_sequence[] = { -+ {0x0104, 0x44}, {0x0234, 0xe8}, -+ {0x0248, 0x44}, {0x028c, 0x18}, -+ {0x081c, 0xe5}, {0x0878, 0x00}, -+ {0x0994, 0x1c}, {0x0af0, 0x00}, -+ {0x181c, 0xe5}, {0x1878, 0x00}, -+ {0x1994, 0x1c}, {0x1af0, 0x00}, -+ {0x0428, 0x60}, {0x0d58, 0x33}, -+ {0x1d58, 0x33}, {0x0990, 0x74}, -+ {0x0d64, 0x17}, {0x08c8, 0x13}, -+ {0x1990, 0x74}, {0x1d64, 0x17}, -+ {0x18c8, 0x13}, {0x0d90, 0x40}, -+ {0x0da8, 0x40}, {0x0dc0, 0x40}, -+ {0x0dd8, 0x40}, {0x1d90, 0x40}, -+ {0x1da8, 0x40}, {0x1dc0, 0x40}, -+ {0x1dd8, 0x40}, {0x03c0, 0x30}, -+ {0x03c4, 0x06}, {0x0e10, 0x00}, -+ {0x1e10, 0x00}, {0x043c, 0x0f}, -+ {0x0d2c, 0xff}, {0x1d2c, 0xff}, -+ {0x0d34, 0x0f}, {0x1d34, 0x0f}, -+ {0x08fc, 0x2a}, {0x0914, 0x28}, -+ {0x0a30, 0x03}, {0x0e38, 0x03}, -+ {0x0ecc, 0x27}, {0x0ed0, 0x22}, -+ {0x0ed4, 0x26}, {0x18fc, 0x2a}, -+ {0x1914, 0x28}, {0x1a30, 0x03}, -+ {0x1e38, 0x03}, {0x1ecc, 0x27}, -+ {0x1ed0, 0x22}, {0x1ed4, 0x26}, -+ {0x0048, 0x0f}, {0x0060, 0x3c}, -+ {0x0064, 0xf7}, {0x006c, 0x20}, -+ {0x0070, 0x7d}, {0x0074, 0x68}, -+ {0x0af4, 0x1a}, {0x1af4, 0x1a}, -+ {0x0440, 0x3f}, {0x10d4, 0x08}, -+ {0x20d4, 0x08}, {0x00d4, 0x30}, -+ {0x0024, 0x6e}, -+}; -+ -+static inline int rk_udphy_grfreg_write(struct regmap *base, -+ const struct rk_udphy_grf_reg *reg, bool en) -+{ -+ return regmap_write(base, reg->offset, en ? reg->enable : reg->disable); -+} -+ -+static int rk_udphy_clk_init(struct rk_udphy *udphy, struct device *dev) -+{ -+ int i; -+ -+ udphy->num_clks = devm_clk_bulk_get_all(dev, &udphy->clks); -+ if (udphy->num_clks < 1) -+ return -ENODEV; -+ -+ /* used for configure phy reference clock frequency */ -+ for (i = 0; i < udphy->num_clks; i++) { -+ if (!strncmp(udphy->clks[i].id, "refclk", 6)) { -+ udphy->refclk = udphy->clks[i].clk; -+ break; -+ } -+ } -+ -+ if (!udphy->refclk) -+ return dev_err_probe(udphy->dev, -EINVAL, "no refclk found\n"); -+ -+ return 0; -+} -+ -+static int rk_udphy_reset_assert_all(struct rk_udphy *udphy) -+{ -+ return reset_control_bulk_assert(udphy->num_rsts, udphy->rsts); -+} -+ -+static int rk_udphy_reset_deassert_all(struct rk_udphy *udphy) -+{ -+ return reset_control_bulk_deassert(udphy->num_rsts, udphy->rsts); -+} -+ -+static int rk_udphy_reset_deassert(struct rk_udphy *udphy, char *name) -+{ -+ struct reset_control_bulk_data *list = udphy->rsts; -+ int idx; -+ -+ for (idx = 0; idx < udphy->num_rsts; idx++) { -+ if (!strcmp(list[idx].id, name)) -+ return reset_control_deassert(list[idx].rstc); -+ } -+ -+ return -EINVAL; -+} -+ -+static int rk_udphy_reset_init(struct rk_udphy *udphy, struct device *dev) -+{ -+ const struct rk_udphy_cfg *cfg = udphy->cfgs; -+ int idx; -+ -+ udphy->num_rsts = cfg->num_rsts; -+ udphy->rsts = devm_kcalloc(dev, udphy->num_rsts, -+ sizeof(*udphy->rsts), GFP_KERNEL); -+ if (!udphy->rsts) -+ return -ENOMEM; -+ -+ for (idx = 0; idx < cfg->num_rsts; idx++) -+ udphy->rsts[idx].id = cfg->rst_list[idx]; -+ -+ return devm_reset_control_bulk_get_exclusive(dev, cfg->num_rsts, -+ udphy->rsts); -+} -+ -+static void rk_udphy_u3_port_disable(struct rk_udphy *udphy, u8 disable) -+{ -+ const struct rk_udphy_cfg *cfg = udphy->cfgs; -+ const struct rk_udphy_grf_reg *preg; -+ -+ preg = udphy->id ? &cfg->grfcfg.usb3otg1_cfg : &cfg->grfcfg.usb3otg0_cfg; -+ rk_udphy_grfreg_write(udphy->usbgrf, preg, disable); -+} -+ -+static void rk_udphy_usb_bvalid_enable(struct rk_udphy *udphy, u8 enable) -+{ -+ const struct rk_udphy_cfg *cfg = udphy->cfgs; -+ -+ rk_udphy_grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_phy_con, enable); -+ rk_udphy_grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_grf_con, enable); -+} -+ -+/* -+ * In usb/dp combo phy driver, here are 2 ways to mapping lanes. -+ * -+ * 1 Type-C Mapping table (DP_Alt_Mode V1.0b remove ABF pin mapping) -+ * --------------------------------------------------------------------------- -+ * Type-C Pin B11-B10 A2-A3 A11-A10 B2-B3 -+ * PHY Pad ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) -+ * C/E(Normal) dpln3 dpln2 dpln0 dpln1 -+ * C/E(Flip ) dpln0 dpln1 dpln3 dpln2 -+ * D/F(Normal) usbrx usbtx dpln0 dpln1 -+ * D/F(Flip ) dpln0 dpln1 usbrx usbtx -+ * A(Normal ) dpln3 dpln1 dpln2 dpln0 -+ * A(Flip ) dpln2 dpln0 dpln3 dpln1 -+ * B(Normal ) usbrx usbtx dpln1 dpln0 -+ * B(Flip ) dpln1 dpln0 usbrx usbtx -+ * --------------------------------------------------------------------------- -+ * -+ * 2 Mapping the lanes in dtsi -+ * if all 4 lane assignment for dp function, define rockchip,dp-lane-mux = ; -+ * sample as follow: -+ * --------------------------------------------------------------------------- -+ * B11-B10 A2-A3 A11-A10 B2-B3 -+ * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) -+ * <0 1 2 3> dpln0 dpln1 dpln2 dpln3 -+ * <2 3 0 1> dpln2 dpln3 dpln0 dpln1 -+ * --------------------------------------------------------------------------- -+ * if 2 lane for dp function, 2 lane for usb function, define rockchip,dp-lane-mux = ; -+ * sample as follow: -+ * --------------------------------------------------------------------------- -+ * B11-B10 A2-A3 A11-A10 B2-B3 -+ * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) -+ * <0 1> dpln0 dpln1 usbrx usbtx -+ * <2 3> usbrx usbtx dpln0 dpln1 -+ * --------------------------------------------------------------------------- -+ */ -+ -+static void rk_udphy_dplane_select(struct rk_udphy *udphy) -+{ -+ const struct rk_udphy_cfg *cfg = udphy->cfgs; -+ u32 value = 0; -+ -+ switch (udphy->mode) { -+ case UDPHY_MODE_DP: -+ value |= 2 << udphy->dp_lane_sel[2] * 2; -+ value |= 3 << udphy->dp_lane_sel[3] * 2; -+ fallthrough; -+ -+ case UDPHY_MODE_DP_USB: -+ value |= 0 << udphy->dp_lane_sel[0] * 2; -+ value |= 1 << udphy->dp_lane_sel[1] * 2; -+ break; -+ -+ case UDPHY_MODE_USB: -+ break; -+ -+ default: -+ break; -+ } -+ -+ regmap_write(udphy->vogrf, cfg->vogrfcfg[udphy->id].dp_lane_reg, -+ ((DP_AUX_DIN_SEL | DP_AUX_DOUT_SEL | DP_LANE_SEL_ALL) << 16) | -+ FIELD_PREP(DP_AUX_DIN_SEL, udphy->dp_aux_din_sel) | -+ FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value); -+} -+ -+static int rk_udphy_dplane_get(struct rk_udphy *udphy) -+{ -+ int dp_lanes; -+ -+ switch (udphy->mode) { -+ case UDPHY_MODE_DP: -+ dp_lanes = 4; -+ break; -+ -+ case UDPHY_MODE_DP_USB: -+ dp_lanes = 2; -+ break; -+ -+ case UDPHY_MODE_USB: -+ default: -+ dp_lanes = 0; -+ break; -+ } -+ -+ return dp_lanes; -+} -+ -+static void rk_udphy_dplane_enable(struct rk_udphy *udphy, int dp_lanes) -+{ -+ u32 val = 0; -+ int i; -+ -+ for (i = 0; i < dp_lanes; i++) -+ val |= BIT(udphy->dp_lane_sel[i]); -+ -+ regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, CMN_DP_LANE_EN_ALL, -+ FIELD_PREP(CMN_DP_LANE_EN_ALL, val)); -+ -+ if (!dp_lanes) -+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, -+ CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); -+} -+ -+static void rk_udphy_dp_hpd_event_trigger(struct rk_udphy *udphy, bool hpd) -+{ -+ const struct rk_udphy_cfg *cfg = udphy->cfgs; -+ -+ udphy->dp_sink_hpd_sel = true; -+ udphy->dp_sink_hpd_cfg = hpd; -+ -+ if (!udphy->dp_in_use) -+ return; -+ -+ rk_udphy_grfreg_write(udphy->vogrf, &cfg->vogrfcfg[udphy->id].hpd_trigger, hpd); -+} -+ -+static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy) -+{ -+ if (udphy->flip) { -+ udphy->dp_lane_sel[0] = 0; -+ udphy->dp_lane_sel[1] = 1; -+ udphy->dp_lane_sel[2] = 3; -+ udphy->dp_lane_sel[3] = 2; -+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; -+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; -+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB; -+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB; -+ udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_INVERT; -+ udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_INVERT; -+ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 1); -+ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0); -+ } else { -+ udphy->dp_lane_sel[0] = 2; -+ udphy->dp_lane_sel[1] = 3; -+ udphy->dp_lane_sel[2] = 1; -+ udphy->dp_lane_sel[3] = 0; -+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB; -+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB; -+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; -+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; -+ udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_NORMAL; -+ udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_NORMAL; -+ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0); -+ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 1); -+ } -+ -+ udphy->mode = UDPHY_MODE_DP_USB; -+} -+ -+static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw, -+ enum typec_orientation orien) -+{ -+ struct rk_udphy *udphy = typec_switch_get_drvdata(sw); -+ -+ mutex_lock(&udphy->mutex); -+ -+ if (orien == TYPEC_ORIENTATION_NONE) { -+ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0); -+ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0); -+ /* unattached */ -+ rk_udphy_usb_bvalid_enable(udphy, false); -+ goto unlock_ret; -+ } -+ -+ udphy->flip = (orien == TYPEC_ORIENTATION_REVERSE) ? true : false; -+ rk_udphy_set_typec_default_mapping(udphy); -+ rk_udphy_usb_bvalid_enable(udphy, true); -+ -+unlock_ret: -+ mutex_unlock(&udphy->mutex); -+ return 0; -+} -+ -+static void rk_udphy_orien_switch_unregister(void *data) -+{ -+ struct rk_udphy *udphy = data; -+ -+ typec_switch_unregister(udphy->sw); -+} -+ -+static int rk_udphy_setup_orien_switch(struct rk_udphy *udphy) -+{ -+ struct typec_switch_desc sw_desc = { }; -+ -+ sw_desc.drvdata = udphy; -+ sw_desc.fwnode = dev_fwnode(udphy->dev); -+ sw_desc.set = rk_udphy_orien_sw_set; -+ -+ udphy->sw = typec_switch_register(udphy->dev, &sw_desc); -+ if (IS_ERR(udphy->sw)) { -+ dev_err(udphy->dev, "Error register typec orientation switch: %ld\n", -+ PTR_ERR(udphy->sw)); -+ return PTR_ERR(udphy->sw); -+ } -+ -+ return devm_add_action_or_reset(udphy->dev, -+ rk_udphy_orien_switch_unregister, udphy); -+} -+ -+static int rk_udphy_refclk_set(struct rk_udphy *udphy) -+{ -+ unsigned long rate; -+ int ret; -+ -+ /* configure phy reference clock */ -+ rate = clk_get_rate(udphy->refclk); -+ dev_dbg(udphy->dev, "refclk freq %ld\n", rate); -+ -+ switch (rate) { -+ case 24000000: -+ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_24m_refclk_cfg, -+ ARRAY_SIZE(rk_udphy_24m_refclk_cfg)); -+ if (ret) -+ return ret; -+ break; -+ -+ case 26000000: -+ /* register default is 26MHz */ -+ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_26m_refclk_cfg, -+ ARRAY_SIZE(rk_udphy_26m_refclk_cfg)); -+ if (ret) -+ return ret; -+ break; -+ -+ default: -+ dev_err(udphy->dev, "unsupported refclk freq %ld\n", rate); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int rk_udphy_status_check(struct rk_udphy *udphy) -+{ -+ unsigned int val; -+ int ret; -+ -+ /* LCPLL check */ -+ if (udphy->mode & UDPHY_MODE_USB) { -+ ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_LCPLL_DONE_OFFSET, -+ val, (val & CMN_ANA_LCPLL_AFC_DONE) && -+ (val & CMN_ANA_LCPLL_LOCK_DONE), 200, 100000); -+ if (ret) { -+ dev_err(udphy->dev, "cmn ana lcpll lock timeout\n"); -+ /* -+ * If earlier software (U-Boot) enabled USB once already -+ * the PLL may have problems locking on the first try. -+ * It will be successful on the second try, so for the -+ * time being a -EPROBE_DEFER will solve the issue. -+ * -+ * This requires further investigation to understand the -+ * root cause, especially considering that the driver is -+ * asserting all reset lines at probe time. -+ */ -+ return -EPROBE_DEFER; -+ } -+ -+ if (!udphy->flip) { -+ ret = regmap_read_poll_timeout(udphy->pma_regmap, -+ TRSV_LN0_MON_RX_CDR_DONE_OFFSET, val, -+ val & TRSV_LN0_MON_RX_CDR_LOCK_DONE, -+ 200, 100000); -+ if (ret) -+ dev_err(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n"); -+ } else { -+ ret = regmap_read_poll_timeout(udphy->pma_regmap, -+ TRSV_LN2_MON_RX_CDR_DONE_OFFSET, val, -+ val & TRSV_LN2_MON_RX_CDR_LOCK_DONE, -+ 200, 100000); -+ if (ret) -+ dev_err(udphy->dev, "trsv ln2 mon rx cdr lock timeout\n"); -+ } -+ } -+ -+ return 0; -+} -+ -+static int rk_udphy_init(struct rk_udphy *udphy) -+{ -+ const struct rk_udphy_cfg *cfg = udphy->cfgs; -+ int ret; -+ -+ rk_udphy_reset_assert_all(udphy); -+ usleep_range(10000, 11000); -+ -+ /* enable rx lfps for usb */ -+ if (udphy->mode & UDPHY_MODE_USB) -+ rk_udphy_grfreg_write(udphy->udphygrf, &cfg->grfcfg.rx_lfps, true); -+ -+ /* Step 1: power on pma and deassert apb rstn */ -+ rk_udphy_grfreg_write(udphy->udphygrf, &cfg->grfcfg.low_pwrn, true); -+ -+ rk_udphy_reset_deassert(udphy, "pma_apb"); -+ rk_udphy_reset_deassert(udphy, "pcs_apb"); -+ -+ /* Step 2: set init sequence and phy refclk */ -+ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_init_sequence, -+ ARRAY_SIZE(rk_udphy_init_sequence)); -+ if (ret) { -+ dev_err(udphy->dev, "init sequence set error %d\n", ret); -+ goto assert_resets; -+ } -+ -+ ret = rk_udphy_refclk_set(udphy); -+ if (ret) { -+ dev_err(udphy->dev, "refclk set error %d\n", ret); -+ goto assert_resets; -+ } -+ -+ /* Step 3: configure lane mux */ -+ regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, -+ CMN_DP_LANE_MUX_ALL | CMN_DP_LANE_EN_ALL, -+ FIELD_PREP(CMN_DP_LANE_MUX_N(3), udphy->lane_mux_sel[3]) | -+ FIELD_PREP(CMN_DP_LANE_MUX_N(2), udphy->lane_mux_sel[2]) | -+ FIELD_PREP(CMN_DP_LANE_MUX_N(1), udphy->lane_mux_sel[1]) | -+ FIELD_PREP(CMN_DP_LANE_MUX_N(0), udphy->lane_mux_sel[0]) | -+ FIELD_PREP(CMN_DP_LANE_EN_ALL, 0)); -+ -+ /* Step 4: deassert init rstn and wait for 200ns from datasheet */ -+ if (udphy->mode & UDPHY_MODE_USB) -+ rk_udphy_reset_deassert(udphy, "init"); -+ -+ if (udphy->mode & UDPHY_MODE_DP) { -+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, -+ CMN_DP_INIT_RSTN, -+ FIELD_PREP(CMN_DP_INIT_RSTN, 0x1)); -+ } -+ -+ udelay(1); -+ -+ /* Step 5: deassert cmn/lane rstn */ -+ if (udphy->mode & UDPHY_MODE_USB) { -+ rk_udphy_reset_deassert(udphy, "cmn"); -+ rk_udphy_reset_deassert(udphy, "lane"); -+ } -+ -+ /* Step 6: wait for lock done of pll */ -+ ret = rk_udphy_status_check(udphy); -+ if (ret) -+ goto assert_resets; -+ -+ return 0; -+ -+assert_resets: -+ rk_udphy_reset_assert_all(udphy); -+ return ret; -+} -+ -+static int rk_udphy_setup(struct rk_udphy *udphy) -+{ -+ int ret = 0; -+ -+ ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks); -+ if (ret) { -+ dev_err(udphy->dev, "failed to enable clk\n"); -+ return ret; -+ } -+ -+ ret = rk_udphy_init(udphy); -+ if (ret) { -+ dev_err(udphy->dev, "failed to init combophy\n"); -+ clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void rk_udphy_disable(struct rk_udphy *udphy) -+{ -+ clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks); -+ rk_udphy_reset_assert_all(udphy); -+} -+ -+static int rk_udphy_parse_lane_mux_data(struct rk_udphy *udphy) -+{ -+ int ret, i, num_lanes; -+ -+ num_lanes = device_property_count_u32(udphy->dev, "rockchip,dp-lane-mux"); -+ if (num_lanes < 0) { -+ dev_dbg(udphy->dev, "no dp-lane-mux, following dp alt mode\n"); -+ udphy->mode = UDPHY_MODE_USB; -+ return 0; -+ } -+ -+ if (num_lanes != 2 && num_lanes != 4) -+ return dev_err_probe(udphy->dev, -EINVAL, -+ "invalid number of lane mux\n"); -+ -+ ret = device_property_read_u32_array(udphy->dev, "rockchip,dp-lane-mux", -+ udphy->dp_lane_sel, num_lanes); -+ if (ret) -+ return dev_err_probe(udphy->dev, ret, "get dp lane mux failed\n"); -+ -+ for (i = 0; i < num_lanes; i++) { -+ int j; -+ -+ if (udphy->dp_lane_sel[i] > 3) -+ return dev_err_probe(udphy->dev, -EINVAL, -+ "lane mux between 0 and 3, exceeding the range\n"); -+ -+ udphy->lane_mux_sel[udphy->dp_lane_sel[i]] = PHY_LANE_MUX_DP; -+ -+ for (j = i + 1; j < num_lanes; j++) { -+ if (udphy->dp_lane_sel[i] == udphy->dp_lane_sel[j]) -+ return dev_err_probe(udphy->dev, -EINVAL, -+ "set repeat lane mux value\n"); -+ } -+ } -+ -+ udphy->mode = UDPHY_MODE_DP; -+ if (num_lanes == 2) { -+ udphy->mode |= UDPHY_MODE_USB; -+ udphy->flip = (udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP); -+ } -+ -+ return 0; -+} -+ -+static int rk_udphy_get_initial_status(struct rk_udphy *udphy) -+{ -+ int ret; -+ u32 value; -+ -+ ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks); -+ if (ret) { -+ dev_err(udphy->dev, "failed to enable clk\n"); -+ return ret; -+ } -+ -+ rk_udphy_reset_deassert_all(udphy); -+ -+ regmap_read(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, &value); -+ if (FIELD_GET(CMN_DP_LANE_MUX_ALL, value) && FIELD_GET(CMN_DP_LANE_EN_ALL, value)) -+ udphy->status = UDPHY_MODE_DP; -+ else -+ rk_udphy_disable(udphy); -+ -+ return 0; -+} -+ -+static int rk_udphy_parse_dt(struct rk_udphy *udphy) -+{ -+ struct device *dev = udphy->dev; -+ struct device_node *np = dev_of_node(dev); -+ enum usb_device_speed maximum_speed; -+ int ret; -+ -+ udphy->u2phygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,u2phy-grf"); -+ if (IS_ERR(udphy->u2phygrf)) -+ return dev_err_probe(dev, PTR_ERR(udphy->u2phygrf), "failed to get u2phy-grf\n"); -+ -+ udphy->udphygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbdpphy-grf"); -+ if (IS_ERR(udphy->udphygrf)) -+ return dev_err_probe(dev, PTR_ERR(udphy->udphygrf), "failed to get usbdpphy-grf\n"); -+ -+ udphy->usbgrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usb-grf"); -+ if (IS_ERR(udphy->usbgrf)) -+ return dev_err_probe(dev, PTR_ERR(udphy->usbgrf), "failed to get usb-grf\n"); -+ -+ udphy->vogrf = syscon_regmap_lookup_by_phandle(np, "rockchip,vo-grf"); -+ if (IS_ERR(udphy->vogrf)) -+ return dev_err_probe(dev, PTR_ERR(udphy->vogrf), "failed to get vo-grf\n"); -+ -+ ret = rk_udphy_parse_lane_mux_data(udphy); -+ if (ret) -+ return ret; -+ -+ udphy->sbu1_dc_gpio = devm_gpiod_get_optional(dev, "sbu1-dc", GPIOD_OUT_LOW); -+ if (IS_ERR(udphy->sbu1_dc_gpio)) -+ return PTR_ERR(udphy->sbu1_dc_gpio); -+ -+ udphy->sbu2_dc_gpio = devm_gpiod_get_optional(dev, "sbu2-dc", GPIOD_OUT_LOW); -+ if (IS_ERR(udphy->sbu2_dc_gpio)) -+ return PTR_ERR(udphy->sbu2_dc_gpio); -+ -+ if (device_property_present(dev, "maximum-speed")) { -+ maximum_speed = usb_get_maximum_speed(dev); -+ udphy->hs = maximum_speed <= USB_SPEED_HIGH ? true : false; -+ } -+ -+ ret = rk_udphy_clk_init(udphy, dev); -+ if (ret) -+ return ret; -+ -+ ret = rk_udphy_reset_init(udphy, dev); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode) -+{ -+ int ret; -+ -+ if (!(udphy->mode & mode)) { -+ dev_info(udphy->dev, "mode 0x%02x is not support\n", mode); -+ return 0; -+ } -+ -+ if (udphy->status == UDPHY_MODE_NONE) { -+ udphy->mode_change = false; -+ ret = rk_udphy_setup(udphy); -+ if (ret) -+ return ret; -+ -+ if (udphy->mode & UDPHY_MODE_USB) -+ rk_udphy_u3_port_disable(udphy, false); -+ } else if (udphy->mode_change) { -+ udphy->mode_change = false; -+ udphy->status = UDPHY_MODE_NONE; -+ if (udphy->mode == UDPHY_MODE_DP) -+ rk_udphy_u3_port_disable(udphy, true); -+ -+ rk_udphy_disable(udphy); -+ ret = rk_udphy_setup(udphy); -+ if (ret) -+ return ret; -+ } -+ -+ udphy->status |= mode; -+ -+ return 0; -+} -+ -+static void rk_udphy_power_off(struct rk_udphy *udphy, u8 mode) -+{ -+ if (!(udphy->mode & mode)) { -+ dev_info(udphy->dev, "mode 0x%02x is not support\n", mode); -+ return; -+ } -+ -+ if (!udphy->status) -+ return; -+ -+ udphy->status &= ~mode; -+ -+ if (udphy->status == UDPHY_MODE_NONE) -+ rk_udphy_disable(udphy); -+} -+ -+static int rk_udphy_dp_phy_init(struct phy *phy) -+{ -+ struct rk_udphy *udphy = phy_get_drvdata(phy); -+ -+ mutex_lock(&udphy->mutex); -+ -+ udphy->dp_in_use = true; -+ rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg); -+ -+ mutex_unlock(&udphy->mutex); -+ -+ return 0; -+} -+ -+static int rk_udphy_dp_phy_exit(struct phy *phy) -+{ -+ struct rk_udphy *udphy = phy_get_drvdata(phy); -+ -+ mutex_lock(&udphy->mutex); -+ udphy->dp_in_use = false; -+ mutex_unlock(&udphy->mutex); -+ return 0; -+} -+ -+static int rk_udphy_dp_phy_power_on(struct phy *phy) -+{ -+ struct rk_udphy *udphy = phy_get_drvdata(phy); -+ int ret, dp_lanes; -+ -+ mutex_lock(&udphy->mutex); -+ -+ dp_lanes = rk_udphy_dplane_get(udphy); -+ phy_set_bus_width(phy, dp_lanes); -+ -+ ret = rk_udphy_power_on(udphy, UDPHY_MODE_DP); -+ if (ret) -+ goto unlock; -+ -+ rk_udphy_dplane_enable(udphy, dp_lanes); -+ -+ rk_udphy_dplane_select(udphy); -+ -+unlock: -+ mutex_unlock(&udphy->mutex); -+ /* -+ * If data send by aux channel too fast after phy power on, -+ * the aux may be not ready which will cause aux error. Adding -+ * delay to avoid this issue. -+ */ -+ usleep_range(10000, 11000); -+ return ret; -+} -+ -+static int rk_udphy_dp_phy_power_off(struct phy *phy) -+{ -+ struct rk_udphy *udphy = phy_get_drvdata(phy); -+ -+ mutex_lock(&udphy->mutex); -+ rk_udphy_dplane_enable(udphy, 0); -+ rk_udphy_power_off(udphy, UDPHY_MODE_DP); -+ mutex_unlock(&udphy->mutex); -+ -+ return 0; -+} -+ -+static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate) -+{ -+ switch (link_rate) { -+ case 1620: -+ case 2700: -+ case 5400: -+ case 8100: -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy, -+ struct phy_configure_opts_dp *dp) -+{ -+ int i, ret; -+ -+ /* If changing link rate was required, verify it's supported. */ -+ ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate); -+ if (ret) -+ return ret; -+ -+ /* Verify lane count. */ -+ switch (dp->lanes) { -+ case 1: -+ case 2: -+ case 4: -+ /* valid lane count. */ -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ -+ /* -+ * If changing voltages is required, check swing and pre-emphasis -+ * levels, per-lane. -+ */ -+ if (dp->set_voltages) { -+ /* Lane count verified previously. */ -+ for (i = 0; i < dp->lanes; i++) { -+ if (dp->voltage[i] > 3 || dp->pre[i] > 3) -+ return -EINVAL; -+ -+ /* -+ * Sum of voltage swing and pre-emphasis levels cannot -+ * exceed 3. -+ */ -+ if (dp->voltage[i] + dp->pre[i] > 3) -+ return -EINVAL; -+ } -+ } -+ -+ return 0; -+} -+ -+static void rk_udphy_dp_set_voltage(struct rk_udphy *udphy, u8 bw, -+ u32 voltage, u32 pre, u32 lane) -+{ -+ const struct rk_udphy_cfg *cfg = udphy->cfgs; -+ const struct rk_udphy_dp_tx_drv_ctrl (*dp_ctrl)[4]; -+ u32 offset = 0x800 * lane; -+ u32 val; -+ -+ if (udphy->mux) -+ dp_ctrl = cfg->dp_tx_ctrl_cfg_typec[bw]; -+ else -+ dp_ctrl = cfg->dp_tx_ctrl_cfg[bw]; -+ -+ val = dp_ctrl[voltage][pre].trsv_reg0204; -+ regmap_write(udphy->pma_regmap, 0x0810 + offset, val); -+ -+ val = dp_ctrl[voltage][pre].trsv_reg0205; -+ regmap_write(udphy->pma_regmap, 0x0814 + offset, val); -+ -+ val = dp_ctrl[voltage][pre].trsv_reg0206; -+ regmap_write(udphy->pma_regmap, 0x0818 + offset, val); -+ -+ val = dp_ctrl[voltage][pre].trsv_reg0207; -+ regmap_write(udphy->pma_regmap, 0x081c + offset, val); -+} -+ -+static int rk_udphy_dp_phy_configure(struct phy *phy, -+ union phy_configure_opts *opts) -+{ -+ struct rk_udphy *udphy = phy_get_drvdata(phy); -+ struct phy_configure_opts_dp *dp = &opts->dp; -+ u32 i, val, lane; -+ int ret; -+ -+ ret = rk_udphy_dp_phy_verify_config(udphy, dp); -+ if (ret) -+ return ret; -+ -+ if (dp->set_rate) { -+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, -+ CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); -+ -+ switch (dp->link_rate) { -+ case 1620: -+ udphy->bw = DP_BW_RBR; -+ break; -+ -+ case 2700: -+ udphy->bw = DP_BW_HBR; -+ break; -+ -+ case 5400: -+ udphy->bw = DP_BW_HBR2; -+ break; -+ -+ case 8100: -+ udphy->bw = DP_BW_HBR3; -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ -+ regmap_update_bits(udphy->pma_regmap, CMN_DP_LINK_OFFSET, CMN_DP_TX_LINK_BW, -+ FIELD_PREP(CMN_DP_TX_LINK_BW, udphy->bw)); -+ regmap_update_bits(udphy->pma_regmap, CMN_SSC_EN_OFFSET, CMN_ROPLL_SSC_EN, -+ FIELD_PREP(CMN_ROPLL_SSC_EN, dp->ssc)); -+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, CMN_DP_CMN_RSTN, -+ FIELD_PREP(CMN_DP_CMN_RSTN, 0x1)); -+ -+ ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_ROPLL_DONE_OFFSET, val, -+ FIELD_GET(CMN_ANA_ROPLL_LOCK_DONE, val) && -+ FIELD_GET(CMN_ANA_ROPLL_AFC_DONE, val), -+ 0, 1000); -+ if (ret) { -+ dev_err(udphy->dev, "ROPLL is not lock, set_rate failed\n"); -+ return ret; -+ } -+ } -+ -+ if (dp->set_voltages) { -+ for (i = 0; i < dp->lanes; i++) { -+ lane = udphy->dp_lane_sel[i]; -+ switch (dp->link_rate) { -+ case 1620: -+ case 2700: -+ regmap_update_bits(udphy->pma_regmap, -+ TRSV_ANA_TX_CLK_OFFSET_N(lane), -+ LN_ANA_TX_SER_TXCLK_INV, -+ FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, -+ udphy->lane_mux_sel[lane])); -+ break; -+ -+ case 5400: -+ case 8100: -+ regmap_update_bits(udphy->pma_regmap, -+ TRSV_ANA_TX_CLK_OFFSET_N(lane), -+ LN_ANA_TX_SER_TXCLK_INV, -+ FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, 0x0)); -+ break; -+ } -+ -+ rk_udphy_dp_set_voltage(udphy, udphy->bw, dp->voltage[i], -+ dp->pre[i], lane); -+ } -+ } -+ -+ return 0; -+} -+ -+static const struct phy_ops rk_udphy_dp_phy_ops = { -+ .init = rk_udphy_dp_phy_init, -+ .exit = rk_udphy_dp_phy_exit, -+ .power_on = rk_udphy_dp_phy_power_on, -+ .power_off = rk_udphy_dp_phy_power_off, -+ .configure = rk_udphy_dp_phy_configure, -+ .owner = THIS_MODULE, -+}; -+ -+static int rk_udphy_usb3_phy_init(struct phy *phy) -+{ -+ struct rk_udphy *udphy = phy_get_drvdata(phy); -+ int ret = 0; -+ -+ mutex_lock(&udphy->mutex); -+ /* DP only or high-speed, disable U3 port */ -+ if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) { -+ rk_udphy_u3_port_disable(udphy, true); -+ goto unlock; -+ } -+ -+ ret = rk_udphy_power_on(udphy, UDPHY_MODE_USB); -+ -+unlock: -+ mutex_unlock(&udphy->mutex); -+ return ret; -+} -+ -+static int rk_udphy_usb3_phy_exit(struct phy *phy) -+{ -+ struct rk_udphy *udphy = phy_get_drvdata(phy); -+ -+ mutex_lock(&udphy->mutex); -+ /* DP only or high-speed */ -+ if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) -+ goto unlock; -+ -+ rk_udphy_power_off(udphy, UDPHY_MODE_USB); -+ -+unlock: -+ mutex_unlock(&udphy->mutex); -+ return 0; -+} -+ -+static const struct phy_ops rk_udphy_usb3_phy_ops = { -+ .init = rk_udphy_usb3_phy_init, -+ .exit = rk_udphy_usb3_phy_exit, -+ .owner = THIS_MODULE, -+}; -+ -+static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux, -+ struct typec_mux_state *state) -+{ -+ struct rk_udphy *udphy = typec_mux_get_drvdata(mux); -+ u8 mode; -+ -+ mutex_lock(&udphy->mutex); -+ -+ switch (state->mode) { -+ case TYPEC_DP_STATE_C: -+ case TYPEC_DP_STATE_E: -+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; -+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; -+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; -+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; -+ mode = UDPHY_MODE_DP; -+ break; -+ -+ case TYPEC_DP_STATE_D: -+ default: -+ if (udphy->flip) { -+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; -+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; -+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB; -+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB; -+ } else { -+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB; -+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB; -+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; -+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; -+ } -+ mode = UDPHY_MODE_DP_USB; -+ break; -+ } -+ -+ if (state->alt && state->alt->svid == USB_TYPEC_DP_SID) { -+ struct typec_displayport_data *data = state->data; -+ -+ if (!data) { -+ rk_udphy_dp_hpd_event_trigger(udphy, false); -+ } else if (data->status & DP_STATUS_IRQ_HPD) { -+ rk_udphy_dp_hpd_event_trigger(udphy, false); -+ usleep_range(750, 800); -+ rk_udphy_dp_hpd_event_trigger(udphy, true); -+ } else if (data->status & DP_STATUS_HPD_STATE) { -+ if (udphy->mode != mode) { -+ udphy->mode = mode; -+ udphy->mode_change = true; -+ } -+ rk_udphy_dp_hpd_event_trigger(udphy, true); -+ } else { -+ rk_udphy_dp_hpd_event_trigger(udphy, false); -+ } -+ } -+ -+ mutex_unlock(&udphy->mutex); -+ return 0; -+} -+ -+static void rk_udphy_typec_mux_unregister(void *data) -+{ -+ struct rk_udphy *udphy = data; -+ -+ typec_mux_unregister(udphy->mux); -+} -+ -+static int rk_udphy_setup_typec_mux(struct rk_udphy *udphy) -+{ -+ struct typec_mux_desc mux_desc = {}; -+ -+ mux_desc.drvdata = udphy; -+ mux_desc.fwnode = dev_fwnode(udphy->dev); -+ mux_desc.set = rk_udphy_typec_mux_set; -+ -+ udphy->mux = typec_mux_register(udphy->dev, &mux_desc); -+ if (IS_ERR(udphy->mux)) { -+ dev_err(udphy->dev, "Error register typec mux: %ld\n", -+ PTR_ERR(udphy->mux)); -+ return PTR_ERR(udphy->mux); -+ } -+ -+ return devm_add_action_or_reset(udphy->dev, rk_udphy_typec_mux_unregister, -+ udphy); -+} -+ -+static const struct regmap_config rk_udphy_pma_regmap_cfg = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .fast_io = true, -+ .max_register = 0x20dc, -+}; -+ -+static struct phy *rk_udphy_phy_xlate(struct device *dev, struct of_phandle_args *args) -+{ -+ struct rk_udphy *udphy = dev_get_drvdata(dev); -+ -+ if (args->args_count == 0) -+ return ERR_PTR(-EINVAL); -+ -+ switch (args->args[0]) { -+ case PHY_TYPE_USB3: -+ return udphy->phy_u3; -+ case PHY_TYPE_DP: -+ return udphy->phy_dp; -+ } -+ -+ return ERR_PTR(-EINVAL); -+} -+ -+static int rk_udphy_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct phy_provider *phy_provider; -+ struct resource *res; -+ struct rk_udphy *udphy; -+ void __iomem *base; -+ int id, ret; -+ -+ udphy = devm_kzalloc(dev, sizeof(*udphy), GFP_KERNEL); -+ if (!udphy) -+ return -ENOMEM; -+ -+ udphy->cfgs = device_get_match_data(dev); -+ if (!udphy->cfgs) -+ return dev_err_probe(dev, -EINVAL, "missing match data\n"); -+ -+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ /* find the phy-id from the io address */ -+ udphy->id = -ENODEV; -+ for (id = 0; id < udphy->cfgs->num_phys; id++) { -+ if (res->start == udphy->cfgs->phy_ids[id]) { -+ udphy->id = id; -+ break; -+ } -+ } -+ -+ if (udphy->id < 0) -+ return dev_err_probe(dev, -ENODEV, "no matching device found\n"); -+ -+ udphy->pma_regmap = devm_regmap_init_mmio(dev, base + UDPHY_PMA, -+ &rk_udphy_pma_regmap_cfg); -+ if (IS_ERR(udphy->pma_regmap)) -+ return PTR_ERR(udphy->pma_regmap); -+ -+ udphy->dev = dev; -+ ret = rk_udphy_parse_dt(udphy); -+ if (ret) -+ return ret; -+ -+ ret = rk_udphy_get_initial_status(udphy); -+ if (ret) -+ return ret; -+ -+ mutex_init(&udphy->mutex); -+ platform_set_drvdata(pdev, udphy); -+ -+ if (device_property_present(dev, "orientation-switch")) { -+ ret = rk_udphy_setup_orien_switch(udphy); -+ if (ret) -+ return ret; -+ } -+ -+ if (device_property_present(dev, "mode-switch")) { -+ ret = rk_udphy_setup_typec_mux(udphy); -+ if (ret) -+ return ret; -+ } -+ -+ udphy->phy_u3 = devm_phy_create(dev, dev->of_node, &rk_udphy_usb3_phy_ops); -+ if (IS_ERR(udphy->phy_u3)) { -+ ret = PTR_ERR(udphy->phy_u3); -+ return dev_err_probe(dev, ret, "failed to create USB3 phy\n"); -+ } -+ phy_set_drvdata(udphy->phy_u3, udphy); -+ -+ udphy->phy_dp = devm_phy_create(dev, dev->of_node, &rk_udphy_dp_phy_ops); -+ if (IS_ERR(udphy->phy_dp)) { -+ ret = PTR_ERR(udphy->phy_dp); -+ return dev_err_probe(dev, ret, "failed to create DP phy\n"); -+ } -+ phy_set_bus_width(udphy->phy_dp, rk_udphy_dplane_get(udphy)); -+ udphy->phy_dp->attrs.max_link_rate = 8100; -+ phy_set_drvdata(udphy->phy_dp, udphy); -+ -+ phy_provider = devm_of_phy_provider_register(dev, rk_udphy_phy_xlate); -+ if (IS_ERR(phy_provider)) { -+ ret = PTR_ERR(phy_provider); -+ return dev_err_probe(dev, ret, "failed to register phy provider\n"); -+ } -+ -+ return 0; -+} -+ -+static int __maybe_unused rk_udphy_resume(struct device *dev) -+{ -+ struct rk_udphy *udphy = dev_get_drvdata(dev); -+ -+ if (udphy->dp_sink_hpd_sel) -+ rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg); -+ -+ return 0; -+} -+ -+static const struct dev_pm_ops rk_udphy_pm_ops = { -+ SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, rk_udphy_resume) -+}; -+ -+static const char * const rk_udphy_rst_list[] = { -+ "init", "cmn", "lane", "pcs_apb", "pma_apb" -+}; -+ -+static const struct rk_udphy_cfg rk3588_udphy_cfgs = { -+ .num_phys = 2, -+ .phy_ids = { -+ 0xfed80000, -+ 0xfed90000, -+ }, -+ .num_rsts = ARRAY_SIZE(rk_udphy_rst_list), -+ .rst_list = rk_udphy_rst_list, -+ .grfcfg = { -+ /* u2phy-grf */ -+ .bvalid_phy_con = RK_UDPHY_GEN_GRF_REG(0x0008, 1, 0, 0x2, 0x3), -+ .bvalid_grf_con = RK_UDPHY_GEN_GRF_REG(0x0010, 3, 2, 0x2, 0x3), -+ -+ /* usb-grf */ -+ .usb3otg0_cfg = RK_UDPHY_GEN_GRF_REG(0x001c, 15, 0, 0x1100, 0x0188), -+ .usb3otg1_cfg = RK_UDPHY_GEN_GRF_REG(0x0034, 15, 0, 0x1100, 0x0188), -+ -+ /* usbdpphy-grf */ -+ .low_pwrn = RK_UDPHY_GEN_GRF_REG(0x0004, 13, 13, 0, 1), -+ .rx_lfps = RK_UDPHY_GEN_GRF_REG(0x0004, 14, 14, 0, 1), -+ }, -+ .vogrfcfg = { -+ { -+ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0000, 11, 10, 1, 3), -+ .dp_lane_reg = 0x0000, -+ }, -+ { -+ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0008, 11, 10, 1, 3), -+ .dp_lane_reg = 0x0008, -+ }, -+ }, -+ .dp_tx_ctrl_cfg = { -+ rk3588_dp_tx_drv_ctrl_rbr_hbr, -+ rk3588_dp_tx_drv_ctrl_rbr_hbr, -+ rk3588_dp_tx_drv_ctrl_hbr2, -+ rk3588_dp_tx_drv_ctrl_hbr3, -+ }, -+ .dp_tx_ctrl_cfg_typec = { -+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec, -+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec, -+ rk3588_dp_tx_drv_ctrl_hbr2, -+ rk3588_dp_tx_drv_ctrl_hbr3, -+ }, -+}; -+ -+static const struct of_device_id rk_udphy_dt_match[] = { -+ { -+ .compatible = "rockchip,rk3588-usbdp-phy", -+ .data = &rk3588_udphy_cfgs -+ }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, rk_udphy_dt_match); -+ -+static struct platform_driver rk_udphy_driver = { -+ .probe = rk_udphy_probe, -+ .driver = { -+ .name = "rockchip-usbdp-phy", -+ .of_match_table = rk_udphy_dt_match, -+ .pm = &rk_udphy_pm_ops, -+ }, -+}; -+module_platform_driver(rk_udphy_driver); -+ -+MODULE_AUTHOR("Frank Wang "); -+MODULE_AUTHOR("Zhang Yubing "); -+MODULE_DESCRIPTION("Rockchip USBDP Combo PHY driver"); -+MODULE_LICENSE("GPL"); --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Fri, 16 Feb 2024 18:01:18 +0100 -Subject: arm64: defconfig: enable Rockchip Samsung USBDP PHY - -The USBDP Phy is used by RK3588 to handle the Dual-Role USB3 -controllers. The Phy also supports Displayport Alt-Mode, but -the necessary DRM driver has not yet been merged. - -Signed-off-by: Sebastian Reichel ---- - arch/arm64/configs/defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig -index e6cf3e5d63c3..07890b86777e 100644 ---- a/arch/arm64/configs/defconfig -+++ b/arch/arm64/configs/defconfig -@@ -1492,6 +1492,7 @@ CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=m - CONFIG_PHY_ROCKCHIP_PCIE=m - CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=y - CONFIG_PHY_ROCKCHIP_TYPEC=y -+CONFIG_PHY_ROCKCHIP_USBDP=m - CONFIG_PHY_SAMSUNG_UFS=y - CONFIG_PHY_UNIPHIER_USB2=y - CONFIG_PHY_UNIPHIER_USB3=y --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Fri, 16 Feb 2024 18:01:19 +0100 -Subject: arm64: dts: rockchip: fix usb2phy nodename for rk3588 - -usb2-phy should be named usb2phy according to the DT binding, -so let's fix it up accordingly. - -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 82350ddb262f..4df0e26321ff 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -542,7 +542,7 @@ usb2phy2_grf: syscon@fd5d8000 { - #address-cells = <1>; - #size-cells = <1>; - -- u2phy2: usb2-phy@8000 { -+ u2phy2: usb2phy@8000 { - compatible = "rockchip,rk3588-usb2phy"; - reg = <0x8000 0x10>; - interrupts = ; -@@ -567,7 +567,7 @@ usb2phy3_grf: syscon@fd5dc000 { - #address-cells = <1>; - #size-cells = <1>; - -- u2phy3: usb2-phy@c000 { -+ u2phy3: usb2phy@c000 { - compatible = "rockchip,rk3588-usb2phy"; - reg = <0xc000 0x10>; - interrupts = ; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Fri, 16 Feb 2024 18:01:20 +0100 -Subject: arm64: dts: rockchip: reorder usb2phy properties for rk3588 - -Reorder common DT properties alphabetically for usb2phy, according -to latest DT style rules. - -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 16 +++++----- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 4df0e26321ff..572732ed6596 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -545,13 +545,13 @@ usb2phy2_grf: syscon@fd5d8000 { - u2phy2: usb2phy@8000 { - compatible = "rockchip,rk3588-usb2phy"; - reg = <0x8000 0x10>; -- interrupts = ; -- resets = <&cru SRST_OTGPHY_U2_0>, <&cru SRST_P_USB2PHY_U2_0_GRF0>; -- reset-names = "phy", "apb"; -+ #clock-cells = <0>; - clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; - clock-names = "phyclk"; - clock-output-names = "usb480m_phy2"; -- #clock-cells = <0>; -+ interrupts = ; -+ resets = <&cru SRST_OTGPHY_U2_0>, <&cru SRST_P_USB2PHY_U2_0_GRF0>; -+ reset-names = "phy", "apb"; - status = "disabled"; - - u2phy2_host: host-port { -@@ -570,13 +570,13 @@ usb2phy3_grf: syscon@fd5dc000 { - u2phy3: usb2phy@c000 { - compatible = "rockchip,rk3588-usb2phy"; - reg = <0xc000 0x10>; -- interrupts = ; -- resets = <&cru SRST_OTGPHY_U2_1>, <&cru SRST_P_USB2PHY_U2_1_GRF0>; -- reset-names = "phy", "apb"; -+ #clock-cells = <0>; - clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; - clock-names = "phyclk"; - clock-output-names = "usb480m_phy3"; -- #clock-cells = <0>; -+ interrupts = ; -+ resets = <&cru SRST_OTGPHY_U2_1>, <&cru SRST_P_USB2PHY_U2_1_GRF0>; -+ reset-names = "phy", "apb"; - status = "disabled"; - - u2phy3_host: host-port { --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Fri, 16 Feb 2024 18:01:21 +0100 -Subject: arm64: dts: rockchip: add USBDP phys on rk3588 - -Add both USB3-DisplayPort PHYs to RK3588 SoC DT. - -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588.dtsi | 52 ++++++++ - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 63 ++++++++++ - 2 files changed, 115 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588.dtsi b/arch/arm64/boot/dts/rockchip/rk3588.dtsi -index 5519c1430cb7..4fdd047c9eb9 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi -@@ -17,6 +17,36 @@ pipe_phy1_grf: syscon@fd5c0000 { - reg = <0x0 0xfd5c0000 0x0 0x100>; - }; - -+ usbdpphy1_grf: syscon@fd5cc000 { -+ compatible = "rockchip,rk3588-usbdpphy-grf", "syscon"; -+ reg = <0x0 0xfd5cc000 0x0 0x4000>; -+ }; -+ -+ usb2phy1_grf: syscon@fd5d4000 { -+ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd"; -+ reg = <0x0 0xfd5d4000 0x0 0x4000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ u2phy1: usb2phy@4000 { -+ compatible = "rockchip,rk3588-usb2phy"; -+ reg = <0x4000 0x10>; -+ #clock-cells = <0>; -+ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; -+ clock-names = "phyclk"; -+ clock-output-names = "usb480m_phy1"; -+ interrupts = ; -+ resets = <&cru SRST_OTGPHY_U3_1>, <&cru SRST_P_USB2PHY_U3_1_GRF0>; -+ reset-names = "phy", "apb"; -+ status = "disabled"; -+ -+ u2phy1_otg: otg-port { -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ - i2s8_8ch: i2s@fddc8000 { - compatible = "rockchip,rk3588-i2s-tdm"; - reg = <0x0 0xfddc8000 0x0 0x1000>; -@@ -310,6 +340,28 @@ sata-port@0 { - }; - }; - -+ usbdp_phy1: phy@fed90000 { -+ compatible = "rockchip,rk3588-usbdp-phy"; -+ reg = <0x0 0xfed90000 0x0 0x10000>; -+ #phy-cells = <1>; -+ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>, -+ <&cru CLK_USBDP_PHY1_IMMORTAL>, -+ <&cru PCLK_USBDPPHY1>, -+ <&u2phy1>; -+ clock-names = "refclk", "immortal", "pclk", "utmi"; -+ resets = <&cru SRST_USBDP_COMBO_PHY1_INIT>, -+ <&cru SRST_USBDP_COMBO_PHY1_CMN>, -+ <&cru SRST_USBDP_COMBO_PHY1_LANE>, -+ <&cru SRST_USBDP_COMBO_PHY1_PCS>, -+ <&cru SRST_P_USBDPPHY1>; -+ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb"; -+ rockchip,u2phy-grf = <&usb2phy1_grf>; -+ rockchip,usb-grf = <&usb_grf>; -+ rockchip,usbdpphy-grf = <&usbdpphy1_grf>; -+ rockchip,vo-grf = <&vo0_grf>; -+ status = "disabled"; -+ }; -+ - combphy1_ps: phy@fee10000 { - compatible = "rockchip,rk3588-naneng-combphy"; - reg = <0x0 0xfee10000 0x0 0x100>; -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 572732ed6596..d70ffe457b83 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -516,11 +516,22 @@ vop_grf: syscon@fd5a4000 { - reg = <0x0 0xfd5a4000 0x0 0x2000>; - }; - -+ vo0_grf: syscon@fd5a6000 { -+ compatible = "rockchip,rk3588-vo-grf", "syscon"; -+ reg = <0x0 0xfd5a6000 0x0 0x2000>; -+ clocks = <&cru PCLK_VO0GRF>; -+ }; -+ - vo1_grf: syscon@fd5a8000 { - compatible = "rockchip,rk3588-vo-grf", "syscon"; - reg = <0x0 0xfd5a8000 0x0 0x100>; - }; - -+ usb_grf: syscon@fd5ac000 { -+ compatible = "rockchip,rk3588-usb-grf", "syscon"; -+ reg = <0x0 0xfd5ac000 0x0 0x4000>; -+ }; -+ - php_grf: syscon@fd5b0000 { - compatible = "rockchip,rk3588-php-grf", "syscon"; - reg = <0x0 0xfd5b0000 0x0 0x1000>; -@@ -536,6 +547,36 @@ pipe_phy2_grf: syscon@fd5c4000 { - reg = <0x0 0xfd5c4000 0x0 0x100>; - }; - -+ usbdpphy0_grf: syscon@fd5c8000 { -+ compatible = "rockchip,rk3588-usbdpphy-grf", "syscon"; -+ reg = <0x0 0xfd5c8000 0x0 0x4000>; -+ }; -+ -+ usb2phy0_grf: syscon@fd5d0000 { -+ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd"; -+ reg = <0x0 0xfd5d0000 0x0 0x4000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ u2phy0: usb2phy@0 { -+ compatible = "rockchip,rk3588-usb2phy"; -+ reg = <0x0 0x10>; -+ #clock-cells = <0>; -+ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; -+ clock-names = "phyclk"; -+ clock-output-names = "usb480m_phy0"; -+ interrupts = ; -+ resets = <&cru SRST_OTGPHY_U3_0>, <&cru SRST_P_USB2PHY_U3_0_GRF0>; -+ reset-names = "phy", "apb"; -+ status = "disabled"; -+ -+ u2phy0_otg: otg-port { -+ #phy-cells = <0>; -+ status = "disabled"; -+ }; -+ }; -+ }; -+ - usb2phy2_grf: syscon@fd5d8000 { - compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd"; - reg = <0x0 0xfd5d8000 0x0 0x4000>; -@@ -2358,6 +2399,28 @@ dmac2: dma-controller@fed10000 { - #dma-cells = <1>; - }; - -+ usbdp_phy0: phy@fed80000 { -+ compatible = "rockchip,rk3588-usbdp-phy"; -+ reg = <0x0 0xfed80000 0x0 0x10000>; -+ #phy-cells = <1>; -+ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>, -+ <&cru CLK_USBDP_PHY0_IMMORTAL>, -+ <&cru PCLK_USBDPPHY0>, -+ <&u2phy0>; -+ clock-names = "refclk", "immortal", "pclk", "utmi"; -+ resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>, -+ <&cru SRST_USBDP_COMBO_PHY0_CMN>, -+ <&cru SRST_USBDP_COMBO_PHY0_LANE>, -+ <&cru SRST_USBDP_COMBO_PHY0_PCS>, -+ <&cru SRST_P_USBDPPHY0>; -+ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb"; -+ rockchip,u2phy-grf = <&usb2phy0_grf>; -+ rockchip,usb-grf = <&usb_grf>; -+ rockchip,usbdpphy-grf = <&usbdpphy0_grf>; -+ rockchip,vo-grf = <&vo0_grf>; -+ status = "disabled"; -+ }; -+ - combphy0_ps: phy@fee00000 { - compatible = "rockchip,rk3588-naneng-combphy"; - reg = <0x0 0xfee00000 0x0 0x100>; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Fri, 16 Feb 2024 18:01:22 +0100 -Subject: arm64: dts: rockchip: add USB3 DRD controllers on rk3588 - -Add both USB3 dual-role controllers to the RK3588 devicetree. - -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588.dtsi | 20 +++++++++ - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 22 ++++++++++ - 2 files changed, 42 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588.dtsi b/arch/arm64/boot/dts/rockchip/rk3588.dtsi -index 4fdd047c9eb9..5984016b5f96 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi -@@ -7,6 +7,26 @@ - #include "rk3588-pinctrl.dtsi" - - / { -+ usb_host1_xhci: usb@fc400000 { -+ compatible = "rockchip,rk3588-dwc3", "snps,dwc3"; -+ reg = <0x0 0xfc400000 0x0 0x400000>; -+ interrupts = ; -+ clocks = <&cru REF_CLK_USB3OTG1>, <&cru SUSPEND_CLK_USB3OTG1>, -+ <&cru ACLK_USB3OTG1>; -+ clock-names = "ref_clk", "suspend_clk", "bus_clk"; -+ dr_mode = "otg"; -+ phys = <&u2phy1_otg>, <&usbdp_phy1 PHY_TYPE_USB3>; -+ phy-names = "usb2-phy", "usb3-phy"; -+ phy_type = "utmi_wide"; -+ power-domains = <&power RK3588_PD_USB>; -+ resets = <&cru SRST_A_USB3OTG1>; -+ snps,dis_enblslpm_quirk; -+ snps,dis-u2-freeclk-exists-quirk; -+ snps,dis-del-phy-power-chg-quirk; -+ snps,dis-tx-ipgap-linecheck-quirk; -+ status = "disabled"; -+ }; -+ - pcie30_phy_grf: syscon@fd5b8000 { - compatible = "rockchip,rk3588-pcie3-phy-grf", "syscon"; - reg = <0x0 0xfd5b8000 0x0 0x10000>; -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index d70ffe457b83..ce39d3f9593c 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -436,6 +436,28 @@ scmi_shmem: sram@0 { - }; - }; - -+ usb_host0_xhci: usb@fc000000 { -+ compatible = "rockchip,rk3588-dwc3", "snps,dwc3"; -+ reg = <0x0 0xfc000000 0x0 0x400000>; -+ interrupts = ; -+ clocks = <&cru REF_CLK_USB3OTG0>, <&cru SUSPEND_CLK_USB3OTG0>, -+ <&cru ACLK_USB3OTG0>; -+ clock-names = "ref_clk", "suspend_clk", "bus_clk"; -+ dr_mode = "otg"; -+ phys = <&u2phy0_otg>, <&usbdp_phy0 PHY_TYPE_USB3>; -+ phy-names = "usb2-phy", "usb3-phy"; -+ phy_type = "utmi_wide"; -+ power-domains = <&power RK3588_PD_USB>; -+ resets = <&cru SRST_A_USB3OTG0>; -+ snps,dis_enblslpm_quirk; -+ snps,dis-u1-entry-quirk; -+ snps,dis-u2-entry-quirk; -+ snps,dis-u2-freeclk-exists-quirk; -+ snps,dis-del-phy-power-chg-quirk; -+ snps,dis-tx-ipgap-linecheck-quirk; -+ status = "disabled"; -+ }; -+ - usb_host0_ehci: usb@fc800000 { - compatible = "rockchip,rk3588-ehci", "generic-ehci"; - reg = <0x0 0xfc800000 0x0 0x40000>; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Fri, 16 Feb 2024 18:01:23 +0100 -Subject: arm64: dts: rockchip: add USB3 to rk3588-evb1 - -Add support for the board's USB3 connectors. It has 1x USB Type-A -and 1x USB Type-C. - -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts | 143 ++++++++++ - 1 file changed, 143 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts -index de30c2632b8e..c3746d3a9b1d 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include "rk3588.dtsi" - - / { -@@ -224,6 +225,18 @@ vcc5v0_usb: vcc5v0-usb-regulator { - regulator-max-microvolt = <5000000>; - vin-supply = <&vcc5v0_usbdcin>; - }; -+ -+ vbus5v0_typec: vbus5v0-typec { -+ compatible = "regulator-fixed"; -+ regulator-name = "vbus5v0_typec"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ enable-active-high; -+ gpio = <&gpio4 RK_PD0 GPIO_ACTIVE_HIGH>; -+ vin-supply = <&vcc5v0_usb>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&typec5v_pwren>; -+ }; - }; - - &combphy0_ps { -@@ -284,6 +297,56 @@ &gmac0_rgmii_clk - &i2c2 { - status = "okay"; - -+ usbc0: usb-typec@22 { -+ compatible = "fcs,fusb302"; -+ reg = <0x22>; -+ interrupt-parent = <&gpio3>; -+ interrupts = ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usbc0_int>; -+ vbus-supply = <&vbus5v0_typec>; -+ status = "okay"; -+ -+ usb_con: connector { -+ compatible = "usb-c-connector"; -+ label = "USB-C"; -+ data-role = "dual"; -+ power-role = "dual"; -+ try-power-role = "source"; -+ op-sink-microwatt = <1000000>; -+ sink-pdos = -+ ; -+ source-pdos = -+ ; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ usbc0_orien_sw: endpoint { -+ remote-endpoint = <&usbdp_phy0_orientation_switch>; -+ }; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ usbc0_role_sw: endpoint { -+ remote-endpoint = <&dwc3_0_role_switch>; -+ }; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ dp_altmode_mux: endpoint { -+ remote-endpoint = <&usbdp_phy0_dp_altmode_mux>; -+ }; -+ }; -+ }; -+ }; -+ }; -+ - hym8563: rtc@51 { - compatible = "haoyu,hym8563"; - reg = <0x51>; -@@ -410,6 +473,16 @@ vcc5v0_host_en: vcc5v0-host-en { - rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; -+ -+ usb-typec { -+ usbc0_int: usbc0-int { -+ rockchip,pins = <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ -+ typec5v_pwren: typec5v-pwren { -+ rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; - }; - - &pwm2 { -@@ -1041,6 +1114,22 @@ &sata0 { - status = "okay"; - }; - -+&u2phy0 { -+ status = "okay"; -+}; -+ -+&u2phy0_otg { -+ status = "okay"; -+}; -+ -+&u2phy1 { -+ status = "okay"; -+}; -+ -+&u2phy1_otg { -+ status = "okay"; -+}; -+ - &u2phy2 { - status = "okay"; - }; -@@ -1079,3 +1168,57 @@ &usb_host1_ehci { - &usb_host1_ohci { - status = "okay"; - }; -+ -+&usbdp_phy0 { -+ orientation-switch; -+ mode-switch; -+ sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>; -+ sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+ -+ port { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ usbdp_phy0_orientation_switch: endpoint@0 { -+ reg = <0>; -+ remote-endpoint = <&usbc0_orien_sw>; -+ }; -+ -+ usbdp_phy0_dp_altmode_mux: endpoint@1 { -+ reg = <1>; -+ remote-endpoint = <&dp_altmode_mux>; -+ }; -+ }; -+}; -+ -+&usbdp_phy1 { -+ /* -+ * USBDP PHY1 is wired to a female USB3 Type-A connector. Additionally -+ * the differential pairs 2+3 and the aux channel are wired to a RTD2166, -+ * which converts the DP signal into VGA. This is exposed on the -+ * board via a female VGA connector. -+ */ -+ rockchip,dp-lane-mux = <2 3>; -+ status = "okay"; -+}; -+ -+&usb_host0_xhci { -+ dr_mode = "otg"; -+ usb-role-switch; -+ status = "okay"; -+ -+ port { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ dwc3_0_role_switch: endpoint@0 { -+ reg = <0>; -+ remote-endpoint = <&usbc0_role_sw>; -+ }; -+ }; -+}; -+ -+&usb_host1_xhci { -+ dr_mode = "host"; -+ status = "okay"; -+}; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Fri, 28 Jul 2023 16:43:16 +0200 -Subject: usb: typec: tcpm: avoid graph warning - -When using a devicetree as described in commit d56de8c9a17d ("usb: -typec: tcpm: try to get role switch from tcpc fwnode"), the kernel -will print an error when probing the TCPM driver, which looks -similar to this: - -OF: graph: no port node found in /i2c@feac0000/usb-typec@22 - -This is a false positive, since the code first tries to find a ports -node for the device and only then checks the fwnode. Fix this by -swapping the order. - -Note, that this will now generate a error message for devicetrees with -a role-switch ports node directly in the TCPM node instead of in the -connectors sub-node, before falling back to the legacy behaviour. These -devicetrees generate warnings when being checked against the bindings, -and should be fixed. - -Fixes: d56de8c9a17d ("usb: typec: tcpm: try to get role switch from tcpc fwnode") -Signed-off-by: Sebastian Reichel ---- - drivers/usb/typec/tcpm/tcpm.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c -index df9a5d6760b4..edeb738702d9 100644 ---- a/drivers/usb/typec/tcpm/tcpm.c -+++ b/drivers/usb/typec/tcpm/tcpm.c -@@ -6831,9 +6831,9 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) - - port->partner_desc.identity = &port->partner_ident; - -- port->role_sw = usb_role_switch_get(port->dev); -+ port->role_sw = fwnode_usb_role_switch_get(tcpc->fwnode); - if (!port->role_sw) -- port->role_sw = fwnode_usb_role_switch_get(tcpc->fwnode); -+ port->role_sw = usb_role_switch_get(port->dev); - if (IS_ERR(port->role_sw)) { - err = PTR_ERR(port->role_sw); - goto out_destroy_wq; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Fri, 16 Feb 2024 18:01:24 +0100 -Subject: arm64: dts: rockchip: add upper USB3 port to rock-5a - -Enable full support (XHCI, EHCI, OHCI) for the upper USB3 port from -Radxa Rock 5 Model A. The lower one is already supported. - -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 18 ++++++++++ - 1 file changed, 18 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -index 2002fd0221fa..149058352f4e 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -@@ -698,6 +698,14 @@ regulator-state-mem { - }; - }; - -+&u2phy0 { -+ status = "okay"; -+}; -+ -+&u2phy0_otg { -+ status = "okay"; -+}; -+ - &u2phy2 { - status = "okay"; - }; -@@ -721,6 +729,11 @@ &uart2 { - status = "okay"; - }; - -+&usbdp_phy0 { -+ status = "okay"; -+ rockchip,dp-lane-mux = <2 3>; -+}; -+ - &usb_host0_ehci { - status = "okay"; - pinctrl-names = "default"; -@@ -731,6 +744,11 @@ &usb_host0_ohci { - status = "okay"; - }; - -+&usb_host0_xhci { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ - &usb_host1_ehci { - status = "okay"; - }; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sebastian Reichel -Date: Fri, 16 Feb 2024 18:01:25 +0100 -Subject: arm64: dts: rockchip: add lower USB3 port to rock-5b - -Enable full support (XHCI, EHCI, OHCI) for the lower USB3 port from -Radxa Rock 5 Model B. The upper one is already supported. - -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 17 ++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index a0e303c3a1dc..149bd44ffd1c 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -@@ -736,6 +736,14 @@ &uart2 { - status = "okay"; - }; - -+&u2phy1 { -+ status = "okay"; -+}; -+ -+&u2phy1_otg { -+ status = "okay"; -+}; -+ - &u2phy2 { - status = "okay"; - }; -@@ -755,6 +763,10 @@ &u2phy3_host { - status = "okay"; - }; - -+&usbdp_phy1 { -+ status = "okay"; -+}; -+ - &usb_host0_ehci { - status = "okay"; - }; -@@ -771,6 +783,11 @@ &usb_host1_ohci { - status = "okay"; - }; - -+&usb_host1_xhci { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ - &usb_host2_xhci { - status = "okay"; - }; --- -Armbian - diff --git a/patch/kernel/rockchip-rk3588-edge/0135-phy-rockchip-Add-Samsung-HDMI-eDP-Combo-PHY-driver.patch b/patch/kernel/rockchip-rk3588-edge/0135-phy-rockchip-Add-Samsung-HDMI-eDP-Combo-PHY-driver.patch deleted file mode 100644 index b12c93356834..000000000000 --- a/patch/kernel/rockchip-rk3588-edge/0135-phy-rockchip-Add-Samsung-HDMI-eDP-Combo-PHY-driver.patch +++ /dev/null @@ -1,1091 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Wed, 14 Feb 2024 13:45:37 +0200 -Subject: phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver - -Add driver for the HDMI/eDP TX Combo PHY found on Rockchip RK3588 SoC. - -The PHY is based on a Samsung IP block and supports HDMI 2.1 TMDS, FRL -and eDP links. The maximum data rate is 12Gbps (FRL), while the minimum -is 250Mbps (TMDS). - -Only the TMDS link is currently supported. - -Co-developed-by: Algea Cao -Signed-off-by: Algea Cao -Tested-by: Heiko Stuebner -Signed-off-by: Cristian Ciocaltea ---- - drivers/phy/rockchip/Kconfig | 8 + - drivers/phy/rockchip/Makefile | 1 + - drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 1028 ++++++++++ - 3 files changed, 1037 insertions(+) - -diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig -index d21b458c1d18..c3d62243b474 100644 ---- a/drivers/phy/rockchip/Kconfig -+++ b/drivers/phy/rockchip/Kconfig -@@ -83,6 +83,14 @@ config PHY_ROCKCHIP_PCIE - help - Enable this to support the Rockchip PCIe PHY. - -+config PHY_ROCKCHIP_SAMSUNG_HDPTX -+ tristate "Rockchip Samsung HDMI/eDP Combo PHY driver" -+ depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF -+ select GENERIC_PHY -+ help -+ Enable this to support the Rockchip HDMI/eDP Combo PHY -+ with Samsung IP block. -+ - config PHY_ROCKCHIP_SNPS_PCIE3 - tristate "Rockchip Snps PCIe3 PHY Driver" - depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST -diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile -index 25d2e1355db7..010a824e32ce 100644 ---- a/drivers/phy/rockchip/Makefile -+++ b/drivers/phy/rockchip/Makefile -@@ -8,6 +8,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o - obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o - obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o - obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o -+obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX) += phy-rockchip-samsung-hdptx.o - obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o - obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o - obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o -diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c -new file mode 100644 -index 000000000000..946c01210ac8 ---- /dev/null -+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c -@@ -0,0 +1,1028 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+/* -+ * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd. -+ * Copyright (c) 2024 Collabora Ltd. -+ * -+ * Author: Algea Cao -+ * Author: Cristian Ciocaltea -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define GRF_HDPTX_CON0 0x00 -+#define HDPTX_I_PLL_EN BIT(7) -+#define HDPTX_I_BIAS_EN BIT(6) -+#define HDPTX_I_BGR_EN BIT(5) -+#define GRF_HDPTX_STATUS 0x80 -+#define HDPTX_O_PLL_LOCK_DONE BIT(3) -+#define HDPTX_O_PHY_CLK_RDY BIT(2) -+#define HDPTX_O_PHY_RDY BIT(1) -+#define HDPTX_O_SB_RDY BIT(0) -+ -+#define HDTPX_REG(_n, _min, _max) \ -+ ( \ -+ BUILD_BUG_ON_ZERO((0x##_n) < (0x##_min)) + \ -+ BUILD_BUG_ON_ZERO((0x##_n) > (0x##_max)) + \ -+ ((0x##_n) * 4) \ -+ ) -+ -+#define CMN_REG(n) HDTPX_REG(n, 0000, 00a7) -+#define SB_REG(n) HDTPX_REG(n, 0100, 0129) -+#define LNTOP_REG(n) HDTPX_REG(n, 0200, 0229) -+#define LANE_REG(n) HDTPX_REG(n, 0300, 062d) -+ -+/* CMN_REG(0008) */ -+#define LCPLL_EN_MASK BIT(6) -+#define LCPLL_LCVCO_MODE_EN_MASK BIT(4) -+/* CMN_REG(001e) */ -+#define LCPLL_PI_EN_MASK BIT(5) -+#define LCPLL_100M_CLK_EN_MASK BIT(0) -+/* CMN_REG(0025) */ -+#define LCPLL_PMS_IQDIV_RSTN BIT(4) -+/* CMN_REG(0028) */ -+#define LCPLL_SDC_FRAC_EN BIT(2) -+#define LCPLL_SDC_FRAC_RSTN BIT(0) -+/* CMN_REG(002d) */ -+#define LCPLL_SDC_N_MASK GENMASK(3, 1) -+/* CMN_REG(002e) */ -+#define LCPLL_SDC_NUMBERATOR_MASK GENMASK(5, 0) -+/* CMN_REG(002f) */ -+#define LCPLL_SDC_DENOMINATOR_MASK GENMASK(7, 2) -+#define LCPLL_SDC_NDIV_RSTN BIT(0) -+/* CMN_REG(003d) */ -+#define ROPLL_LCVCO_EN BIT(4) -+/* CMN_REG(004e) */ -+#define ROPLL_PI_EN BIT(5) -+/* CMN_REG(005c) */ -+#define ROPLL_PMS_IQDIV_RSTN BIT(5) -+/* CMN_REG(005e) */ -+#define ROPLL_SDM_EN_MASK BIT(6) -+#define ROPLL_SDM_FRAC_EN_RBR BIT(3) -+#define ROPLL_SDM_FRAC_EN_HBR BIT(2) -+#define ROPLL_SDM_FRAC_EN_HBR2 BIT(1) -+#define ROPLL_SDM_FRAC_EN_HBR3 BIT(0) -+/* CMN_REG(0064) */ -+#define ROPLL_SDM_NUM_SIGN_RBR_MASK BIT(3) -+/* CMN_REG(0069) */ -+#define ROPLL_SDC_N_RBR_MASK GENMASK(2, 0) -+/* CMN_REG(0074) */ -+#define ROPLL_SDC_NDIV_RSTN BIT(2) -+#define ROPLL_SSC_EN BIT(0) -+/* CMN_REG(0081) */ -+#define OVRD_PLL_CD_CLK_EN BIT(8) -+#define PLL_CD_HSCLK_EAST_EN BIT(0) -+/* CMN_REG(0086) */ -+#define PLL_PCG_POSTDIV_SEL_MASK GENMASK(7, 4) -+#define PLL_PCG_CLK_SEL_MASK GENMASK(3, 1) -+#define PLL_PCG_CLK_EN BIT(0) -+/* CMN_REG(0087) */ -+#define PLL_FRL_MODE_EN BIT(3) -+#define PLL_TX_HS_CLK_EN BIT(2) -+/* CMN_REG(0089) */ -+#define LCPLL_ALONE_MODE BIT(1) -+/* CMN_REG(0097) */ -+#define DIG_CLK_SEL BIT(1) -+#define ROPLL_REF BIT(1) -+#define LCPLL_REF 0 -+/* CMN_REG(0099) */ -+#define CMN_ROPLL_ALONE_MODE BIT(2) -+#define ROPLL_ALONE_MODE BIT(2) -+/* CMN_REG(009a) */ -+#define HS_SPEED_SEL BIT(0) -+#define DIV_10_CLOCK BIT(0) -+/* CMN_REG(009b) */ -+#define IS_SPEED_SEL BIT(4) -+#define LINK_SYMBOL_CLOCK BIT(4) -+#define LINK_SYMBOL_CLOCK1_2 0 -+ -+/* SB_REG(0102) */ -+#define OVRD_SB_RXTERM_EN_MASK BIT(5) -+#define SB_RXTERM_EN_MASK BIT(4) -+#define ANA_SB_RXTERM_OFFSP_MASK GENMASK(3, 0) -+/* SB_REG(0103) */ -+#define ANA_SB_RXTERM_OFFSN_MASK GENMASK(6, 3) -+#define OVRD_SB_RX_RESCAL_DONE_MASK BIT(1) -+#define SB_RX_RESCAL_DONE_MASK BIT(0) -+/* SB_REG(0104) */ -+#define OVRD_SB_EN_MASK BIT(5) -+#define SB_EN_MASK BIT(4) -+/* SB_REG(0105) */ -+#define OVRD_SB_EARC_CMDC_EN_MASK BIT(6) -+#define SB_EARC_CMDC_EN_MASK BIT(5) -+#define ANA_SB_TX_HLVL_PROG_MASK GENMASK(2, 0) -+/* SB_REG(0106) */ -+#define ANA_SB_TX_LLVL_PROG_MASK GENMASK(6, 4) -+/* SB_REG(0109) */ -+#define ANA_SB_DMRX_AFC_DIV_RATIO_MASK GENMASK(2, 0) -+/* SB_REG(010f) */ -+#define OVRD_SB_VREG_EN_MASK BIT(7) -+#define SB_VREG_EN_MASK BIT(6) -+#define OVRD_SB_VREG_LPF_BYPASS_MASK BIT(5) -+#define SB_VREG_LPF_BYPASS_MASK BIT(4) -+#define ANA_SB_VREG_GAIN_CTRL_MASK GENMASK(3, 0) -+/* SB_REG(0110) */ -+#define ANA_SB_VREG_REF_SEL_MASK BIT(0) -+/* SB_REG(0113) */ -+#define SB_RX_RCAL_OPT_CODE_MASK GENMASK(5, 4) -+#define SB_RX_RTERM_CTRL_MASK GENMASK(3, 0) -+/* SB_REG(0114) */ -+#define SB_TG_SB_EN_DELAY_TIME_MASK GENMASK(5, 3) -+#define SB_TG_RXTERM_EN_DELAY_TIME_MASK GENMASK(2, 0) -+/* SB_REG(0115) */ -+#define SB_READY_DELAY_TIME_MASK GENMASK(5, 3) -+#define SB_TG_OSC_EN_DELAY_TIME_MASK GENMASK(2, 0) -+/* SB_REG(0116) */ -+#define AFC_RSTN_DELAY_TIME_MASK GENMASK(6, 4) -+/* SB_REG(0117) */ -+#define FAST_PULSE_TIME_MASK GENMASK(3, 0) -+/* SB_REG(011b) */ -+#define SB_EARC_SIG_DET_BYPASS_MASK BIT(4) -+#define SB_AFC_TOL_MASK GENMASK(3, 0) -+/* SB_REG(011f) */ -+#define SB_PWM_AFC_CTRL_MASK GENMASK(7, 2) -+#define SB_RCAL_RSTN_MASK BIT(1) -+/* SB_REG(0120) */ -+#define SB_EARC_EN_MASK BIT(1) -+#define SB_EARC_AFC_EN_MASK BIT(2) -+/* SB_REG(0123) */ -+#define OVRD_SB_READY_MASK BIT(5) -+#define SB_READY_MASK BIT(4) -+ -+/* LNTOP_REG(0200) */ -+#define PROTOCOL_SEL BIT(2) -+#define HDMI_MODE BIT(2) -+#define HDMI_TMDS_FRL_SEL BIT(1) -+/* LNTOP_REG(0206) */ -+#define DATA_BUS_SEL BIT(0) -+#define DATA_BUS_36_40 BIT(0) -+/* LNTOP_REG(0207) */ -+#define LANE_EN 0xf -+#define ALL_LANE_EN 0xf -+ -+/* LANE_REG(0312) */ -+#define LN0_TX_SER_RATE_SEL_RBR BIT(5) -+#define LN0_TX_SER_RATE_SEL_HBR BIT(4) -+#define LN0_TX_SER_RATE_SEL_HBR2 BIT(3) -+#define LN0_TX_SER_RATE_SEL_HBR3 BIT(2) -+/* LANE_REG(0412) */ -+#define LN1_TX_SER_RATE_SEL_RBR BIT(5) -+#define LN1_TX_SER_RATE_SEL_HBR BIT(4) -+#define LN1_TX_SER_RATE_SEL_HBR2 BIT(3) -+#define LN1_TX_SER_RATE_SEL_HBR3 BIT(2) -+/* LANE_REG(0512) */ -+#define LN2_TX_SER_RATE_SEL_RBR BIT(5) -+#define LN2_TX_SER_RATE_SEL_HBR BIT(4) -+#define LN2_TX_SER_RATE_SEL_HBR2 BIT(3) -+#define LN2_TX_SER_RATE_SEL_HBR3 BIT(2) -+/* LANE_REG(0612) */ -+#define LN3_TX_SER_RATE_SEL_RBR BIT(5) -+#define LN3_TX_SER_RATE_SEL_HBR BIT(4) -+#define LN3_TX_SER_RATE_SEL_HBR2 BIT(3) -+#define LN3_TX_SER_RATE_SEL_HBR3 BIT(2) -+ -+struct lcpll_config { -+ u32 bit_rate; -+ u8 lcvco_mode_en; -+ u8 pi_en; -+ u8 clk_en_100m; -+ u8 pms_mdiv; -+ u8 pms_mdiv_afc; -+ u8 pms_pdiv; -+ u8 pms_refdiv; -+ u8 pms_sdiv; -+ u8 pi_cdiv_rstn; -+ u8 pi_cdiv_sel; -+ u8 sdm_en; -+ u8 sdm_rstn; -+ u8 sdc_frac_en; -+ u8 sdc_rstn; -+ u8 sdm_deno; -+ u8 sdm_num_sign; -+ u8 sdm_num; -+ u8 sdc_n; -+ u8 sdc_n2; -+ u8 sdc_num; -+ u8 sdc_deno; -+ u8 sdc_ndiv_rstn; -+ u8 ssc_en; -+ u8 ssc_fm_dev; -+ u8 ssc_fm_freq; -+ u8 ssc_clk_div_sel; -+ u8 cd_tx_ser_rate_sel; -+}; -+ -+struct ropll_config { -+ u32 bit_rate; -+ u8 pms_mdiv; -+ u8 pms_mdiv_afc; -+ u8 pms_pdiv; -+ u8 pms_refdiv; -+ u8 pms_sdiv; -+ u8 pms_iqdiv_rstn; -+ u8 ref_clk_sel; -+ u8 sdm_en; -+ u8 sdm_rstn; -+ u8 sdc_frac_en; -+ u8 sdc_rstn; -+ u8 sdm_clk_div; -+ u8 sdm_deno; -+ u8 sdm_num_sign; -+ u8 sdm_num; -+ u8 sdc_n; -+ u8 sdc_num; -+ u8 sdc_deno; -+ u8 sdc_ndiv_rstn; -+ u8 ssc_en; -+ u8 ssc_fm_dev; -+ u8 ssc_fm_freq; -+ u8 ssc_clk_div_sel; -+ u8 ana_cpp_ctrl; -+ u8 ana_lpf_c_sel; -+ u8 cd_tx_ser_rate_sel; -+}; -+ -+enum rk_hdptx_reset { -+ RST_PHY = 0, -+ RST_APB, -+ RST_INIT, -+ RST_CMN, -+ RST_LANE, -+ RST_ROPLL, -+ RST_LCPLL, -+ RST_MAX -+}; -+ -+struct rk_hdptx_phy { -+ struct device *dev; -+ struct regmap *regmap; -+ struct regmap *grf; -+ -+ struct phy *phy; -+ struct phy_config *phy_cfg; -+ struct clk_bulk_data *clks; -+ int nr_clks; -+ struct reset_control_bulk_data rsts[RST_MAX]; -+}; -+ -+static const struct ropll_config ropll_tmds_cfg[] = { -+ { 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, -+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 3712500, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, -+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 2970000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, -+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 1620000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10, -+ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 1856250, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, -+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 1540000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1, -+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 1485000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5, -+ 0x10, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 1462500, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1, -+ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 1190000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1, -+ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 1065000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1, -+ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 1080000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0, -+ 0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 855000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1, -+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 835000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0, -+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 928125, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, -+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 742500, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, -+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1, -+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5, -+ 1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0, -+ 0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 270000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0, -+ 0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+ { 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1, -+ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, -+}; -+ -+static const struct reg_sequence rk_hdtpx_common_cmn_init_seq[] = { -+ REG_SEQ0(CMN_REG(0009), 0x0c), -+ REG_SEQ0(CMN_REG(000a), 0x83), -+ REG_SEQ0(CMN_REG(000b), 0x06), -+ REG_SEQ0(CMN_REG(000c), 0x20), -+ REG_SEQ0(CMN_REG(000d), 0xb8), -+ REG_SEQ0(CMN_REG(000e), 0x0f), -+ REG_SEQ0(CMN_REG(000f), 0x0f), -+ REG_SEQ0(CMN_REG(0010), 0x04), -+ REG_SEQ0(CMN_REG(0011), 0x00), -+ REG_SEQ0(CMN_REG(0012), 0x26), -+ REG_SEQ0(CMN_REG(0013), 0x22), -+ REG_SEQ0(CMN_REG(0014), 0x24), -+ REG_SEQ0(CMN_REG(0015), 0x77), -+ REG_SEQ0(CMN_REG(0016), 0x08), -+ REG_SEQ0(CMN_REG(0017), 0x00), -+ REG_SEQ0(CMN_REG(0018), 0x04), -+ REG_SEQ0(CMN_REG(0019), 0x48), -+ REG_SEQ0(CMN_REG(001a), 0x01), -+ REG_SEQ0(CMN_REG(001b), 0x00), -+ REG_SEQ0(CMN_REG(001c), 0x01), -+ REG_SEQ0(CMN_REG(001d), 0x64), -+ REG_SEQ0(CMN_REG(001f), 0x00), -+ REG_SEQ0(CMN_REG(0026), 0x53), -+ REG_SEQ0(CMN_REG(0029), 0x01), -+ REG_SEQ0(CMN_REG(0030), 0x00), -+ REG_SEQ0(CMN_REG(0031), 0x20), -+ REG_SEQ0(CMN_REG(0032), 0x30), -+ REG_SEQ0(CMN_REG(0033), 0x0b), -+ REG_SEQ0(CMN_REG(0034), 0x23), -+ REG_SEQ0(CMN_REG(0035), 0x00), -+ REG_SEQ0(CMN_REG(0038), 0x00), -+ REG_SEQ0(CMN_REG(0039), 0x00), -+ REG_SEQ0(CMN_REG(003a), 0x00), -+ REG_SEQ0(CMN_REG(003b), 0x00), -+ REG_SEQ0(CMN_REG(003c), 0x80), -+ REG_SEQ0(CMN_REG(003e), 0x0c), -+ REG_SEQ0(CMN_REG(003f), 0x83), -+ REG_SEQ0(CMN_REG(0040), 0x06), -+ REG_SEQ0(CMN_REG(0041), 0x20), -+ REG_SEQ0(CMN_REG(0042), 0xb8), -+ REG_SEQ0(CMN_REG(0043), 0x00), -+ REG_SEQ0(CMN_REG(0044), 0x46), -+ REG_SEQ0(CMN_REG(0045), 0x24), -+ REG_SEQ0(CMN_REG(0046), 0xff), -+ REG_SEQ0(CMN_REG(0047), 0x00), -+ REG_SEQ0(CMN_REG(0048), 0x44), -+ REG_SEQ0(CMN_REG(0049), 0xfa), -+ REG_SEQ0(CMN_REG(004a), 0x08), -+ REG_SEQ0(CMN_REG(004b), 0x00), -+ REG_SEQ0(CMN_REG(004c), 0x01), -+ REG_SEQ0(CMN_REG(004d), 0x64), -+ REG_SEQ0(CMN_REG(004e), 0x14), -+ REG_SEQ0(CMN_REG(004f), 0x00), -+ REG_SEQ0(CMN_REG(0050), 0x00), -+ REG_SEQ0(CMN_REG(005d), 0x0c), -+ REG_SEQ0(CMN_REG(005f), 0x01), -+ REG_SEQ0(CMN_REG(006b), 0x04), -+ REG_SEQ0(CMN_REG(0073), 0x30), -+ REG_SEQ0(CMN_REG(0074), 0x00), -+ REG_SEQ0(CMN_REG(0075), 0x20), -+ REG_SEQ0(CMN_REG(0076), 0x30), -+ REG_SEQ0(CMN_REG(0077), 0x08), -+ REG_SEQ0(CMN_REG(0078), 0x0c), -+ REG_SEQ0(CMN_REG(0079), 0x00), -+ REG_SEQ0(CMN_REG(007b), 0x00), -+ REG_SEQ0(CMN_REG(007c), 0x00), -+ REG_SEQ0(CMN_REG(007d), 0x00), -+ REG_SEQ0(CMN_REG(007e), 0x00), -+ REG_SEQ0(CMN_REG(007f), 0x00), -+ REG_SEQ0(CMN_REG(0080), 0x00), -+ REG_SEQ0(CMN_REG(0081), 0x09), -+ REG_SEQ0(CMN_REG(0082), 0x04), -+ REG_SEQ0(CMN_REG(0083), 0x24), -+ REG_SEQ0(CMN_REG(0084), 0x20), -+ REG_SEQ0(CMN_REG(0085), 0x03), -+ REG_SEQ0(CMN_REG(0086), 0x01), -+ REG_SEQ0(CMN_REG(0087), 0x0c), -+ REG_SEQ0(CMN_REG(008a), 0x55), -+ REG_SEQ0(CMN_REG(008b), 0x25), -+ REG_SEQ0(CMN_REG(008c), 0x2c), -+ REG_SEQ0(CMN_REG(008d), 0x22), -+ REG_SEQ0(CMN_REG(008e), 0x14), -+ REG_SEQ0(CMN_REG(008f), 0x20), -+ REG_SEQ0(CMN_REG(0090), 0x00), -+ REG_SEQ0(CMN_REG(0091), 0x00), -+ REG_SEQ0(CMN_REG(0092), 0x00), -+ REG_SEQ0(CMN_REG(0093), 0x00), -+ REG_SEQ0(CMN_REG(009a), 0x11), -+ REG_SEQ0(CMN_REG(009b), 0x10), -+}; -+ -+static const struct reg_sequence rk_hdtpx_tmds_cmn_init_seq[] = { -+ REG_SEQ0(CMN_REG(0008), 0x00), -+ REG_SEQ0(CMN_REG(0011), 0x01), -+ REG_SEQ0(CMN_REG(0017), 0x20), -+ REG_SEQ0(CMN_REG(001e), 0x14), -+ REG_SEQ0(CMN_REG(0020), 0x00), -+ REG_SEQ0(CMN_REG(0021), 0x00), -+ REG_SEQ0(CMN_REG(0022), 0x11), -+ REG_SEQ0(CMN_REG(0023), 0x00), -+ REG_SEQ0(CMN_REG(0024), 0x00), -+ REG_SEQ0(CMN_REG(0025), 0x53), -+ REG_SEQ0(CMN_REG(0026), 0x00), -+ REG_SEQ0(CMN_REG(0027), 0x00), -+ REG_SEQ0(CMN_REG(0028), 0x01), -+ REG_SEQ0(CMN_REG(002a), 0x00), -+ REG_SEQ0(CMN_REG(002b), 0x00), -+ REG_SEQ0(CMN_REG(002c), 0x00), -+ REG_SEQ0(CMN_REG(002d), 0x00), -+ REG_SEQ0(CMN_REG(002e), 0x04), -+ REG_SEQ0(CMN_REG(002f), 0x00), -+ REG_SEQ0(CMN_REG(0030), 0x20), -+ REG_SEQ0(CMN_REG(0031), 0x30), -+ REG_SEQ0(CMN_REG(0032), 0x0b), -+ REG_SEQ0(CMN_REG(0033), 0x23), -+ REG_SEQ0(CMN_REG(0034), 0x00), -+ REG_SEQ0(CMN_REG(003d), 0x40), -+ REG_SEQ0(CMN_REG(0042), 0x78), -+ REG_SEQ0(CMN_REG(004e), 0x34), -+ REG_SEQ0(CMN_REG(005c), 0x25), -+ REG_SEQ0(CMN_REG(005e), 0x4f), -+ REG_SEQ0(CMN_REG(0074), 0x04), -+ REG_SEQ0(CMN_REG(0081), 0x01), -+ REG_SEQ0(CMN_REG(0087), 0x04), -+ REG_SEQ0(CMN_REG(0089), 0x00), -+ REG_SEQ0(CMN_REG(0095), 0x00), -+ REG_SEQ0(CMN_REG(0097), 0x02), -+ REG_SEQ0(CMN_REG(0099), 0x04), -+ REG_SEQ0(CMN_REG(009b), 0x00), -+}; -+ -+static const struct reg_sequence rk_hdtpx_common_sb_init_seq[] = { -+ REG_SEQ0(SB_REG(0114), 0x00), -+ REG_SEQ0(SB_REG(0115), 0x00), -+ REG_SEQ0(SB_REG(0116), 0x00), -+ REG_SEQ0(SB_REG(0117), 0x00), -+}; -+ -+static const struct reg_sequence rk_hdtpx_tmds_lntop_highbr_seq[] = { -+ REG_SEQ0(LNTOP_REG(0201), 0x00), -+ REG_SEQ0(LNTOP_REG(0202), 0x00), -+ REG_SEQ0(LNTOP_REG(0203), 0x0f), -+ REG_SEQ0(LNTOP_REG(0204), 0xff), -+ REG_SEQ0(LNTOP_REG(0205), 0xff), -+}; -+ -+static const struct reg_sequence rk_hdtpx_tmds_lntop_lowbr_seq[] = { -+ REG_SEQ0(LNTOP_REG(0201), 0x07), -+ REG_SEQ0(LNTOP_REG(0202), 0xc1), -+ REG_SEQ0(LNTOP_REG(0203), 0xf0), -+ REG_SEQ0(LNTOP_REG(0204), 0x7c), -+ REG_SEQ0(LNTOP_REG(0205), 0x1f), -+}; -+ -+static const struct reg_sequence rk_hdtpx_common_lane_init_seq[] = { -+ REG_SEQ0(LANE_REG(0303), 0x0c), -+ REG_SEQ0(LANE_REG(0307), 0x20), -+ REG_SEQ0(LANE_REG(030a), 0x17), -+ REG_SEQ0(LANE_REG(030b), 0x77), -+ REG_SEQ0(LANE_REG(030c), 0x77), -+ REG_SEQ0(LANE_REG(030d), 0x77), -+ REG_SEQ0(LANE_REG(030e), 0x38), -+ REG_SEQ0(LANE_REG(0310), 0x03), -+ REG_SEQ0(LANE_REG(0311), 0x0f), -+ REG_SEQ0(LANE_REG(0316), 0x02), -+ REG_SEQ0(LANE_REG(031b), 0x01), -+ REG_SEQ0(LANE_REG(031f), 0x15), -+ REG_SEQ0(LANE_REG(0320), 0xa0), -+ REG_SEQ0(LANE_REG(0403), 0x0c), -+ REG_SEQ0(LANE_REG(0407), 0x20), -+ REG_SEQ0(LANE_REG(040a), 0x17), -+ REG_SEQ0(LANE_REG(040b), 0x77), -+ REG_SEQ0(LANE_REG(040c), 0x77), -+ REG_SEQ0(LANE_REG(040d), 0x77), -+ REG_SEQ0(LANE_REG(040e), 0x38), -+ REG_SEQ0(LANE_REG(0410), 0x03), -+ REG_SEQ0(LANE_REG(0411), 0x0f), -+ REG_SEQ0(LANE_REG(0416), 0x02), -+ REG_SEQ0(LANE_REG(041b), 0x01), -+ REG_SEQ0(LANE_REG(041f), 0x15), -+ REG_SEQ0(LANE_REG(0420), 0xa0), -+ REG_SEQ0(LANE_REG(0503), 0x0c), -+ REG_SEQ0(LANE_REG(0507), 0x20), -+ REG_SEQ0(LANE_REG(050a), 0x17), -+ REG_SEQ0(LANE_REG(050b), 0x77), -+ REG_SEQ0(LANE_REG(050c), 0x77), -+ REG_SEQ0(LANE_REG(050d), 0x77), -+ REG_SEQ0(LANE_REG(050e), 0x38), -+ REG_SEQ0(LANE_REG(0510), 0x03), -+ REG_SEQ0(LANE_REG(0511), 0x0f), -+ REG_SEQ0(LANE_REG(0516), 0x02), -+ REG_SEQ0(LANE_REG(051b), 0x01), -+ REG_SEQ0(LANE_REG(051f), 0x15), -+ REG_SEQ0(LANE_REG(0520), 0xa0), -+ REG_SEQ0(LANE_REG(0603), 0x0c), -+ REG_SEQ0(LANE_REG(0607), 0x20), -+ REG_SEQ0(LANE_REG(060a), 0x17), -+ REG_SEQ0(LANE_REG(060b), 0x77), -+ REG_SEQ0(LANE_REG(060c), 0x77), -+ REG_SEQ0(LANE_REG(060d), 0x77), -+ REG_SEQ0(LANE_REG(060e), 0x38), -+ REG_SEQ0(LANE_REG(0610), 0x03), -+ REG_SEQ0(LANE_REG(0611), 0x0f), -+ REG_SEQ0(LANE_REG(0616), 0x02), -+ REG_SEQ0(LANE_REG(061b), 0x01), -+ REG_SEQ0(LANE_REG(061f), 0x15), -+ REG_SEQ0(LANE_REG(0620), 0xa0), -+}; -+ -+static const struct reg_sequence rk_hdtpx_tmds_lane_init_seq[] = { -+ REG_SEQ0(LANE_REG(0312), 0x00), -+ REG_SEQ0(LANE_REG(031e), 0x00), -+ REG_SEQ0(LANE_REG(0412), 0x00), -+ REG_SEQ0(LANE_REG(041e), 0x00), -+ REG_SEQ0(LANE_REG(0512), 0x00), -+ REG_SEQ0(LANE_REG(051e), 0x00), -+ REG_SEQ0(LANE_REG(0612), 0x00), -+ REG_SEQ0(LANE_REG(061e), 0x08), -+ REG_SEQ0(LANE_REG(0303), 0x2f), -+ REG_SEQ0(LANE_REG(0403), 0x2f), -+ REG_SEQ0(LANE_REG(0503), 0x2f), -+ REG_SEQ0(LANE_REG(0603), 0x2f), -+ REG_SEQ0(LANE_REG(0305), 0x03), -+ REG_SEQ0(LANE_REG(0405), 0x03), -+ REG_SEQ0(LANE_REG(0505), 0x03), -+ REG_SEQ0(LANE_REG(0605), 0x03), -+ REG_SEQ0(LANE_REG(0306), 0x1c), -+ REG_SEQ0(LANE_REG(0406), 0x1c), -+ REG_SEQ0(LANE_REG(0506), 0x1c), -+ REG_SEQ0(LANE_REG(0606), 0x1c), -+}; -+ -+static bool rk_hdptx_phy_is_rw_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case 0x0000 ... 0x029c: -+ case 0x0400 ... 0x04a4: -+ case 0x0800 ... 0x08a4: -+ case 0x0c00 ... 0x0cb4: -+ case 0x1000 ... 0x10b4: -+ case 0x1400 ... 0x14b4: -+ case 0x1800 ... 0x18b4: -+ return true; -+ } -+ -+ return false; -+} -+ -+static const struct regmap_config rk_hdptx_phy_regmap_config = { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .writeable_reg = rk_hdptx_phy_is_rw_reg, -+ .readable_reg = rk_hdptx_phy_is_rw_reg, -+ .fast_io = true, -+ .max_register = 0x18b4, -+}; -+ -+#define rk_hdptx_multi_reg_write(hdptx, seq) \ -+ regmap_multi_reg_write((hdptx)->regmap, seq, ARRAY_SIZE(seq)) -+ -+static void rk_hdptx_pre_power_up(struct rk_hdptx_phy *hdptx) -+{ -+ u32 val; -+ -+ reset_control_assert(hdptx->rsts[RST_APB].rstc); -+ usleep_range(20, 25); -+ reset_control_deassert(hdptx->rsts[RST_APB].rstc); -+ -+ reset_control_assert(hdptx->rsts[RST_LANE].rstc); -+ reset_control_assert(hdptx->rsts[RST_CMN].rstc); -+ reset_control_assert(hdptx->rsts[RST_INIT].rstc); -+ -+ val = (HDPTX_I_PLL_EN | HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16; -+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); -+} -+ -+static int rk_hdptx_post_enable_lane(struct rk_hdptx_phy *hdptx) -+{ -+ u32 val; -+ int ret; -+ -+ reset_control_deassert(hdptx->rsts[RST_LANE].rstc); -+ -+ val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 | -+ HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN; -+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); -+ -+ ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val, -+ (val & HDPTX_O_PHY_RDY) && -+ (val & HDPTX_O_PLL_LOCK_DONE), -+ 100, 5000); -+ if (ret) { -+ dev_err(hdptx->dev, "Failed to get PHY lane lock: %d\n", ret); -+ return ret; -+ } -+ -+ dev_dbg(hdptx->dev, "PHY lane locked\n"); -+ -+ return 0; -+} -+ -+static int rk_hdptx_post_enable_pll(struct rk_hdptx_phy *hdptx) -+{ -+ u32 val; -+ int ret; -+ -+ val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 | -+ HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN; -+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); -+ -+ usleep_range(10, 15); -+ reset_control_deassert(hdptx->rsts[RST_INIT].rstc); -+ -+ usleep_range(10, 15); -+ val = HDPTX_I_PLL_EN << 16 | HDPTX_I_PLL_EN; -+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); -+ -+ usleep_range(10, 15); -+ reset_control_deassert(hdptx->rsts[RST_CMN].rstc); -+ -+ ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val, -+ val & HDPTX_O_PHY_CLK_RDY, 20, 400); -+ if (ret) { -+ dev_err(hdptx->dev, "Failed to get PHY clk ready: %d\n", ret); -+ return ret; -+ } -+ -+ dev_dbg(hdptx->dev, "PHY clk ready\n"); -+ -+ return 0; -+} -+ -+static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx) -+{ -+ u32 val; -+ -+ /* reset phy and apb, or phy locked flag may keep 1 */ -+ reset_control_assert(hdptx->rsts[RST_PHY].rstc); -+ usleep_range(20, 30); -+ reset_control_deassert(hdptx->rsts[RST_PHY].rstc); -+ -+ reset_control_assert(hdptx->rsts[RST_APB].rstc); -+ usleep_range(20, 30); -+ reset_control_deassert(hdptx->rsts[RST_APB].rstc); -+ -+ regmap_write(hdptx->regmap, LANE_REG(0300), 0x82); -+ regmap_write(hdptx->regmap, SB_REG(010f), 0xc1); -+ regmap_write(hdptx->regmap, SB_REG(0110), 0x1); -+ regmap_write(hdptx->regmap, LANE_REG(0301), 0x80); -+ regmap_write(hdptx->regmap, LANE_REG(0401), 0x80); -+ regmap_write(hdptx->regmap, LANE_REG(0501), 0x80); -+ regmap_write(hdptx->regmap, LANE_REG(0601), 0x80); -+ -+ reset_control_assert(hdptx->rsts[RST_LANE].rstc); -+ reset_control_assert(hdptx->rsts[RST_CMN].rstc); -+ reset_control_assert(hdptx->rsts[RST_INIT].rstc); -+ -+ val = (HDPTX_I_PLL_EN | HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16; -+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); -+} -+ -+static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate, -+ struct ropll_config *cfg) -+{ -+ const unsigned int fout = data_rate / 2, fref = 24000; -+ unsigned long k = 0, lc, k_sub, lc_sub; -+ unsigned int fvco, sdc; -+ u32 mdiv, sdiv, n = 8; -+ -+ if (fout > 0xfffffff) -+ return false; -+ -+ for (sdiv = 16; sdiv >= 1; sdiv--) { -+ if (sdiv % 2 && sdiv != 1) -+ continue; -+ -+ fvco = fout * sdiv; -+ -+ if (fvco < 2000000 || fvco > 4000000) -+ continue; -+ -+ mdiv = DIV_ROUND_UP(fvco, fref); -+ if (mdiv < 20 || mdiv > 255) -+ continue; -+ -+ if (fref * mdiv - fvco) { -+ for (sdc = 264000; sdc <= 750000; sdc += fref) -+ if (sdc * n > fref * mdiv) -+ break; -+ -+ if (sdc > 750000) -+ continue; -+ -+ rational_best_approximation(fref * mdiv - fvco, -+ sdc / 16, -+ GENMASK(6, 0), -+ GENMASK(7, 0), -+ &k, &lc); -+ -+ rational_best_approximation(sdc * n - fref * mdiv, -+ sdc, -+ GENMASK(6, 0), -+ GENMASK(7, 0), -+ &k_sub, &lc_sub); -+ } -+ -+ break; -+ } -+ -+ if (sdiv < 1) -+ return false; -+ -+ if (cfg) { -+ cfg->pms_mdiv = mdiv; -+ cfg->pms_mdiv_afc = mdiv; -+ cfg->pms_pdiv = 1; -+ cfg->pms_refdiv = 1; -+ cfg->pms_sdiv = sdiv - 1; -+ -+ cfg->sdm_en = k > 0 ? 1 : 0; -+ if (cfg->sdm_en) { -+ cfg->sdm_deno = lc; -+ cfg->sdm_num_sign = 1; -+ cfg->sdm_num = k; -+ cfg->sdc_n = n - 3; -+ cfg->sdc_num = k_sub; -+ cfg->sdc_deno = lc_sub; -+ } -+ } -+ -+ return true; -+} -+ -+static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, -+ unsigned int rate) -+{ -+ const struct ropll_config *cfg = NULL; -+ struct ropll_config rc = {0}; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) -+ if (rate == ropll_tmds_cfg[i].bit_rate) { -+ cfg = &ropll_tmds_cfg[i]; -+ break; -+ } -+ -+ if (!cfg) { -+ if (rk_hdptx_phy_clk_pll_calc(rate, &rc)) { -+ cfg = &rc; -+ } else { -+ dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__); -+ return -EINVAL; -+ } -+ } -+ -+ dev_dbg(hdptx->dev, "mdiv=%u, sdiv=%u, sdm_en=%u, k_sign=%u, k=%u, lc=%u\n", -+ cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en, -+ cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno); -+ -+ rk_hdptx_pre_power_up(hdptx); -+ -+ reset_control_assert(hdptx->rsts[RST_ROPLL].rstc); -+ usleep_range(20, 30); -+ reset_control_deassert(hdptx->rsts[RST_ROPLL].rstc); -+ -+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_cmn_init_seq); -+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_cmn_init_seq); -+ -+ regmap_write(hdptx->regmap, CMN_REG(0051), cfg->pms_mdiv); -+ regmap_write(hdptx->regmap, CMN_REG(0055), cfg->pms_mdiv_afc); -+ regmap_write(hdptx->regmap, CMN_REG(0059), -+ (cfg->pms_pdiv << 4) | cfg->pms_refdiv); -+ regmap_write(hdptx->regmap, CMN_REG(005a), cfg->pms_sdiv << 4); -+ -+ regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDM_EN_MASK, -+ FIELD_PREP(ROPLL_SDM_EN_MASK, cfg->sdm_en)); -+ if (!cfg->sdm_en) -+ regmap_update_bits(hdptx->regmap, CMN_REG(005e), 0xf, 0); -+ -+ regmap_update_bits(hdptx->regmap, CMN_REG(0064), ROPLL_SDM_NUM_SIGN_RBR_MASK, -+ FIELD_PREP(ROPLL_SDM_NUM_SIGN_RBR_MASK, cfg->sdm_num_sign)); -+ -+ regmap_write(hdptx->regmap, CMN_REG(0060), cfg->sdm_deno); -+ regmap_write(hdptx->regmap, CMN_REG(0065), cfg->sdm_num); -+ -+ regmap_update_bits(hdptx->regmap, CMN_REG(0069), ROPLL_SDC_N_RBR_MASK, -+ FIELD_PREP(ROPLL_SDC_N_RBR_MASK, cfg->sdc_n)); -+ -+ regmap_write(hdptx->regmap, CMN_REG(006c), cfg->sdc_num); -+ regmap_write(hdptx->regmap, CMN_REG(0070), cfg->sdc_deno); -+ -+ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK, -+ FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv)); -+ -+ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN, -+ PLL_PCG_CLK_EN); -+ -+ return rk_hdptx_post_enable_pll(hdptx); -+} -+ -+static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, -+ unsigned int rate) -+{ -+ u32 val; -+ int ret; -+ -+ ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); -+ if (ret) -+ return ret; -+ -+ if (!(val & HDPTX_O_PLL_LOCK_DONE)) { -+ ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate); -+ if (ret) -+ return ret; -+ } -+ -+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq); -+ -+ regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06); -+ -+ if (rate >= 3400000) { -+ /* For 1/40 bitrate clk */ -+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq); -+ } else { -+ /* For 1/10 bitrate clk */ -+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_lowbr_seq); -+ } -+ -+ regmap_write(hdptx->regmap, LNTOP_REG(0206), 0x07); -+ regmap_write(hdptx->regmap, LNTOP_REG(0207), 0x0f); -+ -+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_lane_init_seq); -+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lane_init_seq); -+ -+ return rk_hdptx_post_enable_lane(hdptx); -+} -+ -+static int rk_hdptx_phy_power_on(struct phy *phy) -+{ -+ struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); -+ int ret, bus_width = phy_get_bus_width(hdptx->phy); -+ /* -+ * FIXME: Temporary workaround to pass pixel_clk_rate -+ * from the HDMI bridge driver until phy_configure_opts_hdmi -+ * becomes available in the PHY API. -+ */ -+ unsigned int rate = bus_width & 0xfffffff; -+ -+ dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n", -+ __func__, bus_width, rate); -+ -+ ret = pm_runtime_resume_and_get(hdptx->dev); -+ if (ret) { -+ dev_err(hdptx->dev, "Failed to resume phy: %d\n", ret); -+ return ret; -+ } -+ -+ ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate); -+ if (ret) -+ pm_runtime_put(hdptx->dev); -+ -+ return ret; -+} -+ -+static int rk_hdptx_phy_power_off(struct phy *phy) -+{ -+ struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); -+ u32 val; -+ int ret; -+ -+ ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); -+ if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) -+ rk_hdptx_phy_disable(hdptx); -+ -+ pm_runtime_put(hdptx->dev); -+ -+ return ret; -+} -+ -+static const struct phy_ops rk_hdptx_phy_ops = { -+ .power_on = rk_hdptx_phy_power_on, -+ .power_off = rk_hdptx_phy_power_off, -+ .owner = THIS_MODULE, -+}; -+ -+static int rk_hdptx_phy_runtime_suspend(struct device *dev) -+{ -+ struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev); -+ -+ clk_bulk_disable_unprepare(hdptx->nr_clks, hdptx->clks); -+ -+ return 0; -+} -+ -+static int rk_hdptx_phy_runtime_resume(struct device *dev) -+{ -+ struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = clk_bulk_prepare_enable(hdptx->nr_clks, hdptx->clks); -+ if (ret) -+ dev_err(hdptx->dev, "Failed to enable clocks: %d\n", ret); -+ -+ return ret; -+} -+ -+static int rk_hdptx_phy_probe(struct platform_device *pdev) -+{ -+ struct phy_provider *phy_provider; -+ struct device *dev = &pdev->dev; -+ struct rk_hdptx_phy *hdptx; -+ void __iomem *regs; -+ int ret; -+ -+ hdptx = devm_kzalloc(dev, sizeof(*hdptx), GFP_KERNEL); -+ if (!hdptx) -+ return -ENOMEM; -+ -+ hdptx->dev = dev; -+ -+ regs = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(regs)) -+ return dev_err_probe(dev, PTR_ERR(regs), -+ "Failed to ioremap resource\n"); -+ -+ ret = devm_clk_bulk_get_all(dev, &hdptx->clks); -+ if (ret < 0) -+ return dev_err_probe(dev, ret, "Failed to get clocks\n"); -+ if (ret == 0) -+ return dev_err_probe(dev, -EINVAL, "Missing clocks\n"); -+ -+ hdptx->nr_clks = ret; -+ -+ hdptx->regmap = devm_regmap_init_mmio(dev, regs, -+ &rk_hdptx_phy_regmap_config); -+ if (IS_ERR(hdptx->regmap)) -+ return dev_err_probe(dev, PTR_ERR(hdptx->regmap), -+ "Failed to init regmap\n"); -+ -+ hdptx->rsts[RST_PHY].id = "phy"; -+ hdptx->rsts[RST_APB].id = "apb"; -+ hdptx->rsts[RST_INIT].id = "init"; -+ hdptx->rsts[RST_CMN].id = "cmn"; -+ hdptx->rsts[RST_LANE].id = "lane"; -+ hdptx->rsts[RST_ROPLL].id = "ropll"; -+ hdptx->rsts[RST_LCPLL].id = "lcpll"; -+ -+ ret = devm_reset_control_bulk_get_exclusive(dev, RST_MAX, hdptx->rsts); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to get resets\n"); -+ -+ hdptx->grf = syscon_regmap_lookup_by_phandle(dev->of_node, -+ "rockchip,grf"); -+ if (IS_ERR(hdptx->grf)) -+ return dev_err_probe(dev, PTR_ERR(hdptx->grf), -+ "Could not get GRF syscon\n"); -+ -+ hdptx->phy = devm_phy_create(dev, NULL, &rk_hdptx_phy_ops); -+ if (IS_ERR(hdptx->phy)) -+ return dev_err_probe(dev, PTR_ERR(hdptx->phy), -+ "Failed to create HDMI PHY\n"); -+ -+ platform_set_drvdata(pdev, hdptx); -+ phy_set_drvdata(hdptx->phy, hdptx); -+ phy_set_bus_width(hdptx->phy, 8); -+ -+ ret = devm_pm_runtime_enable(dev); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); -+ -+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); -+ if (IS_ERR(phy_provider)) -+ return dev_err_probe(dev, PTR_ERR(phy_provider), -+ "Failed to register PHY provider\n"); -+ -+ reset_control_deassert(hdptx->rsts[RST_APB].rstc); -+ reset_control_deassert(hdptx->rsts[RST_CMN].rstc); -+ reset_control_deassert(hdptx->rsts[RST_INIT].rstc); -+ -+ return 0; -+} -+ -+static const struct dev_pm_ops rk_hdptx_phy_pm_ops = { -+ RUNTIME_PM_OPS(rk_hdptx_phy_runtime_suspend, -+ rk_hdptx_phy_runtime_resume, NULL) -+}; -+ -+static const struct of_device_id rk_hdptx_phy_of_match[] = { -+ { .compatible = "rockchip,rk3588-hdptx-phy", }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, rk_hdptx_phy_of_match); -+ -+static struct platform_driver rk_hdptx_phy_driver = { -+ .probe = rk_hdptx_phy_probe, -+ .driver = { -+ .name = "rockchip-hdptx-phy", -+ .pm = &rk_hdptx_phy_pm_ops, -+ .of_match_table = rk_hdptx_phy_of_match, -+ }, -+}; -+module_platform_driver(rk_hdptx_phy_driver); -+ -+MODULE_AUTHOR("Algea Cao "); -+MODULE_AUTHOR("Cristian Ciocaltea "); -+MODULE_DESCRIPTION("Samsung HDMI/eDP Transmitter Combo PHY Driver"); -+MODULE_LICENSE("GPL"); --- -Armbian - diff --git a/patch/kernel/rockchip-rk3588-edge/0136-arm64-dts-rockchip-Add-HDMI0-PHY-to-rk3588.patch b/patch/kernel/rockchip-rk3588-edge/0136-arm64-dts-rockchip-Add-HDMI0-PHY-to-rk3588.patch deleted file mode 100644 index c3e0c43c3c7a..000000000000 --- a/patch/kernel/rockchip-rk3588-edge/0136-arm64-dts-rockchip-Add-HDMI0-PHY-to-rk3588.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Cristian Ciocaltea -Date: Mon, 19 Feb 2024 22:46:25 +0200 -Subject: arm64: dts: rockchip: Add HDMI0 PHY to rk3588 - -Add DT nodes for HDMI0 PHY and related syscon found on RK3588 SoC. - -Signed-off-by: Cristian Ciocaltea ---- - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 21 ++++++++++ - 1 file changed, 21 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index c7a912617b79..ca34e95b8008 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -859,6 +859,11 @@ u2phy3_host: host-port { - }; - }; - -+ hdptxphy0_grf: syscon@fd5e0000 { -+ compatible = "rockchip,rk3588-hdptxphy-grf", "syscon"; -+ reg = <0x0 0xfd5e0000 0x0 0x100>; -+ }; -+ - ioc: syscon@fd5f0000 { - compatible = "rockchip,rk3588-ioc", "syscon"; - reg = <0x0 0xfd5f0000 0x0 0x10000>; -@@ -2848,6 +2853,22 @@ usbdp_phy0: phy@fed80000 { - status = "disabled"; - }; - -+ hdptxphy_hdmi0: phy@fed60000 { -+ compatible = "rockchip,rk3588-hdptx-phy"; -+ reg = <0x0 0xfed60000 0x0 0x2000>; -+ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>; -+ clock-names = "ref", "apb"; -+ #phy-cells = <0>; -+ resets = <&cru SRST_HDPTX0>, <&cru SRST_P_HDPTX0>, -+ <&cru SRST_HDPTX0_INIT>, <&cru SRST_HDPTX0_CMN>, -+ <&cru SRST_HDPTX0_LANE>, <&cru SRST_HDPTX0_ROPLL>, -+ <&cru SRST_HDPTX0_LCPLL>; -+ reset-names = "phy", "apb", "init", "cmn", "lane", "ropll", -+ "lcpll"; -+ rockchip,grf = <&hdptxphy0_grf>; -+ status = "disabled"; -+ }; -+ - combphy0_ps: phy@fee00000 { - compatible = "rockchip,rk3588-naneng-combphy"; - reg = <0x0 0xfee00000 0x0 0x100>; --- -Armbian - diff --git a/patch/kernel/rockchip-rk3588-edge/0141-panthor-v6.patch b/patch/kernel/rockchip-rk3588-edge/0141-panthor-v6.patch deleted file mode 100644 index bffe36dcd80f..000000000000 --- a/patch/kernel/rockchip-rk3588-edge/0141-panthor-v6.patch +++ /dev/null @@ -1,14855 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:15 +0100 -Subject: drm/panthor: Add uAPI - -Panthor follows the lead of other recently submitted drivers with -ioctls allowing us to support modern Vulkan features, like sparse memory -binding: - -- Pretty standard GEM management ioctls (BO_CREATE and BO_MMAP_OFFSET), - with the 'exclusive-VM' bit to speed-up BO reservation on job submission -- VM management ioctls (VM_CREATE, VM_DESTROY and VM_BIND). The VM_BIND - ioctl is loosely based on the Xe model, and can handle both - asynchronous and synchronous requests -- GPU execution context creation/destruction, tiler heap context creation - and job submission. Those ioctls reflect how the hardware/scheduler - works and are thus driver specific. - -We also have a way to expose IO regions, such that the usermode driver -can directly access specific/well-isolate registers, like the -LATEST_FLUSH register used to implement cache-flush reduction. - -This uAPI intentionally keeps usermode queues out of the scope, which -explains why doorbell registers and command stream ring-buffers are not -directly exposed to userspace. - -v6: -- Add Maxime's and Heiko's acks - -v5: -- Fix typo -- Add Liviu's R-b - -v4: -- Add a VM_GET_STATE ioctl -- Fix doc -- Expose the CORE_FEATURES register so we can deal with variants in the - UMD -- Add Steve's R-b - -v3: -- Add the concept of sync-only VM operation -- Fix support for 32-bit userspace -- Rework drm_panthor_vm_create to pass the user VA size instead of - the kernel VA size (suggested by Robin Murphy) -- Typo fixes -- Explicitly cast enums with top bit set to avoid compiler warnings in - -pedantic mode. -- Drop property core_group_count as it can be easily calculated by the - number of bits set in l2_present. - -Co-developed-by: Steven Price -Signed-off-by: Steven Price -Signed-off-by: Boris Brezillon -Reviewed-by: Steven Price -Reviewed-by: Liviu Dudau -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - Documentation/gpu/driver-uapi.rst | 5 + - include/uapi/drm/panthor_drm.h | 945 ++++++++++ - 2 files changed, 950 insertions(+) - -diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst -index e5070a0e95ab..971cdb4816fc 100644 ---- a/Documentation/gpu/driver-uapi.rst -+++ b/Documentation/gpu/driver-uapi.rst -@@ -18,6 +18,11 @@ VM_BIND / EXEC uAPI - - .. kernel-doc:: include/uapi/drm/nouveau_drm.h - -+drm/panthor uAPI -+================ -+ -+.. kernel-doc:: include/uapi/drm/panthor_drm.h -+ - drm/xe uAPI - =========== - -diff --git a/include/uapi/drm/panthor_drm.h b/include/uapi/drm/panthor_drm.h -new file mode 100644 -index 000000000000..373df80f41ed ---- /dev/null -+++ b/include/uapi/drm/panthor_drm.h -@@ -0,0 +1,945 @@ -+/* SPDX-License-Identifier: MIT */ -+/* Copyright (C) 2023 Collabora ltd. */ -+#ifndef _PANTHOR_DRM_H_ -+#define _PANTHOR_DRM_H_ -+ -+#include "drm.h" -+ -+#if defined(__cplusplus) -+extern "C" { -+#endif -+ -+/** -+ * DOC: Introduction -+ * -+ * This documentation describes the Panthor IOCTLs. -+ * -+ * Just a few generic rules about the data passed to the Panthor IOCTLs: -+ * -+ * - Structures must be aligned on 64-bit/8-byte. If the object is not -+ * naturally aligned, a padding field must be added. -+ * - Fields must be explicitly aligned to their natural type alignment with -+ * pad[0..N] fields. -+ * - All padding fields will be checked by the driver to make sure they are -+ * zeroed. -+ * - Flags can be added, but not removed/replaced. -+ * - New fields can be added to the main structures (the structures -+ * directly passed to the ioctl). Those fields can be added at the end of -+ * the structure, or replace existing padding fields. Any new field being -+ * added must preserve the behavior that existed before those fields were -+ * added when a value of zero is passed. -+ * - New fields can be added to indirect objects (objects pointed by the -+ * main structure), iff those objects are passed a size to reflect the -+ * size known by the userspace driver (see drm_panthor_obj_array::stride -+ * or drm_panthor_dev_query::size). -+ * - If the kernel driver is too old to know some fields, those will be -+ * ignored if zero, and otherwise rejected (and so will be zero on output). -+ * - If userspace is too old to know some fields, those will be zeroed -+ * (input) before the structure is parsed by the kernel driver. -+ * - Each new flag/field addition must come with a driver version update so -+ * the userspace driver doesn't have to trial and error to know which -+ * flags are supported. -+ * - Structures should not contain unions, as this would defeat the -+ * extensibility of such structures. -+ * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed -+ * at the end of the drm_panthor_ioctl_id enum. -+ */ -+ -+/** -+ * DOC: MMIO regions exposed to userspace. -+ * -+ * .. c:macro:: DRM_PANTHOR_USER_MMIO_OFFSET -+ * -+ * File offset for all MMIO regions being exposed to userspace. Don't use -+ * this value directly, use DRM_PANTHOR_USER__OFFSET values instead. -+ * pgoffset passed to mmap2() is an unsigned long, which forces us to use a -+ * different offset on 32-bit and 64-bit systems. -+ * -+ * .. c:macro:: DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET -+ * -+ * File offset for the LATEST_FLUSH_ID register. The Userspace driver controls -+ * GPU cache flushing through CS instructions, but the flush reduction -+ * mechanism requires a flush_id. This flush_id could be queried with an -+ * ioctl, but Arm provides a well-isolated register page containing only this -+ * read-only register, so let's expose this page through a static mmap offset -+ * and allow direct mapping of this MMIO region so we can avoid the -+ * user <-> kernel round-trip. -+ */ -+#define DRM_PANTHOR_USER_MMIO_OFFSET_32BIT (1ull << 43) -+#define DRM_PANTHOR_USER_MMIO_OFFSET_64BIT (1ull << 56) -+#define DRM_PANTHOR_USER_MMIO_OFFSET (sizeof(unsigned long) < 8 ? \ -+ DRM_PANTHOR_USER_MMIO_OFFSET_32BIT : \ -+ DRM_PANTHOR_USER_MMIO_OFFSET_64BIT) -+#define DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET (DRM_PANTHOR_USER_MMIO_OFFSET | 0) -+ -+/** -+ * DOC: IOCTL IDs -+ * -+ * enum drm_panthor_ioctl_id - IOCTL IDs -+ * -+ * Place new ioctls at the end, don't re-order, don't replace or remove entries. -+ * -+ * These IDs are not meant to be used directly. Use the DRM_IOCTL_PANTHOR_xxx -+ * definitions instead. -+ */ -+enum drm_panthor_ioctl_id { -+ /** @DRM_PANTHOR_DEV_QUERY: Query device information. */ -+ DRM_PANTHOR_DEV_QUERY = 0, -+ -+ /** @DRM_PANTHOR_VM_CREATE: Create a VM. */ -+ DRM_PANTHOR_VM_CREATE, -+ -+ /** @DRM_PANTHOR_VM_DESTROY: Destroy a VM. */ -+ DRM_PANTHOR_VM_DESTROY, -+ -+ /** @DRM_PANTHOR_VM_BIND: Bind/unbind memory to a VM. */ -+ DRM_PANTHOR_VM_BIND, -+ -+ /** @DRM_PANTHOR_VM_GET_STATE: Get VM state. */ -+ DRM_PANTHOR_VM_GET_STATE, -+ -+ /** @DRM_PANTHOR_BO_CREATE: Create a buffer object. */ -+ DRM_PANTHOR_BO_CREATE, -+ -+ /** -+ * @DRM_PANTHOR_BO_MMAP_OFFSET: Get the file offset to pass to -+ * mmap to map a GEM object. -+ */ -+ DRM_PANTHOR_BO_MMAP_OFFSET, -+ -+ /** @DRM_PANTHOR_GROUP_CREATE: Create a scheduling group. */ -+ DRM_PANTHOR_GROUP_CREATE, -+ -+ /** @DRM_PANTHOR_GROUP_DESTROY: Destroy a scheduling group. */ -+ DRM_PANTHOR_GROUP_DESTROY, -+ -+ /** -+ * @DRM_PANTHOR_GROUP_SUBMIT: Submit jobs to queues belonging -+ * to a specific scheduling group. -+ */ -+ DRM_PANTHOR_GROUP_SUBMIT, -+ -+ /** @DRM_PANTHOR_GROUP_GET_STATE: Get the state of a scheduling group. */ -+ DRM_PANTHOR_GROUP_GET_STATE, -+ -+ /** @DRM_PANTHOR_TILER_HEAP_CREATE: Create a tiler heap. */ -+ DRM_PANTHOR_TILER_HEAP_CREATE, -+ -+ /** @DRM_PANTHOR_TILER_HEAP_DESTROY: Destroy a tiler heap. */ -+ DRM_PANTHOR_TILER_HEAP_DESTROY, -+}; -+ -+/** -+ * DRM_IOCTL_PANTHOR() - Build a Panthor IOCTL number -+ * @__access: Access type. Must be R, W or RW. -+ * @__id: One of the DRM_PANTHOR_xxx id. -+ * @__type: Suffix of the type being passed to the IOCTL. -+ * -+ * Don't use this macro directly, use the DRM_IOCTL_PANTHOR_xxx -+ * values instead. -+ * -+ * Return: An IOCTL number to be passed to ioctl() from userspace. -+ */ -+#define DRM_IOCTL_PANTHOR(__access, __id, __type) \ -+ DRM_IO ## __access(DRM_COMMAND_BASE + DRM_PANTHOR_ ## __id, \ -+ struct drm_panthor_ ## __type) -+ -+#define DRM_IOCTL_PANTHOR_DEV_QUERY \ -+ DRM_IOCTL_PANTHOR(WR, DEV_QUERY, dev_query) -+#define DRM_IOCTL_PANTHOR_VM_CREATE \ -+ DRM_IOCTL_PANTHOR(WR, VM_CREATE, vm_create) -+#define DRM_IOCTL_PANTHOR_VM_DESTROY \ -+ DRM_IOCTL_PANTHOR(WR, VM_DESTROY, vm_destroy) -+#define DRM_IOCTL_PANTHOR_VM_BIND \ -+ DRM_IOCTL_PANTHOR(WR, VM_BIND, vm_bind) -+#define DRM_IOCTL_PANTHOR_VM_GET_STATE \ -+ DRM_IOCTL_PANTHOR(WR, VM_GET_STATE, vm_get_state) -+#define DRM_IOCTL_PANTHOR_BO_CREATE \ -+ DRM_IOCTL_PANTHOR(WR, BO_CREATE, bo_create) -+#define DRM_IOCTL_PANTHOR_BO_MMAP_OFFSET \ -+ DRM_IOCTL_PANTHOR(WR, BO_MMAP_OFFSET, bo_mmap_offset) -+#define DRM_IOCTL_PANTHOR_GROUP_CREATE \ -+ DRM_IOCTL_PANTHOR(WR, GROUP_CREATE, group_create) -+#define DRM_IOCTL_PANTHOR_GROUP_DESTROY \ -+ DRM_IOCTL_PANTHOR(WR, GROUP_DESTROY, group_destroy) -+#define DRM_IOCTL_PANTHOR_GROUP_SUBMIT \ -+ DRM_IOCTL_PANTHOR(WR, GROUP_SUBMIT, group_submit) -+#define DRM_IOCTL_PANTHOR_GROUP_GET_STATE \ -+ DRM_IOCTL_PANTHOR(WR, GROUP_GET_STATE, group_get_state) -+#define DRM_IOCTL_PANTHOR_TILER_HEAP_CREATE \ -+ DRM_IOCTL_PANTHOR(WR, TILER_HEAP_CREATE, tiler_heap_create) -+#define DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY \ -+ DRM_IOCTL_PANTHOR(WR, TILER_HEAP_DESTROY, tiler_heap_destroy) -+ -+/** -+ * DOC: IOCTL arguments -+ */ -+ -+/** -+ * struct drm_panthor_obj_array - Object array. -+ * -+ * This object is used to pass an array of objects whose size is subject to changes in -+ * future versions of the driver. In order to support this mutability, we pass a stride -+ * describing the size of the object as known by userspace. -+ * -+ * You shouldn't fill drm_panthor_obj_array fields directly. You should instead use -+ * the DRM_PANTHOR_OBJ_ARRAY() macro that takes care of initializing the stride to -+ * the object size. -+ */ -+struct drm_panthor_obj_array { -+ /** @stride: Stride of object struct. Used for versioning. */ -+ __u32 stride; -+ -+ /** @count: Number of objects in the array. */ -+ __u32 count; -+ -+ /** @array: User pointer to an array of objects. */ -+ __u64 array; -+}; -+ -+/** -+ * DRM_PANTHOR_OBJ_ARRAY() - Initialize a drm_panthor_obj_array field. -+ * @cnt: Number of elements in the array. -+ * @ptr: Pointer to the array to pass to the kernel. -+ * -+ * Macro initializing a drm_panthor_obj_array based on the object size as known -+ * by userspace. -+ */ -+#define DRM_PANTHOR_OBJ_ARRAY(cnt, ptr) \ -+ { .stride = sizeof((ptr)[0]), .count = (cnt), .array = (__u64)(uintptr_t)(ptr) } -+ -+/** -+ * enum drm_panthor_sync_op_flags - Synchronization operation flags. -+ */ -+enum drm_panthor_sync_op_flags { -+ /** @DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK: Synchronization handle type mask. */ -+ DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK = 0xff, -+ -+ /** @DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ: Synchronization object type. */ -+ DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ = 0, -+ -+ /** -+ * @DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ: Timeline synchronization -+ * object type. -+ */ -+ DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ = 1, -+ -+ /** @DRM_PANTHOR_SYNC_OP_WAIT: Wait operation. */ -+ DRM_PANTHOR_SYNC_OP_WAIT = 0 << 31, -+ -+ /** @DRM_PANTHOR_SYNC_OP_SIGNAL: Signal operation. */ -+ DRM_PANTHOR_SYNC_OP_SIGNAL = (int)(1u << 31), -+}; -+ -+/** -+ * struct drm_panthor_sync_op - Synchronization operation. -+ */ -+struct drm_panthor_sync_op { -+ /** @flags: Synchronization operation flags. Combination of DRM_PANTHOR_SYNC_OP values. */ -+ __u32 flags; -+ -+ /** @handle: Sync handle. */ -+ __u32 handle; -+ -+ /** -+ * @timeline_value: MBZ if -+ * (flags & DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK) != -+ * DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ. -+ */ -+ __u64 timeline_value; -+}; -+ -+/** -+ * enum drm_panthor_dev_query_type - Query type -+ * -+ * Place new types at the end, don't re-order, don't remove or replace. -+ */ -+enum drm_panthor_dev_query_type { -+ /** @DRM_PANTHOR_DEV_QUERY_GPU_INFO: Query GPU information. */ -+ DRM_PANTHOR_DEV_QUERY_GPU_INFO = 0, -+ -+ /** @DRM_PANTHOR_DEV_QUERY_CSIF_INFO: Query command-stream interface information. */ -+ DRM_PANTHOR_DEV_QUERY_CSIF_INFO, -+}; -+ -+/** -+ * struct drm_panthor_gpu_info - GPU information -+ * -+ * Structure grouping all queryable information relating to the GPU. -+ */ -+struct drm_panthor_gpu_info { -+ /** @gpu_id : GPU ID. */ -+ __u32 gpu_id; -+#define DRM_PANTHOR_ARCH_MAJOR(x) ((x) >> 28) -+#define DRM_PANTHOR_ARCH_MINOR(x) (((x) >> 24) & 0xf) -+#define DRM_PANTHOR_ARCH_REV(x) (((x) >> 20) & 0xf) -+#define DRM_PANTHOR_PRODUCT_MAJOR(x) (((x) >> 16) & 0xf) -+#define DRM_PANTHOR_VERSION_MAJOR(x) (((x) >> 12) & 0xf) -+#define DRM_PANTHOR_VERSION_MINOR(x) (((x) >> 4) & 0xff) -+#define DRM_PANTHOR_VERSION_STATUS(x) ((x) & 0xf) -+ -+ /** @gpu_rev: GPU revision. */ -+ __u32 gpu_rev; -+ -+ /** @csf_id: Command stream frontend ID. */ -+ __u32 csf_id; -+#define DRM_PANTHOR_CSHW_MAJOR(x) (((x) >> 26) & 0x3f) -+#define DRM_PANTHOR_CSHW_MINOR(x) (((x) >> 20) & 0x3f) -+#define DRM_PANTHOR_CSHW_REV(x) (((x) >> 16) & 0xf) -+#define DRM_PANTHOR_MCU_MAJOR(x) (((x) >> 10) & 0x3f) -+#define DRM_PANTHOR_MCU_MINOR(x) (((x) >> 4) & 0x3f) -+#define DRM_PANTHOR_MCU_REV(x) ((x) & 0xf) -+ -+ /** @l2_features: L2-cache features. */ -+ __u32 l2_features; -+ -+ /** @tiler_features: Tiler features. */ -+ __u32 tiler_features; -+ -+ /** @mem_features: Memory features. */ -+ __u32 mem_features; -+ -+ /** @mmu_features: MMU features. */ -+ __u32 mmu_features; -+#define DRM_PANTHOR_MMU_VA_BITS(x) ((x) & 0xff) -+ -+ /** @thread_features: Thread features. */ -+ __u32 thread_features; -+ -+ /** @max_threads: Maximum number of threads. */ -+ __u32 max_threads; -+ -+ /** @thread_max_workgroup_size: Maximum workgroup size. */ -+ __u32 thread_max_workgroup_size; -+ -+ /** -+ * @thread_max_barrier_size: Maximum number of threads that can wait -+ * simultaneously on a barrier. -+ */ -+ __u32 thread_max_barrier_size; -+ -+ /** @coherency_features: Coherency features. */ -+ __u32 coherency_features; -+ -+ /** @texture_features: Texture features. */ -+ __u32 texture_features[4]; -+ -+ /** @as_present: Bitmask encoding the number of address-space exposed by the MMU. */ -+ __u32 as_present; -+ -+ /** @shader_present: Bitmask encoding the shader cores exposed by the GPU. */ -+ __u64 shader_present; -+ -+ /** @l2_present: Bitmask encoding the L2 caches exposed by the GPU. */ -+ __u64 l2_present; -+ -+ /** @tiler_present: Bitmask encoding the tiler units exposed by the GPU. */ -+ __u64 tiler_present; -+ -+ /* @core_features: Used to discriminate core variants when they exist. */ -+ __u32 core_features; -+ -+ /* @pad: MBZ. */ -+ __u32 pad; -+}; -+ -+/** -+ * struct drm_panthor_csif_info - Command stream interface information -+ * -+ * Structure grouping all queryable information relating to the command stream interface. -+ */ -+struct drm_panthor_csif_info { -+ /** @csg_slot_count: Number of command stream group slots exposed by the firmware. */ -+ __u32 csg_slot_count; -+ -+ /** @cs_slot_count: Number of command stream slots per group. */ -+ __u32 cs_slot_count; -+ -+ /** @cs_reg_count: Number of command stream registers. */ -+ __u32 cs_reg_count; -+ -+ /** @scoreboard_slot_count: Number of scoreboard slots. */ -+ __u32 scoreboard_slot_count; -+ -+ /** -+ * @unpreserved_cs_reg_count: Number of command stream registers reserved by -+ * the kernel driver to call a userspace command stream. -+ * -+ * All registers can be used by a userspace command stream, but the -+ * [cs_slot_count - unpreserved_cs_reg_count .. cs_slot_count] registers are -+ * used by the kernel when DRM_PANTHOR_IOCTL_GROUP_SUBMIT is called. -+ */ -+ __u32 unpreserved_cs_reg_count; -+ -+ /** -+ * @pad: Padding field, set to zero. -+ */ -+ __u32 pad; -+}; -+ -+/** -+ * struct drm_panthor_dev_query - Arguments passed to DRM_PANTHOR_IOCTL_DEV_QUERY -+ */ -+struct drm_panthor_dev_query { -+ /** @type: the query type (see drm_panthor_dev_query_type). */ -+ __u32 type; -+ -+ /** -+ * @size: size of the type being queried. -+ * -+ * If pointer is NULL, size is updated by the driver to provide the -+ * output structure size. If pointer is not NULL, the driver will -+ * only copy min(size, actual_structure_size) bytes to the pointer, -+ * and update the size accordingly. This allows us to extend query -+ * types without breaking userspace. -+ */ -+ __u32 size; -+ -+ /** -+ * @pointer: user pointer to a query type struct. -+ * -+ * Pointer can be NULL, in which case, nothing is copied, but the -+ * actual structure size is returned. If not NULL, it must point to -+ * a location that's large enough to hold size bytes. -+ */ -+ __u64 pointer; -+}; -+ -+/** -+ * struct drm_panthor_vm_create - Arguments passed to DRM_PANTHOR_IOCTL_VM_CREATE -+ */ -+struct drm_panthor_vm_create { -+ /** @flags: VM flags, MBZ. */ -+ __u32 flags; -+ -+ /** @id: Returned VM ID. */ -+ __u32 id; -+ -+ /** -+ * @user_va_range: Size of the VA space reserved for user objects. -+ * -+ * The kernel will pick the remaining space to map kernel-only objects to the -+ * VM (heap chunks, heap context, ring buffers, kernel synchronization objects, -+ * ...). If the space left for kernel objects is too small, kernel object -+ * allocation will fail further down the road. One can use -+ * drm_panthor_gpu_info::mmu_features to extract the total virtual address -+ * range, and chose a user_va_range that leaves some space to the kernel. -+ * -+ * If user_va_range is zero, the kernel will pick a sensible value based on -+ * TASK_SIZE and the virtual range supported by the GPU MMU (the kernel/user -+ * split should leave enough VA space for userspace processes to support SVM, -+ * while still allowing the kernel to map some amount of kernel objects in -+ * the kernel VA range). The value chosen by the driver will be returned in -+ * @user_va_range. -+ * -+ * User VA space always starts at 0x0, kernel VA space is always placed after -+ * the user VA range. -+ */ -+ __u64 user_va_range; -+}; -+ -+/** -+ * struct drm_panthor_vm_destroy - Arguments passed to DRM_PANTHOR_IOCTL_VM_DESTROY -+ */ -+struct drm_panthor_vm_destroy { -+ /** @id: ID of the VM to destroy. */ -+ __u32 id; -+ -+ /** @pad: MBZ. */ -+ __u32 pad; -+}; -+ -+/** -+ * enum drm_panthor_vm_bind_op_flags - VM bind operation flags -+ */ -+enum drm_panthor_vm_bind_op_flags { -+ /** -+ * @DRM_PANTHOR_VM_BIND_OP_MAP_READONLY: Map the memory read-only. -+ * -+ * Only valid with DRM_PANTHOR_VM_BIND_OP_TYPE_MAP. -+ */ -+ DRM_PANTHOR_VM_BIND_OP_MAP_READONLY = 1 << 0, -+ -+ /** -+ * @DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC: Map the memory not-executable. -+ * -+ * Only valid with DRM_PANTHOR_VM_BIND_OP_TYPE_MAP. -+ */ -+ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC = 1 << 1, -+ -+ /** -+ * @DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED: Map the memory uncached. -+ * -+ * Only valid with DRM_PANTHOR_VM_BIND_OP_TYPE_MAP. -+ */ -+ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED = 1 << 2, -+ -+ /** -+ * @DRM_PANTHOR_VM_BIND_OP_TYPE_MASK: Mask used to determine the type of operation. -+ */ -+ DRM_PANTHOR_VM_BIND_OP_TYPE_MASK = (int)(0xfu << 28), -+ -+ /** @DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: Map operation. */ -+ DRM_PANTHOR_VM_BIND_OP_TYPE_MAP = 0 << 28, -+ -+ /** @DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP: Unmap operation. */ -+ DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP = 1 << 28, -+ -+ /** -+ * @DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY: No VM operation. -+ * -+ * Just serves as a synchronization point on a VM queue. -+ * -+ * Only valid if %DRM_PANTHOR_VM_BIND_ASYNC is set in drm_panthor_vm_bind::flags, -+ * and drm_panthor_vm_bind_op::syncs contains at least one element. -+ */ -+ DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY = 2 << 28, -+}; -+ -+/** -+ * struct drm_panthor_vm_bind_op - VM bind operation -+ */ -+struct drm_panthor_vm_bind_op { -+ /** @flags: Combination of drm_panthor_vm_bind_op_flags flags. */ -+ __u32 flags; -+ -+ /** -+ * @bo_handle: Handle of the buffer object to map. -+ * MBZ for unmap or sync-only operations. -+ */ -+ __u32 bo_handle; -+ -+ /** -+ * @bo_offset: Buffer object offset. -+ * MBZ for unmap or sync-only operations. -+ */ -+ __u64 bo_offset; -+ -+ /** -+ * @va: Virtual address to map/unmap. -+ * MBZ for sync-only operations. -+ */ -+ __u64 va; -+ -+ /** -+ * @size: Size to map/unmap. -+ * MBZ for sync-only operations. -+ */ -+ __u64 size; -+ -+ /** -+ * @syncs: Array of struct drm_panthor_sync_op synchronization -+ * operations. -+ * -+ * This array must be empty if %DRM_PANTHOR_VM_BIND_ASYNC is not set on -+ * the drm_panthor_vm_bind object containing this VM bind operation. -+ * -+ * This array shall not be empty for sync-only operations. -+ */ -+ struct drm_panthor_obj_array syncs; -+ -+}; -+ -+/** -+ * enum drm_panthor_vm_bind_flags - VM bind flags -+ */ -+enum drm_panthor_vm_bind_flags { -+ /** -+ * @DRM_PANTHOR_VM_BIND_ASYNC: VM bind operations are queued to the VM -+ * queue instead of being executed synchronously. -+ */ -+ DRM_PANTHOR_VM_BIND_ASYNC = 1 << 0, -+}; -+ -+/** -+ * struct drm_panthor_vm_bind - Arguments passed to DRM_IOCTL_PANTHOR_VM_BIND -+ */ -+struct drm_panthor_vm_bind { -+ /** @vm_id: VM targeted by the bind request. */ -+ __u32 vm_id; -+ -+ /** @flags: Combination of drm_panthor_vm_bind_flags flags. */ -+ __u32 flags; -+ -+ /** @ops: Array of struct drm_panthor_vm_bind_op bind operations. */ -+ struct drm_panthor_obj_array ops; -+}; -+ -+/** -+ * enum drm_panthor_vm_state - VM states. -+ */ -+enum drm_panthor_vm_state { -+ /** -+ * @DRM_PANTHOR_VM_STATE_USABLE: VM is usable. -+ * -+ * New VM operations will be accepted on this VM. -+ */ -+ DRM_PANTHOR_VM_STATE_USABLE, -+ -+ /** -+ * @DRM_PANTHOR_VM_STATE_UNUSABLE: VM is unusable. -+ * -+ * Something put the VM in an unusable state (like an asynchronous -+ * VM_BIND request failing for any reason). -+ * -+ * Once the VM is in this state, all new MAP operations will be -+ * rejected, and any GPU job targeting this VM will fail. -+ * UNMAP operations are still accepted. -+ * -+ * The only way to recover from an unusable VM is to create a new -+ * VM, and destroy the old one. -+ */ -+ DRM_PANTHOR_VM_STATE_UNUSABLE, -+}; -+ -+/** -+ * struct drm_panthor_vm_get_state - Get VM state. -+ */ -+struct drm_panthor_vm_get_state { -+ /** @vm_id: VM targeted by the get_state request. */ -+ __u32 vm_id; -+ -+ /** -+ * @state: state returned by the driver. -+ * -+ * Must be one of the enum drm_panthor_vm_state values. -+ */ -+ __u32 state; -+}; -+ -+/** -+ * enum drm_panthor_bo_flags - Buffer object flags, passed at creation time. -+ */ -+enum drm_panthor_bo_flags { -+ /** @DRM_PANTHOR_BO_NO_MMAP: The buffer object will never be CPU-mapped in userspace. */ -+ DRM_PANTHOR_BO_NO_MMAP = (1 << 0), -+}; -+ -+/** -+ * struct drm_panthor_bo_create - Arguments passed to DRM_IOCTL_PANTHOR_BO_CREATE. -+ */ -+struct drm_panthor_bo_create { -+ /** -+ * @size: Requested size for the object -+ * -+ * The (page-aligned) allocated size for the object will be returned. -+ */ -+ __u64 size; -+ -+ /** -+ * @flags: Flags. Must be a combination of drm_panthor_bo_flags flags. -+ */ -+ __u32 flags; -+ -+ /** -+ * @exclusive_vm_id: Exclusive VM this buffer object will be mapped to. -+ * -+ * If not zero, the field must refer to a valid VM ID, and implies that: -+ * - the buffer object will only ever be bound to that VM -+ * - cannot be exported as a PRIME fd -+ */ -+ __u32 exclusive_vm_id; -+ -+ /** -+ * @handle: Returned handle for the object. -+ * -+ * Object handles are nonzero. -+ */ -+ __u32 handle; -+ -+ /** @pad: MBZ. */ -+ __u32 pad; -+}; -+ -+/** -+ * struct drm_panthor_bo_mmap_offset - Arguments passed to DRM_IOCTL_PANTHOR_BO_MMAP_OFFSET. -+ */ -+struct drm_panthor_bo_mmap_offset { -+ /** @handle: Handle of the object we want an mmap offset for. */ -+ __u32 handle; -+ -+ /** @pad: MBZ. */ -+ __u32 pad; -+ -+ /** @offset: The fake offset to use for subsequent mmap calls. */ -+ __u64 offset; -+}; -+ -+/** -+ * struct drm_panthor_queue_create - Queue creation arguments. -+ */ -+struct drm_panthor_queue_create { -+ /** -+ * @priority: Defines the priority of queues inside a group. Goes from 0 to 15, -+ * 15 being the highest priority. -+ */ -+ __u8 priority; -+ -+ /** @pad: Padding fields, MBZ. */ -+ __u8 pad[3]; -+ -+ /** @ringbuf_size: Size of the ring buffer to allocate to this queue. */ -+ __u32 ringbuf_size; -+}; -+ -+/** -+ * enum drm_panthor_group_priority - Scheduling group priority -+ */ -+enum drm_panthor_group_priority { -+ /** @PANTHOR_GROUP_PRIORITY_LOW: Low priority group. */ -+ PANTHOR_GROUP_PRIORITY_LOW = 0, -+ -+ /** @PANTHOR_GROUP_PRIORITY_MEDIUM: Medium priority group. */ -+ PANTHOR_GROUP_PRIORITY_MEDIUM, -+ -+ /** @PANTHOR_GROUP_PRIORITY_HIGH: High priority group. */ -+ PANTHOR_GROUP_PRIORITY_HIGH, -+}; -+ -+/** -+ * struct drm_panthor_group_create - Arguments passed to DRM_IOCTL_PANTHOR_GROUP_CREATE -+ */ -+struct drm_panthor_group_create { -+ /** @queues: Array of drm_panthor_queue_create elements. */ -+ struct drm_panthor_obj_array queues; -+ -+ /** -+ * @max_compute_cores: Maximum number of cores that can be used by compute -+ * jobs across CS queues bound to this group. -+ * -+ * Must be less or equal to the number of bits set in @compute_core_mask. -+ */ -+ __u8 max_compute_cores; -+ -+ /** -+ * @max_fragment_cores: Maximum number of cores that can be used by fragment -+ * jobs across CS queues bound to this group. -+ * -+ * Must be less or equal to the number of bits set in @fragment_core_mask. -+ */ -+ __u8 max_fragment_cores; -+ -+ /** -+ * @max_tiler_cores: Maximum number of tilers that can be used by tiler jobs -+ * across CS queues bound to this group. -+ * -+ * Must be less or equal to the number of bits set in @tiler_core_mask. -+ */ -+ __u8 max_tiler_cores; -+ -+ /** @priority: Group priority (see enum drm_panthor_group_priority). */ -+ __u8 priority; -+ -+ /** @pad: Padding field, MBZ. */ -+ __u32 pad; -+ -+ /** -+ * @compute_core_mask: Mask encoding cores that can be used for compute jobs. -+ * -+ * This field must have at least @max_compute_cores bits set. -+ * -+ * The bits set here should also be set in drm_panthor_gpu_info::shader_present. -+ */ -+ __u64 compute_core_mask; -+ -+ /** -+ * @fragment_core_mask: Mask encoding cores that can be used for fragment jobs. -+ * -+ * This field must have at least @max_fragment_cores bits set. -+ * -+ * The bits set here should also be set in drm_panthor_gpu_info::shader_present. -+ */ -+ __u64 fragment_core_mask; -+ -+ /** -+ * @tiler_core_mask: Mask encoding cores that can be used for tiler jobs. -+ * -+ * This field must have at least @max_tiler_cores bits set. -+ * -+ * The bits set here should also be set in drm_panthor_gpu_info::tiler_present. -+ */ -+ __u64 tiler_core_mask; -+ -+ /** -+ * @vm_id: VM ID to bind this group to. -+ * -+ * All submission to queues bound to this group will use this VM. -+ */ -+ __u32 vm_id; -+ -+ /** -+ * @group_handle: Returned group handle. Passed back when submitting jobs or -+ * destroying a group. -+ */ -+ __u32 group_handle; -+}; -+ -+/** -+ * struct drm_panthor_group_destroy - Arguments passed to DRM_IOCTL_PANTHOR_GROUP_DESTROY -+ */ -+struct drm_panthor_group_destroy { -+ /** @group_handle: Group to destroy */ -+ __u32 group_handle; -+ -+ /** @pad: Padding field, MBZ. */ -+ __u32 pad; -+}; -+ -+/** -+ * struct drm_panthor_queue_submit - Job submission arguments. -+ * -+ * This is describing the userspace command stream to call from the kernel -+ * command stream ring-buffer. Queue submission is always part of a group -+ * submission, taking one or more jobs to submit to the underlying queues. -+ */ -+struct drm_panthor_queue_submit { -+ /** @queue_index: Index of the queue inside a group. */ -+ __u32 queue_index; -+ -+ /** -+ * @stream_size: Size of the command stream to execute. -+ * -+ * Must be 64-bit/8-byte aligned (the size of a CS instruction) -+ * -+ * Can be zero if stream_addr is zero too. -+ */ -+ __u32 stream_size; -+ -+ /** -+ * @stream_addr: GPU address of the command stream to execute. -+ * -+ * Must be aligned on 64-byte. -+ * -+ * Can be zero is stream_size is zero too. -+ */ -+ __u64 stream_addr; -+ -+ /** -+ * @latest_flush: FLUSH_ID read at the time the stream was built. -+ * -+ * This allows cache flush elimination for the automatic -+ * flush+invalidate(all) done at submission time, which is needed to -+ * ensure the GPU doesn't get garbage when reading the indirect command -+ * stream buffers. If you want the cache flush to happen -+ * unconditionally, pass a zero here. -+ */ -+ __u32 latest_flush; -+ -+ /** @pad: MBZ. */ -+ __u32 pad; -+ -+ /** @syncs: Array of struct drm_panthor_sync_op sync operations. */ -+ struct drm_panthor_obj_array syncs; -+}; -+ -+/** -+ * struct drm_panthor_group_submit - Arguments passed to DRM_IOCTL_PANTHOR_GROUP_SUBMIT -+ */ -+struct drm_panthor_group_submit { -+ /** @group_handle: Handle of the group to queue jobs to. */ -+ __u32 group_handle; -+ -+ /** @pad: MBZ. */ -+ __u32 pad; -+ -+ /** @queue_submits: Array of drm_panthor_queue_submit objects. */ -+ struct drm_panthor_obj_array queue_submits; -+}; -+ -+/** -+ * enum drm_panthor_group_state_flags - Group state flags -+ */ -+enum drm_panthor_group_state_flags { -+ /** -+ * @DRM_PANTHOR_GROUP_STATE_TIMEDOUT: Group had unfinished jobs. -+ * -+ * When a group ends up with this flag set, no jobs can be submitted to its queues. -+ */ -+ DRM_PANTHOR_GROUP_STATE_TIMEDOUT = 1 << 0, -+ -+ /** -+ * @DRM_PANTHOR_GROUP_STATE_FATAL_FAULT: Group had fatal faults. -+ * -+ * When a group ends up with this flag set, no jobs can be submitted to its queues. -+ */ -+ DRM_PANTHOR_GROUP_STATE_FATAL_FAULT = 1 << 1, -+}; -+ -+/** -+ * struct drm_panthor_group_get_state - Arguments passed to DRM_IOCTL_PANTHOR_GROUP_GET_STATE -+ * -+ * Used to query the state of a group and decide whether a new group should be created to -+ * replace it. -+ */ -+struct drm_panthor_group_get_state { -+ /** @group_handle: Handle of the group to query state on */ -+ __u32 group_handle; -+ -+ /** -+ * @state: Combination of DRM_PANTHOR_GROUP_STATE_* flags encoding the -+ * group state. -+ */ -+ __u32 state; -+ -+ /** @fatal_queues: Bitmask of queues that faced fatal faults. */ -+ __u32 fatal_queues; -+ -+ /** @pad: MBZ */ -+ __u32 pad; -+}; -+ -+/** -+ * struct drm_panthor_tiler_heap_create - Arguments passed to DRM_IOCTL_PANTHOR_TILER_HEAP_CREATE -+ */ -+struct drm_panthor_tiler_heap_create { -+ /** @vm_id: VM ID the tiler heap should be mapped to */ -+ __u32 vm_id; -+ -+ /** @initial_chunk_count: Initial number of chunks to allocate. */ -+ __u32 initial_chunk_count; -+ -+ /** @chunk_size: Chunk size. Must be a power of two at least 256KB large. */ -+ __u32 chunk_size; -+ -+ /** @max_chunks: Maximum number of chunks that can be allocated. */ -+ __u32 max_chunks; -+ -+ /** -+ * @target_in_flight: Maximum number of in-flight render passes. -+ * -+ * If the heap has more than tiler jobs in-flight, the FW will wait for render -+ * passes to finish before queuing new tiler jobs. -+ */ -+ __u32 target_in_flight; -+ -+ /** @handle: Returned heap handle. Passed back to DESTROY_TILER_HEAP. */ -+ __u32 handle; -+ -+ /** @tiler_heap_ctx_gpu_va: Returned heap GPU virtual address returned */ -+ __u64 tiler_heap_ctx_gpu_va; -+ -+ /** -+ * @first_heap_chunk_gpu_va: First heap chunk. -+ * -+ * The tiler heap is formed of heap chunks forming a single-link list. This -+ * is the first element in the list. -+ */ -+ __u64 first_heap_chunk_gpu_va; -+}; -+ -+/** -+ * struct drm_panthor_tiler_heap_destroy - Arguments passed to DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY -+ */ -+struct drm_panthor_tiler_heap_destroy { -+ /** @handle: Handle of the tiler heap to destroy */ -+ __u32 handle; -+ -+ /** @pad: Padding field, MBZ. */ -+ __u32 pad; -+}; -+ -+#if defined(__cplusplus) -+} -+#endif -+ -+#endif /* _PANTHOR_DRM_H_ */ --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:16 +0100 -Subject: drm/panthor: Add GPU register definitions - -Those are the registers directly accessible through the MMIO range. - -FW registers are exposed in panthor_fw.h. - -v6: -- Add Maxime's and Heiko's acks - -v4: -- Add the CORE_FEATURES register (needed for GPU variants) -- Add Steve's R-b - -v3: -- Add macros to extract GPU ID info -- Formatting changes -- Remove AS_TRANSCFG_ADRMODE_LEGACY - it doesn't exist post-CSF -- Remove CSF_GPU_LATEST_FLUSH_ID_DEFAULT -- Add GPU_L2_FEATURES_LINE_SIZE for extracting the GPU cache line size - -Co-developed-by: Steven Price -Signed-off-by: Steven Price -Signed-off-by: Boris Brezillon -Acked-by: Steven Price # MIT+GPL2 relicensing,Arm -Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro -Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora -Reviewed-by: Steven Price -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - drivers/gpu/drm/panthor/panthor_regs.h | 239 ++++++++++ - 1 file changed, 239 insertions(+) - -diff --git a/drivers/gpu/drm/panthor/panthor_regs.h b/drivers/gpu/drm/panthor/panthor_regs.h -new file mode 100644 -index 000000000000..b7b3b3add166 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_regs.h -@@ -0,0 +1,239 @@ -+/* SPDX-License-Identifier: GPL-2.0 or MIT */ -+/* Copyright 2018 Marty E. Plummer */ -+/* Copyright 2019 Linaro, Ltd, Rob Herring */ -+/* Copyright 2023 Collabora ltd. */ -+/* -+ * Register definitions based on mali_kbase_gpu_regmap.h and -+ * mali_kbase_gpu_regmap_csf.h -+ * (C) COPYRIGHT 2010-2022 ARM Limited. All rights reserved. -+ */ -+#ifndef __PANTHOR_REGS_H__ -+#define __PANTHOR_REGS_H__ -+ -+#define GPU_ID 0x0 -+#define GPU_ARCH_MAJOR(x) ((x) >> 28) -+#define GPU_ARCH_MINOR(x) (((x) & GENMASK(27, 24)) >> 24) -+#define GPU_ARCH_REV(x) (((x) & GENMASK(23, 20)) >> 20) -+#define GPU_PROD_MAJOR(x) (((x) & GENMASK(19, 16)) >> 16) -+#define GPU_VER_MAJOR(x) (((x) & GENMASK(15, 12)) >> 12) -+#define GPU_VER_MINOR(x) (((x) & GENMASK(11, 4)) >> 4) -+#define GPU_VER_STATUS(x) ((x) & GENMASK(3, 0)) -+ -+#define GPU_L2_FEATURES 0x4 -+#define GPU_L2_FEATURES_LINE_SIZE(x) (1 << ((x) & GENMASK(7, 0))) -+ -+#define GPU_CORE_FEATURES 0x8 -+ -+#define GPU_TILER_FEATURES 0xC -+#define GPU_MEM_FEATURES 0x10 -+#define GROUPS_L2_COHERENT BIT(0) -+ -+#define GPU_MMU_FEATURES 0x14 -+#define GPU_MMU_FEATURES_VA_BITS(x) ((x) & GENMASK(7, 0)) -+#define GPU_MMU_FEATURES_PA_BITS(x) (((x) >> 8) & GENMASK(7, 0)) -+#define GPU_AS_PRESENT 0x18 -+#define GPU_CSF_ID 0x1C -+ -+#define GPU_INT_RAWSTAT 0x20 -+#define GPU_INT_CLEAR 0x24 -+#define GPU_INT_MASK 0x28 -+#define GPU_INT_STAT 0x2c -+#define GPU_IRQ_FAULT BIT(0) -+#define GPU_IRQ_PROTM_FAULT BIT(1) -+#define GPU_IRQ_RESET_COMPLETED BIT(8) -+#define GPU_IRQ_POWER_CHANGED BIT(9) -+#define GPU_IRQ_POWER_CHANGED_ALL BIT(10) -+#define GPU_IRQ_CLEAN_CACHES_COMPLETED BIT(17) -+#define GPU_IRQ_DOORBELL_MIRROR BIT(18) -+#define GPU_IRQ_MCU_STATUS_CHANGED BIT(19) -+#define GPU_CMD 0x30 -+#define GPU_CMD_DEF(type, payload) ((type) | ((payload) << 8)) -+#define GPU_SOFT_RESET GPU_CMD_DEF(1, 1) -+#define GPU_HARD_RESET GPU_CMD_DEF(1, 2) -+#define CACHE_CLEAN BIT(0) -+#define CACHE_INV BIT(1) -+#define GPU_FLUSH_CACHES(l2, lsc, oth) \ -+ GPU_CMD_DEF(4, ((l2) << 0) | ((lsc) << 4) | ((oth) << 8)) -+ -+#define GPU_STATUS 0x34 -+#define GPU_STATUS_ACTIVE BIT(0) -+#define GPU_STATUS_PWR_ACTIVE BIT(1) -+#define GPU_STATUS_PAGE_FAULT BIT(4) -+#define GPU_STATUS_PROTM_ACTIVE BIT(7) -+#define GPU_STATUS_DBG_ENABLED BIT(8) -+ -+#define GPU_FAULT_STATUS 0x3C -+#define GPU_FAULT_ADDR_LO 0x40 -+#define GPU_FAULT_ADDR_HI 0x44 -+ -+#define GPU_PWR_KEY 0x50 -+#define GPU_PWR_KEY_UNLOCK 0x2968A819 -+#define GPU_PWR_OVERRIDE0 0x54 -+#define GPU_PWR_OVERRIDE1 0x58 -+ -+#define GPU_TIMESTAMP_OFFSET_LO 0x88 -+#define GPU_TIMESTAMP_OFFSET_HI 0x8C -+#define GPU_CYCLE_COUNT_LO 0x90 -+#define GPU_CYCLE_COUNT_HI 0x94 -+#define GPU_TIMESTAMP_LO 0x98 -+#define GPU_TIMESTAMP_HI 0x9C -+ -+#define GPU_THREAD_MAX_THREADS 0xA0 -+#define GPU_THREAD_MAX_WORKGROUP_SIZE 0xA4 -+#define GPU_THREAD_MAX_BARRIER_SIZE 0xA8 -+#define GPU_THREAD_FEATURES 0xAC -+ -+#define GPU_TEXTURE_FEATURES(n) (0xB0 + ((n) * 4)) -+ -+#define GPU_SHADER_PRESENT_LO 0x100 -+#define GPU_SHADER_PRESENT_HI 0x104 -+#define GPU_TILER_PRESENT_LO 0x110 -+#define GPU_TILER_PRESENT_HI 0x114 -+#define GPU_L2_PRESENT_LO 0x120 -+#define GPU_L2_PRESENT_HI 0x124 -+ -+#define SHADER_READY_LO 0x140 -+#define SHADER_READY_HI 0x144 -+#define TILER_READY_LO 0x150 -+#define TILER_READY_HI 0x154 -+#define L2_READY_LO 0x160 -+#define L2_READY_HI 0x164 -+ -+#define SHADER_PWRON_LO 0x180 -+#define SHADER_PWRON_HI 0x184 -+#define TILER_PWRON_LO 0x190 -+#define TILER_PWRON_HI 0x194 -+#define L2_PWRON_LO 0x1A0 -+#define L2_PWRON_HI 0x1A4 -+ -+#define SHADER_PWROFF_LO 0x1C0 -+#define SHADER_PWROFF_HI 0x1C4 -+#define TILER_PWROFF_LO 0x1D0 -+#define TILER_PWROFF_HI 0x1D4 -+#define L2_PWROFF_LO 0x1E0 -+#define L2_PWROFF_HI 0x1E4 -+ -+#define SHADER_PWRTRANS_LO 0x200 -+#define SHADER_PWRTRANS_HI 0x204 -+#define TILER_PWRTRANS_LO 0x210 -+#define TILER_PWRTRANS_HI 0x214 -+#define L2_PWRTRANS_LO 0x220 -+#define L2_PWRTRANS_HI 0x224 -+ -+#define SHADER_PWRACTIVE_LO 0x240 -+#define SHADER_PWRACTIVE_HI 0x244 -+#define TILER_PWRACTIVE_LO 0x250 -+#define TILER_PWRACTIVE_HI 0x254 -+#define L2_PWRACTIVE_LO 0x260 -+#define L2_PWRACTIVE_HI 0x264 -+ -+#define GPU_REVID 0x280 -+ -+#define GPU_COHERENCY_FEATURES 0x300 -+#define GPU_COHERENCY_PROT_BIT(name) BIT(GPU_COHERENCY_ ## name) -+ -+#define GPU_COHERENCY_PROTOCOL 0x304 -+#define GPU_COHERENCY_ACE 0 -+#define GPU_COHERENCY_ACE_LITE 1 -+#define GPU_COHERENCY_NONE 31 -+ -+#define MCU_CONTROL 0x700 -+#define MCU_CONTROL_ENABLE 1 -+#define MCU_CONTROL_AUTO 2 -+#define MCU_CONTROL_DISABLE 0 -+ -+#define MCU_STATUS 0x704 -+#define MCU_STATUS_DISABLED 0 -+#define MCU_STATUS_ENABLED 1 -+#define MCU_STATUS_HALT 2 -+#define MCU_STATUS_FATAL 3 -+ -+/* Job Control regs */ -+#define JOB_INT_RAWSTAT 0x1000 -+#define JOB_INT_CLEAR 0x1004 -+#define JOB_INT_MASK 0x1008 -+#define JOB_INT_STAT 0x100c -+#define JOB_INT_GLOBAL_IF BIT(31) -+#define JOB_INT_CSG_IF(x) BIT(x) -+ -+/* MMU regs */ -+#define MMU_INT_RAWSTAT 0x2000 -+#define MMU_INT_CLEAR 0x2004 -+#define MMU_INT_MASK 0x2008 -+#define MMU_INT_STAT 0x200c -+ -+/* AS_COMMAND register commands */ -+ -+#define MMU_BASE 0x2400 -+#define MMU_AS_SHIFT 6 -+#define MMU_AS(as) (MMU_BASE + ((as) << MMU_AS_SHIFT)) -+ -+#define AS_TRANSTAB_LO(as) (MMU_AS(as) + 0x0) -+#define AS_TRANSTAB_HI(as) (MMU_AS(as) + 0x4) -+#define AS_MEMATTR_LO(as) (MMU_AS(as) + 0x8) -+#define AS_MEMATTR_HI(as) (MMU_AS(as) + 0xC) -+#define AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL (2 << 2) -+#define AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r) ((3 << 2) | \ -+ ((w) ? BIT(0) : 0) | \ -+ ((r) ? BIT(1) : 0)) -+#define AS_MEMATTR_AARCH64_SH_MIDGARD_INNER (0 << 4) -+#define AS_MEMATTR_AARCH64_SH_CPU_INNER (1 << 4) -+#define AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH (2 << 4) -+#define AS_MEMATTR_AARCH64_SHARED (0 << 6) -+#define AS_MEMATTR_AARCH64_INNER_OUTER_NC (1 << 6) -+#define AS_MEMATTR_AARCH64_INNER_OUTER_WB (2 << 6) -+#define AS_MEMATTR_AARCH64_FAULT (3 << 6) -+#define AS_LOCKADDR_LO(as) (MMU_AS(as) + 0x10) -+#define AS_LOCKADDR_HI(as) (MMU_AS(as) + 0x14) -+#define AS_COMMAND(as) (MMU_AS(as) + 0x18) -+#define AS_COMMAND_NOP 0 -+#define AS_COMMAND_UPDATE 1 -+#define AS_COMMAND_LOCK 2 -+#define AS_COMMAND_UNLOCK 3 -+#define AS_COMMAND_FLUSH_PT 4 -+#define AS_COMMAND_FLUSH_MEM 5 -+#define AS_LOCK_REGION_MIN_SIZE (1ULL << 15) -+#define AS_FAULTSTATUS(as) (MMU_AS(as) + 0x1C) -+#define AS_FAULTSTATUS_ACCESS_TYPE_MASK (0x3 << 8) -+#define AS_FAULTSTATUS_ACCESS_TYPE_ATOMIC (0x0 << 8) -+#define AS_FAULTSTATUS_ACCESS_TYPE_EX (0x1 << 8) -+#define AS_FAULTSTATUS_ACCESS_TYPE_READ (0x2 << 8) -+#define AS_FAULTSTATUS_ACCESS_TYPE_WRITE (0x3 << 8) -+#define AS_FAULTADDRESS_LO(as) (MMU_AS(as) + 0x20) -+#define AS_FAULTADDRESS_HI(as) (MMU_AS(as) + 0x24) -+#define AS_STATUS(as) (MMU_AS(as) + 0x28) -+#define AS_STATUS_AS_ACTIVE BIT(0) -+#define AS_TRANSCFG_LO(as) (MMU_AS(as) + 0x30) -+#define AS_TRANSCFG_HI(as) (MMU_AS(as) + 0x34) -+#define AS_TRANSCFG_ADRMODE_UNMAPPED (1 << 0) -+#define AS_TRANSCFG_ADRMODE_IDENTITY (2 << 0) -+#define AS_TRANSCFG_ADRMODE_AARCH64_4K (6 << 0) -+#define AS_TRANSCFG_ADRMODE_AARCH64_64K (8 << 0) -+#define AS_TRANSCFG_INA_BITS(x) ((x) << 6) -+#define AS_TRANSCFG_OUTA_BITS(x) ((x) << 14) -+#define AS_TRANSCFG_SL_CONCAT BIT(22) -+#define AS_TRANSCFG_PTW_MEMATTR_NC (1 << 24) -+#define AS_TRANSCFG_PTW_MEMATTR_WB (2 << 24) -+#define AS_TRANSCFG_PTW_SH_NS (0 << 28) -+#define AS_TRANSCFG_PTW_SH_OS (2 << 28) -+#define AS_TRANSCFG_PTW_SH_IS (3 << 28) -+#define AS_TRANSCFG_PTW_RA BIT(30) -+#define AS_TRANSCFG_DISABLE_HIER_AP BIT(33) -+#define AS_TRANSCFG_DISABLE_AF_FAULT BIT(34) -+#define AS_TRANSCFG_WXN BIT(35) -+#define AS_TRANSCFG_XREADABLE BIT(36) -+#define AS_FAULTEXTRA_LO(as) (MMU_AS(as) + 0x38) -+#define AS_FAULTEXTRA_HI(as) (MMU_AS(as) + 0x3C) -+ -+#define CSF_GPU_LATEST_FLUSH_ID 0x10000 -+ -+#define CSF_DOORBELL(i) (0x80000 + ((i) * 0x10000)) -+#define CSF_GLB_DOORBELL_ID 0 -+ -+#define gpu_write(dev, reg, data) \ -+ writel(data, (dev)->iomem + (reg)) -+ -+#define gpu_read(dev, reg) \ -+ readl((dev)->iomem + (reg)) -+ -+#endif --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:17 +0100 -Subject: drm/panthor: Add the device logical block - -The panthor driver is designed in a modular way, where each logical -block is dealing with a specific HW-block or software feature. In order -for those blocks to communicate with each other, we need a central -panthor_device collecting all the blocks, and exposing some common -features, like interrupt handling, power management, reset, ... - -This what this panthor_device logical block is about. - -v6: -- Add Maxime's and Heiko's acks -- Keep header inclusion alphabetically ordered - -v5: -- Suspend the MMU/GPU blocks if panthor_fw_resume() fails in - panthor_device_resume() -- Move the pm_runtime_use_autosuspend() call before drm_dev_register() -- Add Liviu's R-b - -v4: -- Check drmm_mutex_init() return code -- Fix panthor_device_reset_work() out path -- Fix the race in the unplug logic -- Fix typos -- Unplug blocks when something fails in panthor_device_init() -- Add Steve's R-b - -v3: -- Add acks for the MIT+GPL2 relicensing -- Fix 32-bit support -- Shorten the sections protected by panthor_device::pm::mmio_lock to fix - lock ordering issues. -- Rename panthor_device::pm::lock into panthor_device::pm::mmio_lock to - better reflect what this lock is protecting -- Use dev_err_probe() -- Make sure we call drm_dev_exit() when something fails half-way in - panthor_device_reset_work() -- Replace CSF_GPU_LATEST_FLUSH_ID_DEFAULT with a constant '1' and a - comment to explain. Also remove setting the dummy flush ID on suspend. -- Remove drm_WARN_ON() in panthor_exception_name() -- Check pirq->suspended in panthor_xxx_irq_raw_handler() - -Co-developed-by: Steven Price -Signed-off-by: Steven Price -Signed-off-by: Boris Brezillon -Acked-by: Steven Price # MIT+GPL2 relicensing,Arm -Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro -Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora -Reviewed-by: Steven Price -Reviewed-by: Liviu Dudau -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - drivers/gpu/drm/panthor/panthor_device.c | 549 ++++++++++ - drivers/gpu/drm/panthor/panthor_device.h | 394 +++++++ - 2 files changed, 943 insertions(+) - -diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c -new file mode 100644 -index 000000000000..bfe8da4a6e4c ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_device.c -@@ -0,0 +1,549 @@ -+// SPDX-License-Identifier: GPL-2.0 or MIT -+/* Copyright 2018 Marty E. Plummer */ -+/* Copyright 2019 Linaro, Ltd, Rob Herring */ -+/* Copyright 2023 Collabora ltd. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "panthor_devfreq.h" -+#include "panthor_device.h" -+#include "panthor_fw.h" -+#include "panthor_gpu.h" -+#include "panthor_mmu.h" -+#include "panthor_regs.h" -+#include "panthor_sched.h" -+ -+static int panthor_clk_init(struct panthor_device *ptdev) -+{ -+ ptdev->clks.core = devm_clk_get(ptdev->base.dev, NULL); -+ if (IS_ERR(ptdev->clks.core)) -+ return dev_err_probe(ptdev->base.dev, -+ PTR_ERR(ptdev->clks.core), -+ "get 'core' clock failed"); -+ -+ ptdev->clks.stacks = devm_clk_get_optional(ptdev->base.dev, "stacks"); -+ if (IS_ERR(ptdev->clks.stacks)) -+ return dev_err_probe(ptdev->base.dev, -+ PTR_ERR(ptdev->clks.stacks), -+ "get 'stacks' clock failed"); -+ -+ ptdev->clks.coregroup = devm_clk_get_optional(ptdev->base.dev, "coregroup"); -+ if (IS_ERR(ptdev->clks.coregroup)) -+ return dev_err_probe(ptdev->base.dev, -+ PTR_ERR(ptdev->clks.coregroup), -+ "get 'coregroup' clock failed"); -+ -+ drm_info(&ptdev->base, "clock rate = %lu\n", clk_get_rate(ptdev->clks.core)); -+ return 0; -+} -+ -+void panthor_device_unplug(struct panthor_device *ptdev) -+{ -+ /* This function can be called from two different path: the reset work -+ * and the platform device remove callback. drm_dev_unplug() doesn't -+ * deal with concurrent callers, so we have to protect drm_dev_unplug() -+ * calls with our own lock, and bail out if the device is already -+ * unplugged. -+ */ -+ mutex_lock(&ptdev->unplug.lock); -+ if (drm_dev_is_unplugged(&ptdev->base)) { -+ /* Someone beat us, release the lock and wait for the unplug -+ * operation to be reported as done. -+ **/ -+ mutex_unlock(&ptdev->unplug.lock); -+ wait_for_completion(&ptdev->unplug.done); -+ return; -+ } -+ -+ /* Call drm_dev_unplug() so any access to HW blocks happening after -+ * that point get rejected. -+ */ -+ drm_dev_unplug(&ptdev->base); -+ -+ /* We do the rest of the unplug with the unplug lock released, -+ * future callers will wait on ptdev->unplug.done anyway. -+ */ -+ mutex_unlock(&ptdev->unplug.lock); -+ -+ drm_WARN_ON(&ptdev->base, pm_runtime_get_sync(ptdev->base.dev) < 0); -+ -+ /* Now, try to cleanly shutdown the GPU before the device resources -+ * get reclaimed. -+ */ -+ panthor_sched_unplug(ptdev); -+ panthor_fw_unplug(ptdev); -+ panthor_mmu_unplug(ptdev); -+ panthor_gpu_unplug(ptdev); -+ -+ pm_runtime_dont_use_autosuspend(ptdev->base.dev); -+ pm_runtime_put_sync_suspend(ptdev->base.dev); -+ -+ /* Report the unplug operation as done to unblock concurrent -+ * panthor_device_unplug() callers. -+ */ -+ complete_all(&ptdev->unplug.done); -+} -+ -+static void panthor_device_reset_cleanup(struct drm_device *ddev, void *data) -+{ -+ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); -+ -+ cancel_work_sync(&ptdev->reset.work); -+ destroy_workqueue(ptdev->reset.wq); -+} -+ -+static void panthor_device_reset_work(struct work_struct *work) -+{ -+ struct panthor_device *ptdev = container_of(work, struct panthor_device, reset.work); -+ int ret = 0, cookie; -+ -+ if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_ACTIVE) { -+ /* -+ * No need for a reset as the device has been (or will be) -+ * powered down -+ */ -+ atomic_set(&ptdev->reset.pending, 0); -+ return; -+ } -+ -+ if (!drm_dev_enter(&ptdev->base, &cookie)) -+ return; -+ -+ panthor_sched_pre_reset(ptdev); -+ panthor_fw_pre_reset(ptdev, true); -+ panthor_mmu_pre_reset(ptdev); -+ panthor_gpu_soft_reset(ptdev); -+ panthor_gpu_l2_power_on(ptdev); -+ panthor_mmu_post_reset(ptdev); -+ ret = panthor_fw_post_reset(ptdev); -+ if (ret) -+ goto out_dev_exit; -+ -+ atomic_set(&ptdev->reset.pending, 0); -+ panthor_sched_post_reset(ptdev); -+ -+out_dev_exit: -+ drm_dev_exit(cookie); -+ -+ if (ret) { -+ panthor_device_unplug(ptdev); -+ drm_err(&ptdev->base, "Failed to boot MCU after reset, making device unusable."); -+ } -+} -+ -+static bool panthor_device_is_initialized(struct panthor_device *ptdev) -+{ -+ return !!ptdev->scheduler; -+} -+ -+static void panthor_device_free_page(struct drm_device *ddev, void *data) -+{ -+ free_page((unsigned long)data); -+} -+ -+int panthor_device_init(struct panthor_device *ptdev) -+{ -+ struct resource *res; -+ struct page *p; -+ int ret; -+ -+ ptdev->coherent = device_get_dma_attr(ptdev->base.dev) == DEV_DMA_COHERENT; -+ -+ init_completion(&ptdev->unplug.done); -+ ret = drmm_mutex_init(&ptdev->base, &ptdev->unplug.lock); -+ if (ret) -+ return ret; -+ -+ ret = drmm_mutex_init(&ptdev->base, &ptdev->pm.mmio_lock); -+ if (ret) -+ return ret; -+ -+ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDED); -+ p = alloc_page(GFP_KERNEL | __GFP_ZERO); -+ if (!p) -+ return -ENOMEM; -+ -+ ptdev->pm.dummy_latest_flush = page_address(p); -+ ret = drmm_add_action_or_reset(&ptdev->base, panthor_device_free_page, -+ ptdev->pm.dummy_latest_flush); -+ if (ret) -+ return ret; -+ -+ /* -+ * Set the dummy page holding the latest flush to 1. This will cause the -+ * flush to avoided as we know it isn't necessary if the submission -+ * happens while the dummy page is mapped. Zero cannot be used because -+ * that means 'always flush'. -+ */ -+ *ptdev->pm.dummy_latest_flush = 1; -+ -+ INIT_WORK(&ptdev->reset.work, panthor_device_reset_work); -+ ptdev->reset.wq = alloc_ordered_workqueue("panthor-reset-wq", 0); -+ if (!ptdev->reset.wq) -+ return -ENOMEM; -+ -+ ret = drmm_add_action_or_reset(&ptdev->base, panthor_device_reset_cleanup, NULL); -+ if (ret) -+ return ret; -+ -+ ret = panthor_clk_init(ptdev); -+ if (ret) -+ return ret; -+ -+ ret = panthor_devfreq_init(ptdev); -+ if (ret) -+ return ret; -+ -+ ptdev->iomem = devm_platform_get_and_ioremap_resource(to_platform_device(ptdev->base.dev), -+ 0, &res); -+ if (IS_ERR(ptdev->iomem)) -+ return PTR_ERR(ptdev->iomem); -+ -+ ptdev->phys_addr = res->start; -+ -+ ret = devm_pm_runtime_enable(ptdev->base.dev); -+ if (ret) -+ return ret; -+ -+ ret = pm_runtime_resume_and_get(ptdev->base.dev); -+ if (ret) -+ return ret; -+ -+ ret = panthor_gpu_init(ptdev); -+ if (ret) -+ goto err_rpm_put; -+ -+ ret = panthor_mmu_init(ptdev); -+ if (ret) -+ goto err_unplug_gpu; -+ -+ ret = panthor_fw_init(ptdev); -+ if (ret) -+ goto err_unplug_mmu; -+ -+ ret = panthor_sched_init(ptdev); -+ if (ret) -+ goto err_unplug_fw; -+ -+ /* ~3 frames */ -+ pm_runtime_set_autosuspend_delay(ptdev->base.dev, 50); -+ pm_runtime_use_autosuspend(ptdev->base.dev); -+ -+ ret = drm_dev_register(&ptdev->base, 0); -+ if (ret) -+ goto err_disable_autosuspend; -+ -+ pm_runtime_put_autosuspend(ptdev->base.dev); -+ return 0; -+ -+err_disable_autosuspend: -+ pm_runtime_dont_use_autosuspend(ptdev->base.dev); -+ panthor_sched_unplug(ptdev); -+ -+err_unplug_fw: -+ panthor_fw_unplug(ptdev); -+ -+err_unplug_mmu: -+ panthor_mmu_unplug(ptdev); -+ -+err_unplug_gpu: -+ panthor_gpu_unplug(ptdev); -+ -+err_rpm_put: -+ pm_runtime_put_sync_suspend(ptdev->base.dev); -+ return ret; -+} -+ -+#define PANTHOR_EXCEPTION(id) \ -+ [DRM_PANTHOR_EXCEPTION_ ## id] = { \ -+ .name = #id, \ -+ } -+ -+struct panthor_exception_info { -+ const char *name; -+}; -+ -+static const struct panthor_exception_info panthor_exception_infos[] = { -+ PANTHOR_EXCEPTION(OK), -+ PANTHOR_EXCEPTION(TERMINATED), -+ PANTHOR_EXCEPTION(KABOOM), -+ PANTHOR_EXCEPTION(EUREKA), -+ PANTHOR_EXCEPTION(ACTIVE), -+ PANTHOR_EXCEPTION(CS_RES_TERM), -+ PANTHOR_EXCEPTION(CS_CONFIG_FAULT), -+ PANTHOR_EXCEPTION(CS_ENDPOINT_FAULT), -+ PANTHOR_EXCEPTION(CS_BUS_FAULT), -+ PANTHOR_EXCEPTION(CS_INSTR_INVALID), -+ PANTHOR_EXCEPTION(CS_CALL_STACK_OVERFLOW), -+ PANTHOR_EXCEPTION(CS_INHERIT_FAULT), -+ PANTHOR_EXCEPTION(INSTR_INVALID_PC), -+ PANTHOR_EXCEPTION(INSTR_INVALID_ENC), -+ PANTHOR_EXCEPTION(INSTR_BARRIER_FAULT), -+ PANTHOR_EXCEPTION(DATA_INVALID_FAULT), -+ PANTHOR_EXCEPTION(TILE_RANGE_FAULT), -+ PANTHOR_EXCEPTION(ADDR_RANGE_FAULT), -+ PANTHOR_EXCEPTION(IMPRECISE_FAULT), -+ PANTHOR_EXCEPTION(OOM), -+ PANTHOR_EXCEPTION(CSF_FW_INTERNAL_ERROR), -+ PANTHOR_EXCEPTION(CSF_RES_EVICTION_TIMEOUT), -+ PANTHOR_EXCEPTION(GPU_BUS_FAULT), -+ PANTHOR_EXCEPTION(GPU_SHAREABILITY_FAULT), -+ PANTHOR_EXCEPTION(SYS_SHAREABILITY_FAULT), -+ PANTHOR_EXCEPTION(GPU_CACHEABILITY_FAULT), -+ PANTHOR_EXCEPTION(TRANSLATION_FAULT_0), -+ PANTHOR_EXCEPTION(TRANSLATION_FAULT_1), -+ PANTHOR_EXCEPTION(TRANSLATION_FAULT_2), -+ PANTHOR_EXCEPTION(TRANSLATION_FAULT_3), -+ PANTHOR_EXCEPTION(TRANSLATION_FAULT_4), -+ PANTHOR_EXCEPTION(PERM_FAULT_0), -+ PANTHOR_EXCEPTION(PERM_FAULT_1), -+ PANTHOR_EXCEPTION(PERM_FAULT_2), -+ PANTHOR_EXCEPTION(PERM_FAULT_3), -+ PANTHOR_EXCEPTION(ACCESS_FLAG_1), -+ PANTHOR_EXCEPTION(ACCESS_FLAG_2), -+ PANTHOR_EXCEPTION(ACCESS_FLAG_3), -+ PANTHOR_EXCEPTION(ADDR_SIZE_FAULT_IN), -+ PANTHOR_EXCEPTION(ADDR_SIZE_FAULT_OUT0), -+ PANTHOR_EXCEPTION(ADDR_SIZE_FAULT_OUT1), -+ PANTHOR_EXCEPTION(ADDR_SIZE_FAULT_OUT2), -+ PANTHOR_EXCEPTION(ADDR_SIZE_FAULT_OUT3), -+ PANTHOR_EXCEPTION(MEM_ATTR_FAULT_0), -+ PANTHOR_EXCEPTION(MEM_ATTR_FAULT_1), -+ PANTHOR_EXCEPTION(MEM_ATTR_FAULT_2), -+ PANTHOR_EXCEPTION(MEM_ATTR_FAULT_3), -+}; -+ -+const char *panthor_exception_name(struct panthor_device *ptdev, u32 exception_code) -+{ -+ if (exception_code >= ARRAY_SIZE(panthor_exception_infos) || -+ !panthor_exception_infos[exception_code].name) -+ return "Unknown exception type"; -+ -+ return panthor_exception_infos[exception_code].name; -+} -+ -+static vm_fault_t panthor_mmio_vm_fault(struct vm_fault *vmf) -+{ -+ struct vm_area_struct *vma = vmf->vma; -+ struct panthor_device *ptdev = vma->vm_private_data; -+ u64 id = (u64)vma->vm_pgoff << PAGE_SHIFT; -+ unsigned long pfn; -+ pgprot_t pgprot; -+ vm_fault_t ret; -+ bool active; -+ int cookie; -+ -+ if (!drm_dev_enter(&ptdev->base, &cookie)) -+ return VM_FAULT_SIGBUS; -+ -+ mutex_lock(&ptdev->pm.mmio_lock); -+ active = atomic_read(&ptdev->pm.state) == PANTHOR_DEVICE_PM_STATE_ACTIVE; -+ -+ switch (panthor_device_mmio_offset(id)) { -+ case DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET: -+ if (active) -+ pfn = __phys_to_pfn(ptdev->phys_addr + CSF_GPU_LATEST_FLUSH_ID); -+ else -+ pfn = virt_to_pfn(ptdev->pm.dummy_latest_flush); -+ break; -+ -+ default: -+ ret = VM_FAULT_SIGBUS; -+ goto out_unlock; -+ } -+ -+ pgprot = vma->vm_page_prot; -+ if (active) -+ pgprot = pgprot_noncached(pgprot); -+ -+ ret = vmf_insert_pfn_prot(vma, vmf->address, pfn, pgprot); -+ -+out_unlock: -+ mutex_unlock(&ptdev->pm.mmio_lock); -+ drm_dev_exit(cookie); -+ return ret; -+} -+ -+static const struct vm_operations_struct panthor_mmio_vm_ops = { -+ .fault = panthor_mmio_vm_fault, -+}; -+ -+int panthor_device_mmap_io(struct panthor_device *ptdev, struct vm_area_struct *vma) -+{ -+ u64 id = (u64)vma->vm_pgoff << PAGE_SHIFT; -+ -+ switch (panthor_device_mmio_offset(id)) { -+ case DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET: -+ if (vma->vm_end - vma->vm_start != PAGE_SIZE || -+ (vma->vm_flags & (VM_WRITE | VM_EXEC))) -+ return -EINVAL; -+ -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ -+ /* Defer actual mapping to the fault handler. */ -+ vma->vm_private_data = ptdev; -+ vma->vm_ops = &panthor_mmio_vm_ops; -+ vm_flags_set(vma, -+ VM_IO | VM_DONTCOPY | VM_DONTEXPAND | -+ VM_NORESERVE | VM_DONTDUMP | VM_PFNMAP); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+int panthor_device_resume(struct device *dev) -+{ -+ struct panthor_device *ptdev = dev_get_drvdata(dev); -+ int ret, cookie; -+ -+ if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_SUSPENDED) -+ return -EINVAL; -+ -+ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_RESUMING); -+ -+ ret = clk_prepare_enable(ptdev->clks.core); -+ if (ret) -+ goto err_set_suspended; -+ -+ ret = clk_prepare_enable(ptdev->clks.stacks); -+ if (ret) -+ goto err_disable_core_clk; -+ -+ ret = clk_prepare_enable(ptdev->clks.coregroup); -+ if (ret) -+ goto err_disable_stacks_clk; -+ -+ ret = panthor_devfreq_resume(ptdev); -+ if (ret) -+ goto err_disable_coregroup_clk; -+ -+ if (panthor_device_is_initialized(ptdev) && -+ drm_dev_enter(&ptdev->base, &cookie)) { -+ panthor_gpu_resume(ptdev); -+ panthor_mmu_resume(ptdev); -+ ret = drm_WARN_ON(&ptdev->base, panthor_fw_resume(ptdev)); -+ if (!ret) { -+ panthor_sched_resume(ptdev); -+ } else { -+ panthor_mmu_suspend(ptdev); -+ panthor_gpu_suspend(ptdev); -+ } -+ -+ drm_dev_exit(cookie); -+ -+ if (ret) -+ goto err_suspend_devfreq; -+ } -+ -+ if (atomic_read(&ptdev->reset.pending)) -+ queue_work(ptdev->reset.wq, &ptdev->reset.work); -+ -+ /* Clear all IOMEM mappings pointing to this device after we've -+ * resumed. This way the fake mappings pointing to the dummy pages -+ * are removed and the real iomem mapping will be restored on next -+ * access. -+ */ -+ mutex_lock(&ptdev->pm.mmio_lock); -+ unmap_mapping_range(ptdev->base.anon_inode->i_mapping, -+ DRM_PANTHOR_USER_MMIO_OFFSET, 0, 1); -+ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_ACTIVE); -+ mutex_unlock(&ptdev->pm.mmio_lock); -+ return 0; -+ -+err_suspend_devfreq: -+ panthor_devfreq_suspend(ptdev); -+ -+err_disable_coregroup_clk: -+ clk_disable_unprepare(ptdev->clks.coregroup); -+ -+err_disable_stacks_clk: -+ clk_disable_unprepare(ptdev->clks.stacks); -+ -+err_disable_core_clk: -+ clk_disable_unprepare(ptdev->clks.core); -+ -+err_set_suspended: -+ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDED); -+ return ret; -+} -+ -+int panthor_device_suspend(struct device *dev) -+{ -+ struct panthor_device *ptdev = dev_get_drvdata(dev); -+ int ret, cookie; -+ -+ if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_ACTIVE) -+ return -EINVAL; -+ -+ /* Clear all IOMEM mappings pointing to this device before we -+ * shutdown the power-domain and clocks. Failing to do that results -+ * in external aborts when the process accesses the iomem region. -+ * We change the state and call unmap_mapping_range() with the -+ * mmio_lock held to make sure the vm_fault handler won't set up -+ * invalid mappings. -+ */ -+ mutex_lock(&ptdev->pm.mmio_lock); -+ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDING); -+ unmap_mapping_range(ptdev->base.anon_inode->i_mapping, -+ DRM_PANTHOR_USER_MMIO_OFFSET, 0, 1); -+ mutex_unlock(&ptdev->pm.mmio_lock); -+ -+ if (panthor_device_is_initialized(ptdev) && -+ drm_dev_enter(&ptdev->base, &cookie)) { -+ cancel_work_sync(&ptdev->reset.work); -+ -+ /* We prepare everything as if we were resetting the GPU. -+ * The end of the reset will happen in the resume path though. -+ */ -+ panthor_sched_suspend(ptdev); -+ panthor_fw_suspend(ptdev); -+ panthor_mmu_suspend(ptdev); -+ panthor_gpu_suspend(ptdev); -+ drm_dev_exit(cookie); -+ } -+ -+ ret = panthor_devfreq_suspend(ptdev); -+ if (ret) { -+ if (panthor_device_is_initialized(ptdev) && -+ drm_dev_enter(&ptdev->base, &cookie)) { -+ panthor_gpu_resume(ptdev); -+ panthor_mmu_resume(ptdev); -+ drm_WARN_ON(&ptdev->base, panthor_fw_resume(ptdev)); -+ panthor_sched_resume(ptdev); -+ drm_dev_exit(cookie); -+ } -+ -+ goto err_set_active; -+ } -+ -+ clk_disable_unprepare(ptdev->clks.coregroup); -+ clk_disable_unprepare(ptdev->clks.stacks); -+ clk_disable_unprepare(ptdev->clks.core); -+ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDED); -+ return 0; -+ -+err_set_active: -+ /* If something failed and we have to revert back to an -+ * active state, we also need to clear the MMIO userspace -+ * mappings, so any dumb pages that were mapped while we -+ * were trying to suspend gets invalidated. -+ */ -+ mutex_lock(&ptdev->pm.mmio_lock); -+ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_ACTIVE); -+ unmap_mapping_range(ptdev->base.anon_inode->i_mapping, -+ DRM_PANTHOR_USER_MMIO_OFFSET, 0, 1); -+ mutex_unlock(&ptdev->pm.mmio_lock); -+ return ret; -+} -+#endif -diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h -new file mode 100644 -index 000000000000..51c9d61b6796 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_device.h -@@ -0,0 +1,394 @@ -+/* SPDX-License-Identifier: GPL-2.0 or MIT */ -+/* Copyright 2018 Marty E. Plummer */ -+/* Copyright 2019 Linaro, Ltd, Rob Herring */ -+/* Copyright 2023 Collabora ltd. */ -+ -+#ifndef __PANTHOR_DEVICE_H__ -+#define __PANTHOR_DEVICE_H__ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+struct panthor_csf; -+struct panthor_csf_ctx; -+struct panthor_device; -+struct panthor_gpu; -+struct panthor_group_pool; -+struct panthor_heap_pool; -+struct panthor_job; -+struct panthor_mmu; -+struct panthor_fw; -+struct panthor_perfcnt; -+struct panthor_vm; -+struct panthor_vm_pool; -+ -+/** -+ * enum panthor_device_pm_state - PM state -+ */ -+enum panthor_device_pm_state { -+ /** @PANTHOR_DEVICE_PM_STATE_SUSPENDED: Device is suspended. */ -+ PANTHOR_DEVICE_PM_STATE_SUSPENDED = 0, -+ -+ /** @PANTHOR_DEVICE_PM_STATE_RESUMING: Device is being resumed. */ -+ PANTHOR_DEVICE_PM_STATE_RESUMING, -+ -+ /** @PANTHOR_DEVICE_PM_STATE_ACTIVE: Device is active. */ -+ PANTHOR_DEVICE_PM_STATE_ACTIVE, -+ -+ /** @PANTHOR_DEVICE_PM_STATE_SUSPENDING: Device is being suspended. */ -+ PANTHOR_DEVICE_PM_STATE_SUSPENDING, -+}; -+ -+/** -+ * struct panthor_irq - IRQ data -+ * -+ * Used to automate IRQ handling for the 3 different IRQs we have in this driver. -+ */ -+struct panthor_irq { -+ /** @ptdev: Panthor device */ -+ struct panthor_device *ptdev; -+ -+ /** @irq: IRQ number. */ -+ int irq; -+ -+ /** @mask: Current mask being applied to xxx_INT_MASK. */ -+ u32 mask; -+ -+ /** @suspended: Set to true when the IRQ is suspended. */ -+ atomic_t suspended; -+}; -+ -+/** -+ * struct panthor_device - Panthor device -+ */ -+struct panthor_device { -+ /** @base: Base drm_device. */ -+ struct drm_device base; -+ -+ /** @phys_addr: Physical address of the iomem region. */ -+ phys_addr_t phys_addr; -+ -+ /** @iomem: CPU mapping of the IOMEM region. */ -+ void __iomem *iomem; -+ -+ /** @clks: GPU clocks. */ -+ struct { -+ /** @core: Core clock. */ -+ struct clk *core; -+ -+ /** @stacks: Stacks clock. This clock is optional. */ -+ struct clk *stacks; -+ -+ /** @coregroup: Core group clock. This clock is optional. */ -+ struct clk *coregroup; -+ } clks; -+ -+ /** @coherent: True if the CPU/GPU are memory coherent. */ -+ bool coherent; -+ -+ /** @gpu_info: GPU information. */ -+ struct drm_panthor_gpu_info gpu_info; -+ -+ /** @csif_info: Command stream interface information. */ -+ struct drm_panthor_csif_info csif_info; -+ -+ /** @gpu: GPU management data. */ -+ struct panthor_gpu *gpu; -+ -+ /** @fw: FW management data. */ -+ struct panthor_fw *fw; -+ -+ /** @mmu: MMU management data. */ -+ struct panthor_mmu *mmu; -+ -+ /** @scheduler: Scheduler management data. */ -+ struct panthor_scheduler *scheduler; -+ -+ /** @devfreq: Device frequency scaling management data. */ -+ struct panthor_devfreq *devfreq; -+ -+ /** @unplug: Device unplug related fields. */ -+ struct { -+ /** @lock: Lock used to serialize unplug operations. */ -+ struct mutex lock; -+ -+ /** -+ * @done: Completion object signaled when the unplug -+ * operation is done. -+ */ -+ struct completion done; -+ } unplug; -+ -+ /** @reset: Reset related fields. */ -+ struct { -+ /** @wq: Ordered worqueud used to schedule reset operations. */ -+ struct workqueue_struct *wq; -+ -+ /** @work: Reset work. */ -+ struct work_struct work; -+ -+ /** @pending: Set to true if a reset is pending. */ -+ atomic_t pending; -+ } reset; -+ -+ /** @pm: Power management related data. */ -+ struct { -+ /** @state: Power state. */ -+ atomic_t state; -+ -+ /** -+ * @mmio_lock: Lock protecting MMIO userspace CPU mappings. -+ * -+ * This is needed to ensure we map the dummy IO pages when -+ * the device is being suspended, and the real IO pages when -+ * the device is being resumed. We can't just do with the -+ * state atomicity to deal with this race. -+ */ -+ struct mutex mmio_lock; -+ -+ /** -+ * @dummy_latest_flush: Dummy LATEST_FLUSH page. -+ * -+ * Used to replace the real LATEST_FLUSH page when the GPU -+ * is suspended. -+ */ -+ u32 *dummy_latest_flush; -+ } pm; -+}; -+ -+/** -+ * struct panthor_file - Panthor file -+ */ -+struct panthor_file { -+ /** @ptdev: Device attached to this file. */ -+ struct panthor_device *ptdev; -+ -+ /** @vms: VM pool attached to this file. */ -+ struct panthor_vm_pool *vms; -+ -+ /** @groups: Scheduling group pool attached to this file. */ -+ struct panthor_group_pool *groups; -+}; -+ -+int panthor_device_init(struct panthor_device *ptdev); -+void panthor_device_unplug(struct panthor_device *ptdev); -+ -+/** -+ * panthor_device_schedule_reset() - Schedules a reset operation -+ */ -+static inline void panthor_device_schedule_reset(struct panthor_device *ptdev) -+{ -+ if (!atomic_cmpxchg(&ptdev->reset.pending, 0, 1) && -+ atomic_read(&ptdev->pm.state) == PANTHOR_DEVICE_PM_STATE_ACTIVE) -+ queue_work(ptdev->reset.wq, &ptdev->reset.work); -+} -+ -+/** -+ * panthor_device_reset_is_pending() - Checks if a reset is pending. -+ * -+ * Return: true if a reset is pending, false otherwise. -+ */ -+static inline bool panthor_device_reset_is_pending(struct panthor_device *ptdev) -+{ -+ return atomic_read(&ptdev->reset.pending) != 0; -+} -+ -+int panthor_device_mmap_io(struct panthor_device *ptdev, -+ struct vm_area_struct *vma); -+ -+int panthor_device_resume(struct device *dev); -+int panthor_device_suspend(struct device *dev); -+ -+enum drm_panthor_exception_type { -+ DRM_PANTHOR_EXCEPTION_OK = 0x00, -+ DRM_PANTHOR_EXCEPTION_TERMINATED = 0x04, -+ DRM_PANTHOR_EXCEPTION_KABOOM = 0x05, -+ DRM_PANTHOR_EXCEPTION_EUREKA = 0x06, -+ DRM_PANTHOR_EXCEPTION_ACTIVE = 0x08, -+ DRM_PANTHOR_EXCEPTION_CS_RES_TERM = 0x0f, -+ DRM_PANTHOR_EXCEPTION_MAX_NON_FAULT = 0x3f, -+ DRM_PANTHOR_EXCEPTION_CS_CONFIG_FAULT = 0x40, -+ DRM_PANTHOR_EXCEPTION_CS_ENDPOINT_FAULT = 0x44, -+ DRM_PANTHOR_EXCEPTION_CS_BUS_FAULT = 0x48, -+ DRM_PANTHOR_EXCEPTION_CS_INSTR_INVALID = 0x49, -+ DRM_PANTHOR_EXCEPTION_CS_CALL_STACK_OVERFLOW = 0x4a, -+ DRM_PANTHOR_EXCEPTION_CS_INHERIT_FAULT = 0x4b, -+ DRM_PANTHOR_EXCEPTION_INSTR_INVALID_PC = 0x50, -+ DRM_PANTHOR_EXCEPTION_INSTR_INVALID_ENC = 0x51, -+ DRM_PANTHOR_EXCEPTION_INSTR_BARRIER_FAULT = 0x55, -+ DRM_PANTHOR_EXCEPTION_DATA_INVALID_FAULT = 0x58, -+ DRM_PANTHOR_EXCEPTION_TILE_RANGE_FAULT = 0x59, -+ DRM_PANTHOR_EXCEPTION_ADDR_RANGE_FAULT = 0x5a, -+ DRM_PANTHOR_EXCEPTION_IMPRECISE_FAULT = 0x5b, -+ DRM_PANTHOR_EXCEPTION_OOM = 0x60, -+ DRM_PANTHOR_EXCEPTION_CSF_FW_INTERNAL_ERROR = 0x68, -+ DRM_PANTHOR_EXCEPTION_CSF_RES_EVICTION_TIMEOUT = 0x69, -+ DRM_PANTHOR_EXCEPTION_GPU_BUS_FAULT = 0x80, -+ DRM_PANTHOR_EXCEPTION_GPU_SHAREABILITY_FAULT = 0x88, -+ DRM_PANTHOR_EXCEPTION_SYS_SHAREABILITY_FAULT = 0x89, -+ DRM_PANTHOR_EXCEPTION_GPU_CACHEABILITY_FAULT = 0x8a, -+ DRM_PANTHOR_EXCEPTION_TRANSLATION_FAULT_0 = 0xc0, -+ DRM_PANTHOR_EXCEPTION_TRANSLATION_FAULT_1 = 0xc1, -+ DRM_PANTHOR_EXCEPTION_TRANSLATION_FAULT_2 = 0xc2, -+ DRM_PANTHOR_EXCEPTION_TRANSLATION_FAULT_3 = 0xc3, -+ DRM_PANTHOR_EXCEPTION_TRANSLATION_FAULT_4 = 0xc4, -+ DRM_PANTHOR_EXCEPTION_PERM_FAULT_0 = 0xc8, -+ DRM_PANTHOR_EXCEPTION_PERM_FAULT_1 = 0xc9, -+ DRM_PANTHOR_EXCEPTION_PERM_FAULT_2 = 0xca, -+ DRM_PANTHOR_EXCEPTION_PERM_FAULT_3 = 0xcb, -+ DRM_PANTHOR_EXCEPTION_ACCESS_FLAG_1 = 0xd9, -+ DRM_PANTHOR_EXCEPTION_ACCESS_FLAG_2 = 0xda, -+ DRM_PANTHOR_EXCEPTION_ACCESS_FLAG_3 = 0xdb, -+ DRM_PANTHOR_EXCEPTION_ADDR_SIZE_FAULT_IN = 0xe0, -+ DRM_PANTHOR_EXCEPTION_ADDR_SIZE_FAULT_OUT0 = 0xe4, -+ DRM_PANTHOR_EXCEPTION_ADDR_SIZE_FAULT_OUT1 = 0xe5, -+ DRM_PANTHOR_EXCEPTION_ADDR_SIZE_FAULT_OUT2 = 0xe6, -+ DRM_PANTHOR_EXCEPTION_ADDR_SIZE_FAULT_OUT3 = 0xe7, -+ DRM_PANTHOR_EXCEPTION_MEM_ATTR_FAULT_0 = 0xe8, -+ DRM_PANTHOR_EXCEPTION_MEM_ATTR_FAULT_1 = 0xe9, -+ DRM_PANTHOR_EXCEPTION_MEM_ATTR_FAULT_2 = 0xea, -+ DRM_PANTHOR_EXCEPTION_MEM_ATTR_FAULT_3 = 0xeb, -+}; -+ -+/** -+ * panthor_exception_is_fault() - Checks if an exception is a fault. -+ * -+ * Return: true if the exception is a fault, false otherwise. -+ */ -+static inline bool -+panthor_exception_is_fault(u32 exception_code) -+{ -+ return exception_code > DRM_PANTHOR_EXCEPTION_MAX_NON_FAULT; -+} -+ -+const char *panthor_exception_name(struct panthor_device *ptdev, -+ u32 exception_code); -+ -+/** -+ * PANTHOR_IRQ_HANDLER() - Define interrupt handlers and the interrupt -+ * registration function. -+ * -+ * The boiler-plate to gracefully deal with shared interrupts is -+ * auto-generated. All you have to do is call PANTHOR_IRQ_HANDLER() -+ * just after the actual handler. The handler prototype is: -+ * -+ * void (*handler)(struct panthor_device *, u32 status); -+ */ -+#define PANTHOR_IRQ_HANDLER(__name, __reg_prefix, __handler) \ -+static irqreturn_t panthor_ ## __name ## _irq_raw_handler(int irq, void *data) \ -+{ \ -+ struct panthor_irq *pirq = data; \ -+ struct panthor_device *ptdev = pirq->ptdev; \ -+ \ -+ if (atomic_read(&pirq->suspended)) \ -+ return IRQ_NONE; \ -+ if (!gpu_read(ptdev, __reg_prefix ## _INT_STAT)) \ -+ return IRQ_NONE; \ -+ \ -+ gpu_write(ptdev, __reg_prefix ## _INT_MASK, 0); \ -+ return IRQ_WAKE_THREAD; \ -+} \ -+ \ -+static irqreturn_t panthor_ ## __name ## _irq_threaded_handler(int irq, void *data) \ -+{ \ -+ struct panthor_irq *pirq = data; \ -+ struct panthor_device *ptdev = pirq->ptdev; \ -+ irqreturn_t ret = IRQ_NONE; \ -+ \ -+ while (true) { \ -+ u32 status = gpu_read(ptdev, __reg_prefix ## _INT_RAWSTAT) & pirq->mask; \ -+ \ -+ if (!status) \ -+ break; \ -+ \ -+ gpu_write(ptdev, __reg_prefix ## _INT_CLEAR, status); \ -+ \ -+ __handler(ptdev, status); \ -+ ret = IRQ_HANDLED; \ -+ } \ -+ \ -+ if (!atomic_read(&pirq->suspended)) \ -+ gpu_write(ptdev, __reg_prefix ## _INT_MASK, pirq->mask); \ -+ \ -+ return ret; \ -+} \ -+ \ -+static inline void panthor_ ## __name ## _irq_suspend(struct panthor_irq *pirq) \ -+{ \ -+ int cookie; \ -+ \ -+ atomic_set(&pirq->suspended, true); \ -+ \ -+ if (drm_dev_enter(&pirq->ptdev->base, &cookie)) { \ -+ gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, 0); \ -+ synchronize_irq(pirq->irq); \ -+ drm_dev_exit(cookie); \ -+ } \ -+ \ -+ pirq->mask = 0; \ -+} \ -+ \ -+static inline void panthor_ ## __name ## _irq_resume(struct panthor_irq *pirq, u32 mask) \ -+{ \ -+ int cookie; \ -+ \ -+ atomic_set(&pirq->suspended, false); \ -+ pirq->mask = mask; \ -+ \ -+ if (drm_dev_enter(&pirq->ptdev->base, &cookie)) { \ -+ gpu_write(pirq->ptdev, __reg_prefix ## _INT_CLEAR, mask); \ -+ gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, mask); \ -+ drm_dev_exit(cookie); \ -+ } \ -+} \ -+ \ -+static int panthor_request_ ## __name ## _irq(struct panthor_device *ptdev, \ -+ struct panthor_irq *pirq, \ -+ int irq, u32 mask) \ -+{ \ -+ pirq->ptdev = ptdev; \ -+ pirq->irq = irq; \ -+ panthor_ ## __name ## _irq_resume(pirq, mask); \ -+ \ -+ return devm_request_threaded_irq(ptdev->base.dev, irq, \ -+ panthor_ ## __name ## _irq_raw_handler, \ -+ panthor_ ## __name ## _irq_threaded_handler, \ -+ IRQF_SHARED, KBUILD_MODNAME "-" # __name, \ -+ pirq); \ -+} -+ -+/** -+ * panthor_device_mmio_offset() - Turn a user MMIO offset into a kernel one -+ * @offset: Offset to convert. -+ * -+ * With 32-bit systems being limited by the 32-bit representation of mmap2's -+ * pgoffset field, we need to make the MMIO offset arch specific. This function -+ * converts a user MMIO offset into something the kernel driver understands. -+ * -+ * If the kernel and userspace architecture match, the offset is unchanged. If -+ * the kernel is 64-bit and userspace is 32-bit, the offset is adjusted to match -+ * 64-bit offsets. 32-bit kernel with 64-bit userspace is impossible. -+ * -+ * Return: Adjusted offset. -+ */ -+static inline u64 panthor_device_mmio_offset(u64 offset) -+{ -+#ifdef CONFIG_ARM64 -+ if (test_tsk_thread_flag(current, TIF_32BIT)) -+ offset += DRM_PANTHOR_USER_MMIO_OFFSET_64BIT - DRM_PANTHOR_USER_MMIO_OFFSET_32BIT; -+#endif -+ -+ return offset; -+} -+ -+extern struct workqueue_struct *panthor_cleanup_wq; -+ -+#endif --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:18 +0100 -Subject: drm/panthor: Add the GPU logical block - -Handles everything that's not related to the FW, the MMU or the -scheduler. This is the block dealing with the GPU property retrieval, -the GPU block power on/off logic, and some global operations, like -global cache flushing. - -v6: -- Add Maxime's and Heiko's acks - -v5: -- Fix GPU_MODEL() kernel doc -- Fix test in panthor_gpu_block_power_off() -- Add Steve's R-b - -v4: -- Expose CORE_FEATURES through DEV_QUERY - -v3: -- Add acks for the MIT/GPL2 relicensing -- Use macros to extract GPU ID info -- Make sure we reset clear pending_reqs bits when wait_event_timeout() - times out but the corresponding bit is cleared in GPU_INT_RAWSTAT - (can happen if the IRQ is masked or HW takes to long to call the IRQ - handler) -- GPU_MODEL now takes separate arch and product majors to be more - readable. -- Drop GPU_IRQ_MCU_STATUS_CHANGED from interrupt mask. -- Handle GPU_IRQ_PROTM_FAULT correctly (don't output registers that are - not updated for protected interrupts). -- Minor code tidy ups - -Cc: Alexey Sheplyakov # MIT+GPL2 relicensing -Co-developed-by: Steven Price -Signed-off-by: Steven Price -Signed-off-by: Boris Brezillon -Acked-by: Steven Price # MIT+GPL2 relicensing,Arm -Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro -Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora -Reviewed-by: Steven Price -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - drivers/gpu/drm/panthor/panthor_gpu.c | 482 ++++++++++ - drivers/gpu/drm/panthor/panthor_gpu.h | 52 + - 2 files changed, 534 insertions(+) - -diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/panthor/panthor_gpu.c -new file mode 100644 -index 000000000000..6dbbc4cfbe7e ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_gpu.c -@@ -0,0 +1,482 @@ -+// SPDX-License-Identifier: GPL-2.0 or MIT -+/* Copyright 2018 Marty E. Plummer */ -+/* Copyright 2019 Linaro, Ltd., Rob Herring */ -+/* Copyright 2019 Collabora ltd. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "panthor_device.h" -+#include "panthor_gpu.h" -+#include "panthor_regs.h" -+ -+/** -+ * struct panthor_gpu - GPU block management data. -+ */ -+struct panthor_gpu { -+ /** @irq: GPU irq. */ -+ struct panthor_irq irq; -+ -+ /** @reqs_lock: Lock protecting access to pending_reqs. */ -+ spinlock_t reqs_lock; -+ -+ /** @pending_reqs: Pending GPU requests. */ -+ u32 pending_reqs; -+ -+ /** @reqs_acked: GPU request wait queue. */ -+ wait_queue_head_t reqs_acked; -+}; -+ -+/** -+ * struct panthor_model - GPU model description -+ */ -+struct panthor_model { -+ /** @name: Model name. */ -+ const char *name; -+ -+ /** @arch_major: Major version number of architecture. */ -+ u8 arch_major; -+ -+ /** @product_major: Major version number of product. */ -+ u8 product_major; -+}; -+ -+/** -+ * GPU_MODEL() - Define a GPU model. A GPU product can be uniquely identified -+ * by a combination of the major architecture version and the major product -+ * version. -+ * @_name: Name for the GPU model. -+ * @_arch_major: Architecture major. -+ * @_product_major: Product major. -+ */ -+#define GPU_MODEL(_name, _arch_major, _product_major) \ -+{\ -+ .name = __stringify(_name), \ -+ .arch_major = _arch_major, \ -+ .product_major = _product_major, \ -+} -+ -+static const struct panthor_model gpu_models[] = { -+ GPU_MODEL(g610, 10, 7), -+ {}, -+}; -+ -+#define GPU_INTERRUPTS_MASK \ -+ (GPU_IRQ_FAULT | \ -+ GPU_IRQ_PROTM_FAULT | \ -+ GPU_IRQ_RESET_COMPLETED | \ -+ GPU_IRQ_CLEAN_CACHES_COMPLETED) -+ -+static void panthor_gpu_init_info(struct panthor_device *ptdev) -+{ -+ const struct panthor_model *model; -+ u32 arch_major, product_major; -+ u32 major, minor, status; -+ unsigned int i; -+ -+ ptdev->gpu_info.gpu_id = gpu_read(ptdev, GPU_ID); -+ ptdev->gpu_info.csf_id = gpu_read(ptdev, GPU_CSF_ID); -+ ptdev->gpu_info.gpu_rev = gpu_read(ptdev, GPU_REVID); -+ ptdev->gpu_info.core_features = gpu_read(ptdev, GPU_CORE_FEATURES); -+ ptdev->gpu_info.l2_features = gpu_read(ptdev, GPU_L2_FEATURES); -+ ptdev->gpu_info.tiler_features = gpu_read(ptdev, GPU_TILER_FEATURES); -+ ptdev->gpu_info.mem_features = gpu_read(ptdev, GPU_MEM_FEATURES); -+ ptdev->gpu_info.mmu_features = gpu_read(ptdev, GPU_MMU_FEATURES); -+ ptdev->gpu_info.thread_features = gpu_read(ptdev, GPU_THREAD_FEATURES); -+ ptdev->gpu_info.max_threads = gpu_read(ptdev, GPU_THREAD_MAX_THREADS); -+ ptdev->gpu_info.thread_max_workgroup_size = gpu_read(ptdev, GPU_THREAD_MAX_WORKGROUP_SIZE); -+ ptdev->gpu_info.thread_max_barrier_size = gpu_read(ptdev, GPU_THREAD_MAX_BARRIER_SIZE); -+ ptdev->gpu_info.coherency_features = gpu_read(ptdev, GPU_COHERENCY_FEATURES); -+ for (i = 0; i < 4; i++) -+ ptdev->gpu_info.texture_features[i] = gpu_read(ptdev, GPU_TEXTURE_FEATURES(i)); -+ -+ ptdev->gpu_info.as_present = gpu_read(ptdev, GPU_AS_PRESENT); -+ -+ ptdev->gpu_info.shader_present = gpu_read(ptdev, GPU_SHADER_PRESENT_LO); -+ ptdev->gpu_info.shader_present |= (u64)gpu_read(ptdev, GPU_SHADER_PRESENT_HI) << 32; -+ -+ ptdev->gpu_info.tiler_present = gpu_read(ptdev, GPU_TILER_PRESENT_LO); -+ ptdev->gpu_info.tiler_present |= (u64)gpu_read(ptdev, GPU_TILER_PRESENT_HI) << 32; -+ -+ ptdev->gpu_info.l2_present = gpu_read(ptdev, GPU_L2_PRESENT_LO); -+ ptdev->gpu_info.l2_present |= (u64)gpu_read(ptdev, GPU_L2_PRESENT_HI) << 32; -+ -+ arch_major = GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id); -+ product_major = GPU_PROD_MAJOR(ptdev->gpu_info.gpu_id); -+ major = GPU_VER_MAJOR(ptdev->gpu_info.gpu_id); -+ minor = GPU_VER_MINOR(ptdev->gpu_info.gpu_id); -+ status = GPU_VER_STATUS(ptdev->gpu_info.gpu_id); -+ -+ for (model = gpu_models; model->name; model++) { -+ if (model->arch_major == arch_major && -+ model->product_major == product_major) -+ break; -+ } -+ -+ drm_info(&ptdev->base, -+ "mali-%s id 0x%x major 0x%x minor 0x%x status 0x%x", -+ model->name ?: "unknown", ptdev->gpu_info.gpu_id >> 16, -+ major, minor, status); -+ -+ drm_info(&ptdev->base, -+ "Features: L2:%#x Tiler:%#x Mem:%#x MMU:%#x AS:%#x", -+ ptdev->gpu_info.l2_features, -+ ptdev->gpu_info.tiler_features, -+ ptdev->gpu_info.mem_features, -+ ptdev->gpu_info.mmu_features, -+ ptdev->gpu_info.as_present); -+ -+ drm_info(&ptdev->base, -+ "shader_present=0x%0llx l2_present=0x%0llx tiler_present=0x%0llx", -+ ptdev->gpu_info.shader_present, ptdev->gpu_info.l2_present, -+ ptdev->gpu_info.tiler_present); -+} -+ -+static void panthor_gpu_irq_handler(struct panthor_device *ptdev, u32 status) -+{ -+ if (status & GPU_IRQ_FAULT) { -+ u32 fault_status = gpu_read(ptdev, GPU_FAULT_STATUS); -+ u64 address = ((u64)gpu_read(ptdev, GPU_FAULT_ADDR_HI) << 32) | -+ gpu_read(ptdev, GPU_FAULT_ADDR_LO); -+ -+ drm_warn(&ptdev->base, "GPU Fault 0x%08x (%s) at 0x%016llx\n", -+ fault_status, panthor_exception_name(ptdev, fault_status & 0xFF), -+ address); -+ } -+ if (status & GPU_IRQ_PROTM_FAULT) -+ drm_warn(&ptdev->base, "GPU Fault in protected mode\n"); -+ -+ spin_lock(&ptdev->gpu->reqs_lock); -+ if (status & ptdev->gpu->pending_reqs) { -+ ptdev->gpu->pending_reqs &= ~status; -+ wake_up_all(&ptdev->gpu->reqs_acked); -+ } -+ spin_unlock(&ptdev->gpu->reqs_lock); -+} -+PANTHOR_IRQ_HANDLER(gpu, GPU, panthor_gpu_irq_handler); -+ -+/** -+ * panthor_gpu_unplug() - Called when the GPU is unplugged. -+ * @ptdev: Device to unplug. -+ */ -+void panthor_gpu_unplug(struct panthor_device *ptdev) -+{ -+ unsigned long flags; -+ -+ /* Make sure the IRQ handler is not running after that point. */ -+ panthor_gpu_irq_suspend(&ptdev->gpu->irq); -+ -+ /* Wake-up all waiters. */ -+ spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); -+ ptdev->gpu->pending_reqs = 0; -+ wake_up_all(&ptdev->gpu->reqs_acked); -+ spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags); -+} -+ -+/** -+ * panthor_gpu_init() - Initialize the GPU block -+ * @ptdev: Device. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_gpu_init(struct panthor_device *ptdev) -+{ -+ struct panthor_gpu *gpu; -+ u32 pa_bits; -+ int ret, irq; -+ -+ gpu = drmm_kzalloc(&ptdev->base, sizeof(*gpu), GFP_KERNEL); -+ if (!gpu) -+ return -ENOMEM; -+ -+ spin_lock_init(&gpu->reqs_lock); -+ init_waitqueue_head(&gpu->reqs_acked); -+ ptdev->gpu = gpu; -+ panthor_gpu_init_info(ptdev); -+ -+ dma_set_max_seg_size(ptdev->base.dev, UINT_MAX); -+ pa_bits = GPU_MMU_FEATURES_PA_BITS(ptdev->gpu_info.mmu_features); -+ ret = dma_set_mask_and_coherent(ptdev->base.dev, DMA_BIT_MASK(pa_bits)); -+ if (ret) -+ return ret; -+ -+ irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "gpu"); -+ if (irq <= 0) -+ return ret; -+ -+ ret = panthor_request_gpu_irq(ptdev, &ptdev->gpu->irq, irq, GPU_INTERRUPTS_MASK); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+/** -+ * panthor_gpu_block_power_off() - Power-off a specific block of the GPU -+ * @ptdev: Device. -+ * @blk_name: Block name. -+ * @pwroff_reg: Power-off register for this block. -+ * @pwrtrans_reg: Power transition register for this block. -+ * @mask: Sub-elements to power-off. -+ * @timeout_us: Timeout in microseconds. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_gpu_block_power_off(struct panthor_device *ptdev, -+ const char *blk_name, -+ u32 pwroff_reg, u32 pwrtrans_reg, -+ u64 mask, u32 timeout_us) -+{ -+ u32 val, i; -+ int ret; -+ -+ for (i = 0; i < 2; i++) { -+ u32 mask32 = mask >> (i * 32); -+ -+ if (!mask32) -+ continue; -+ -+ ret = readl_relaxed_poll_timeout(ptdev->iomem + pwrtrans_reg + (i * 4), -+ val, !(mask32 & val), -+ 100, timeout_us); -+ if (ret) { -+ drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition", -+ blk_name, mask); -+ return ret; -+ } -+ } -+ -+ if (mask & GENMASK(31, 0)) -+ gpu_write(ptdev, pwroff_reg, mask); -+ -+ if (mask >> 32) -+ gpu_write(ptdev, pwroff_reg + 4, mask >> 32); -+ -+ for (i = 0; i < 2; i++) { -+ u32 mask32 = mask >> (i * 32); -+ -+ if (!mask32) -+ continue; -+ -+ ret = readl_relaxed_poll_timeout(ptdev->iomem + pwrtrans_reg + (i * 4), -+ val, !(mask32 & val), -+ 100, timeout_us); -+ if (ret) { -+ drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition", -+ blk_name, mask); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * panthor_gpu_block_power_on() - Power-on a specific block of the GPU -+ * @ptdev: Device. -+ * @blk_name: Block name. -+ * @pwron_reg: Power-on register for this block. -+ * @pwrtrans_reg: Power transition register for this block. -+ * @rdy_reg: Power transition ready register. -+ * @mask: Sub-elements to power-on. -+ * @timeout_us: Timeout in microseconds. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_gpu_block_power_on(struct panthor_device *ptdev, -+ const char *blk_name, -+ u32 pwron_reg, u32 pwrtrans_reg, -+ u32 rdy_reg, u64 mask, u32 timeout_us) -+{ -+ u32 val, i; -+ int ret; -+ -+ for (i = 0; i < 2; i++) { -+ u32 mask32 = mask >> (i * 32); -+ -+ if (!mask32) -+ continue; -+ -+ ret = readl_relaxed_poll_timeout(ptdev->iomem + pwrtrans_reg + (i * 4), -+ val, !(mask32 & val), -+ 100, timeout_us); -+ if (ret) { -+ drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition", -+ blk_name, mask); -+ return ret; -+ } -+ } -+ -+ if (mask & GENMASK(31, 0)) -+ gpu_write(ptdev, pwron_reg, mask); -+ -+ if (mask >> 32) -+ gpu_write(ptdev, pwron_reg + 4, mask >> 32); -+ -+ for (i = 0; i < 2; i++) { -+ u32 mask32 = mask >> (i * 32); -+ -+ if (!mask32) -+ continue; -+ -+ ret = readl_relaxed_poll_timeout(ptdev->iomem + rdy_reg + (i * 4), -+ val, (mask32 & val) == mask32, -+ 100, timeout_us); -+ if (ret) { -+ drm_err(&ptdev->base, "timeout waiting on %s:%llx readyness", -+ blk_name, mask); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * panthor_gpu_l2_power_on() - Power-on the L2-cache -+ * @ptdev: Device. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_gpu_l2_power_on(struct panthor_device *ptdev) -+{ -+ if (ptdev->gpu_info.l2_present != 1) { -+ /* -+ * Only support one core group now. -+ * ~(l2_present - 1) unsets all bits in l2_present except -+ * the bottom bit. (l2_present - 2) has all the bits in -+ * the first core group set. AND them together to generate -+ * a mask of cores in the first core group. -+ */ -+ u64 core_mask = ~(ptdev->gpu_info.l2_present - 1) & -+ (ptdev->gpu_info.l2_present - 2); -+ drm_info_once(&ptdev->base, "using only 1st core group (%lu cores from %lu)\n", -+ hweight64(core_mask), -+ hweight64(ptdev->gpu_info.shader_present)); -+ } -+ -+ return panthor_gpu_power_on(ptdev, L2, 1, 20000); -+} -+ -+/** -+ * panthor_gpu_flush_caches() - Flush caches -+ * @ptdev: Device. -+ * @l2: L2 flush type. -+ * @lsc: LSC flush type. -+ * @other: Other flush type. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_gpu_flush_caches(struct panthor_device *ptdev, -+ u32 l2, u32 lsc, u32 other) -+{ -+ bool timedout = false; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); -+ if (!drm_WARN_ON(&ptdev->base, -+ ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED)) { -+ ptdev->gpu->pending_reqs |= GPU_IRQ_CLEAN_CACHES_COMPLETED; -+ gpu_write(ptdev, GPU_CMD, GPU_FLUSH_CACHES(l2, lsc, other)); -+ } -+ spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags); -+ -+ if (!wait_event_timeout(ptdev->gpu->reqs_acked, -+ !(ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED), -+ msecs_to_jiffies(100))) { -+ spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); -+ if ((ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED) != 0 && -+ !(gpu_read(ptdev, GPU_INT_RAWSTAT) & GPU_IRQ_CLEAN_CACHES_COMPLETED)) -+ timedout = true; -+ else -+ ptdev->gpu->pending_reqs &= ~GPU_IRQ_CLEAN_CACHES_COMPLETED; -+ spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags); -+ } -+ -+ if (timedout) { -+ drm_err(&ptdev->base, "Flush caches timeout"); -+ return -ETIMEDOUT; -+ } -+ -+ return 0; -+} -+ -+/** -+ * panthor_gpu_soft_reset() - Issue a soft-reset -+ * @ptdev: Device. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_gpu_soft_reset(struct panthor_device *ptdev) -+{ -+ bool timedout = false; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); -+ if (!drm_WARN_ON(&ptdev->base, -+ ptdev->gpu->pending_reqs & GPU_IRQ_RESET_COMPLETED)) { -+ ptdev->gpu->pending_reqs |= GPU_IRQ_RESET_COMPLETED; -+ gpu_write(ptdev, GPU_INT_CLEAR, GPU_IRQ_RESET_COMPLETED); -+ gpu_write(ptdev, GPU_CMD, GPU_SOFT_RESET); -+ } -+ spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags); -+ -+ if (!wait_event_timeout(ptdev->gpu->reqs_acked, -+ !(ptdev->gpu->pending_reqs & GPU_IRQ_RESET_COMPLETED), -+ msecs_to_jiffies(100))) { -+ spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); -+ if ((ptdev->gpu->pending_reqs & GPU_IRQ_RESET_COMPLETED) != 0 && -+ !(gpu_read(ptdev, GPU_INT_RAWSTAT) & GPU_IRQ_RESET_COMPLETED)) -+ timedout = true; -+ else -+ ptdev->gpu->pending_reqs &= ~GPU_IRQ_RESET_COMPLETED; -+ spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags); -+ } -+ -+ if (timedout) { -+ drm_err(&ptdev->base, "Soft reset timeout"); -+ return -ETIMEDOUT; -+ } -+ -+ return 0; -+} -+ -+/** -+ * panthor_gpu_suspend() - Suspend the GPU block. -+ * @ptdev: Device. -+ * -+ * Suspend the GPU irq. This should be called last in the suspend procedure, -+ * after all other blocks have been suspented. -+ */ -+void panthor_gpu_suspend(struct panthor_device *ptdev) -+{ -+ /* -+ * It may be preferable to simply power down the L2, but for now just -+ * soft-reset which will leave the L2 powered down. -+ */ -+ panthor_gpu_soft_reset(ptdev); -+ panthor_gpu_irq_suspend(&ptdev->gpu->irq); -+} -+ -+/** -+ * panthor_gpu_resume() - Resume the GPU block. -+ * @ptdev: Device. -+ * -+ * Resume the IRQ handler and power-on the L2-cache. -+ * The FW takes care of powering the other blocks. -+ */ -+void panthor_gpu_resume(struct panthor_device *ptdev) -+{ -+ panthor_gpu_irq_resume(&ptdev->gpu->irq, GPU_INTERRUPTS_MASK); -+ panthor_gpu_l2_power_on(ptdev); -+} -diff --git a/drivers/gpu/drm/panthor/panthor_gpu.h b/drivers/gpu/drm/panthor/panthor_gpu.h -new file mode 100644 -index 000000000000..bba7555dd3c6 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_gpu.h -@@ -0,0 +1,52 @@ -+/* SPDX-License-Identifier: GPL-2.0 or MIT */ -+/* Copyright 2018 Marty E. Plummer */ -+/* Copyright 2019 Collabora ltd. */ -+ -+#ifndef __PANTHOR_GPU_H__ -+#define __PANTHOR_GPU_H__ -+ -+struct panthor_device; -+ -+int panthor_gpu_init(struct panthor_device *ptdev); -+void panthor_gpu_unplug(struct panthor_device *ptdev); -+void panthor_gpu_suspend(struct panthor_device *ptdev); -+void panthor_gpu_resume(struct panthor_device *ptdev); -+ -+int panthor_gpu_block_power_on(struct panthor_device *ptdev, -+ const char *blk_name, -+ u32 pwron_reg, u32 pwrtrans_reg, -+ u32 rdy_reg, u64 mask, u32 timeout_us); -+int panthor_gpu_block_power_off(struct panthor_device *ptdev, -+ const char *blk_name, -+ u32 pwroff_reg, u32 pwrtrans_reg, -+ u64 mask, u32 timeout_us); -+ -+/** -+ * panthor_gpu_power_on() - Power on the GPU block. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+#define panthor_gpu_power_on(ptdev, type, mask, timeout_us) \ -+ panthor_gpu_block_power_on(ptdev, #type, \ -+ type ## _PWRON_LO, \ -+ type ## _PWRTRANS_LO, \ -+ type ## _READY_LO, \ -+ mask, timeout_us) -+ -+/** -+ * panthor_gpu_power_off() - Power off the GPU block. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+#define panthor_gpu_power_off(ptdev, type, mask, timeout_us) \ -+ panthor_gpu_block_power_off(ptdev, #type, \ -+ type ## _PWROFF_LO, \ -+ type ## _PWRTRANS_LO, \ -+ mask, timeout_us) -+ -+int panthor_gpu_l2_power_on(struct panthor_device *ptdev); -+int panthor_gpu_flush_caches(struct panthor_device *ptdev, -+ u32 l2, u32 lsc, u32 other); -+int panthor_gpu_soft_reset(struct panthor_device *ptdev); -+ -+#endif --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:19 +0100 -Subject: drm/panthor: Add GEM logical block - -Anything relating to GEM object management is placed here. Nothing -particularly interesting here, given the implementation is based on -drm_gem_shmem_object, which is doing most of the work. - -v6: -- Add Maxime's and Heiko's acks -- Return a page-aligned BO size to userspace when creating a BO -- Keep header inclusion alphabetically ordered - -v5: -- Add Liviu's and Steve's R-b - -v4: -- Force kernel BOs to be GPU mapped -- Make panthor_kernel_bo_destroy() robust against ERR/NULL BO pointers - to simplify the call sites - -v3: -- Add acks for the MIT/GPL2 relicensing -- Provide a panthor_kernel_bo abstraction for buffer objects managed by - the kernel (will replace panthor_fw_mem and be used everywhere we were - using panthor_gem_create_and_map() before) -- Adjust things to match drm_gpuvm changes -- Change return of panthor_gem_create_with_handle() to int - -Co-developed-by: Steven Price -Signed-off-by: Steven Price -Signed-off-by: Boris Brezillon -Acked-by: Steven Price # MIT+GPL2 relicensing,Arm -Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro -Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora -Reviewed-by: Liviu Dudau -Reviewed-by: Steven Price -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - drivers/gpu/drm/panthor/panthor_gem.c | 230 ++++++++++ - drivers/gpu/drm/panthor/panthor_gem.h | 142 ++++++ - 2 files changed, 372 insertions(+) - -diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c -new file mode 100644 -index 000000000000..d6483266d0c2 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_gem.c -@@ -0,0 +1,230 @@ -+// SPDX-License-Identifier: GPL-2.0 or MIT -+/* Copyright 2019 Linaro, Ltd, Rob Herring */ -+/* Copyright 2023 Collabora ltd. */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "panthor_device.h" -+#include "panthor_gem.h" -+#include "panthor_mmu.h" -+ -+static void panthor_gem_free_object(struct drm_gem_object *obj) -+{ -+ struct panthor_gem_object *bo = to_panthor_bo(obj); -+ struct drm_gem_object *vm_root_gem = bo->exclusive_vm_root_gem; -+ -+ drm_gem_free_mmap_offset(&bo->base.base); -+ mutex_destroy(&bo->gpuva_list_lock); -+ drm_gem_shmem_free(&bo->base); -+ drm_gem_object_put(vm_root_gem); -+} -+ -+/** -+ * panthor_kernel_bo_destroy() - Destroy a kernel buffer object -+ * @vm: The VM this BO was mapped to. -+ * @bo: Kernel buffer object to destroy. If NULL or an ERR_PTR(), the destruction -+ * is skipped. -+ */ -+void panthor_kernel_bo_destroy(struct panthor_vm *vm, -+ struct panthor_kernel_bo *bo) -+{ -+ int ret; -+ -+ if (IS_ERR_OR_NULL(bo)) -+ return; -+ -+ panthor_kernel_bo_vunmap(bo); -+ -+ if (drm_WARN_ON(bo->obj->dev, -+ to_panthor_bo(bo->obj)->exclusive_vm_root_gem != panthor_vm_root_gem(vm))) -+ goto out_free_bo; -+ -+ ret = panthor_vm_unmap_range(vm, bo->va_node.start, -+ panthor_kernel_bo_size(bo)); -+ if (ret) -+ goto out_free_bo; -+ -+ panthor_vm_free_va(vm, &bo->va_node); -+ drm_gem_object_put(bo->obj); -+ -+out_free_bo: -+ kfree(bo); -+} -+ -+/** -+ * panthor_kernel_bo_create() - Create and map a GEM object to a VM -+ * @ptdev: Device. -+ * @vm: VM to map the GEM to. If NULL, the kernel object is not GPU mapped. -+ * @size: Size of the buffer object. -+ * @bo_flags: Combination of drm_panthor_bo_flags flags. -+ * @vm_map_flags: Combination of drm_panthor_vm_bind_op_flags (only those -+ * that are related to map operations). -+ * @gpu_va: GPU address assigned when mapping to the VM. -+ * If gpu_va == PANTHOR_VM_KERNEL_AUTO_VA, the virtual address will be -+ * automatically allocated. -+ * -+ * Return: A valid pointer in case of success, an ERR_PTR() otherwise. -+ */ -+struct panthor_kernel_bo * -+panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm, -+ size_t size, u32 bo_flags, u32 vm_map_flags, -+ u64 gpu_va) -+{ -+ struct drm_gem_shmem_object *obj; -+ struct panthor_kernel_bo *kbo; -+ struct panthor_gem_object *bo; -+ int ret; -+ -+ if (drm_WARN_ON(&ptdev->base, !vm)) -+ return ERR_PTR(-EINVAL); -+ -+ kbo = kzalloc(sizeof(*kbo), GFP_KERNEL); -+ if (!kbo) -+ return ERR_PTR(-ENOMEM); -+ -+ obj = drm_gem_shmem_create(&ptdev->base, size); -+ if (IS_ERR(obj)) { -+ ret = PTR_ERR(obj); -+ goto err_free_bo; -+ } -+ -+ bo = to_panthor_bo(&obj->base); -+ size = obj->base.size; -+ kbo->obj = &obj->base; -+ bo->flags = bo_flags; -+ -+ ret = panthor_vm_alloc_va(vm, gpu_va, size, &kbo->va_node); -+ if (ret) -+ goto err_put_obj; -+ -+ ret = panthor_vm_map_bo_range(vm, bo, 0, size, kbo->va_node.start, vm_map_flags); -+ if (ret) -+ goto err_free_va; -+ -+ bo->exclusive_vm_root_gem = panthor_vm_root_gem(vm); -+ drm_gem_object_get(bo->exclusive_vm_root_gem); -+ bo->base.base.resv = bo->exclusive_vm_root_gem->resv; -+ return kbo; -+ -+err_free_va: -+ panthor_vm_free_va(vm, &kbo->va_node); -+ -+err_put_obj: -+ drm_gem_object_put(&obj->base); -+ -+err_free_bo: -+ kfree(kbo); -+ return ERR_PTR(ret); -+} -+ -+static int panthor_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) -+{ -+ struct panthor_gem_object *bo = to_panthor_bo(obj); -+ -+ /* Don't allow mmap on objects that have the NO_MMAP flag set. */ -+ if (bo->flags & DRM_PANTHOR_BO_NO_MMAP) -+ return -EINVAL; -+ -+ return drm_gem_shmem_object_mmap(obj, vma); -+} -+ -+static struct dma_buf * -+panthor_gem_prime_export(struct drm_gem_object *obj, int flags) -+{ -+ /* We can't export GEMs that have an exclusive VM. */ -+ if (to_panthor_bo(obj)->exclusive_vm_root_gem) -+ return ERR_PTR(-EINVAL); -+ -+ return drm_gem_prime_export(obj, flags); -+} -+ -+static const struct drm_gem_object_funcs panthor_gem_funcs = { -+ .free = panthor_gem_free_object, -+ .print_info = drm_gem_shmem_object_print_info, -+ .pin = drm_gem_shmem_object_pin, -+ .unpin = drm_gem_shmem_object_unpin, -+ .get_sg_table = drm_gem_shmem_object_get_sg_table, -+ .vmap = drm_gem_shmem_object_vmap, -+ .vunmap = drm_gem_shmem_object_vunmap, -+ .mmap = panthor_gem_mmap, -+ .export = panthor_gem_prime_export, -+ .vm_ops = &drm_gem_shmem_vm_ops, -+}; -+ -+/** -+ * panthor_gem_create_object - Implementation of driver->gem_create_object. -+ * @ddev: DRM device -+ * @size: Size in bytes of the memory the object will reference -+ * -+ * This lets the GEM helpers allocate object structs for us, and keep -+ * our BO stats correct. -+ */ -+struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size) -+{ -+ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); -+ struct panthor_gem_object *obj; -+ -+ obj = kzalloc(sizeof(*obj), GFP_KERNEL); -+ if (!obj) -+ return ERR_PTR(-ENOMEM); -+ -+ obj->base.base.funcs = &panthor_gem_funcs; -+ obj->base.map_wc = !ptdev->coherent; -+ mutex_init(&obj->gpuva_list_lock); -+ drm_gem_gpuva_set_lock(&obj->base.base, &obj->gpuva_list_lock); -+ -+ return &obj->base.base; -+} -+ -+/** -+ * panthor_gem_create_with_handle() - Create a GEM object and attach it to a handle. -+ * @file: DRM file. -+ * @ddev: DRM device. -+ * @exclusive_vm: Exclusive VM. Not NULL if the GEM object can't be shared. -+ * @size: Size of the GEM object to allocate. -+ * @flags: Combination of drm_panthor_bo_flags flags. -+ * @handle: Pointer holding the handle pointing to the new GEM object. -+ * -+ * Return: Zero on success -+ */ -+int -+panthor_gem_create_with_handle(struct drm_file *file, -+ struct drm_device *ddev, -+ struct panthor_vm *exclusive_vm, -+ u64 *size, u32 flags, u32 *handle) -+{ -+ int ret; -+ struct drm_gem_shmem_object *shmem; -+ struct panthor_gem_object *bo; -+ -+ shmem = drm_gem_shmem_create(ddev, *size); -+ if (IS_ERR(shmem)) -+ return PTR_ERR(shmem); -+ -+ bo = to_panthor_bo(&shmem->base); -+ bo->flags = flags; -+ -+ if (exclusive_vm) { -+ bo->exclusive_vm_root_gem = panthor_vm_root_gem(exclusive_vm); -+ drm_gem_object_get(bo->exclusive_vm_root_gem); -+ bo->base.base.resv = bo->exclusive_vm_root_gem->resv; -+ } -+ -+ /* -+ * Allocate an id of idr table where the obj is registered -+ * and handle has the id what user can see. -+ */ -+ ret = drm_gem_handle_create(file, &shmem->base, handle); -+ if (!ret) -+ *size = bo->base.base.size; -+ -+ /* drop reference from allocate - handle holds it now. */ -+ drm_gem_object_put(&shmem->base); -+ -+ return ret; -+} -diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h -new file mode 100644 -index 000000000000..3bccba394d00 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_gem.h -@@ -0,0 +1,142 @@ -+/* SPDX-License-Identifier: GPL-2.0 or MIT */ -+/* Copyright 2019 Linaro, Ltd, Rob Herring */ -+/* Copyright 2023 Collabora ltd. */ -+ -+#ifndef __PANTHOR_GEM_H__ -+#define __PANTHOR_GEM_H__ -+ -+#include -+#include -+ -+#include -+#include -+ -+struct panthor_vm; -+ -+/** -+ * struct panthor_gem_object - Driver specific GEM object. -+ */ -+struct panthor_gem_object { -+ /** @base: Inherit from drm_gem_shmem_object. */ -+ struct drm_gem_shmem_object base; -+ -+ /** -+ * @exclusive_vm_root_gem: Root GEM of the exclusive VM this GEM object -+ * is attached to. -+ * -+ * If @exclusive_vm_root_gem != NULL, any attempt to bind the GEM to a -+ * different VM will fail. -+ * -+ * All FW memory objects have this field set to the root GEM of the MCU -+ * VM. -+ */ -+ struct drm_gem_object *exclusive_vm_root_gem; -+ -+ /** -+ * @gpuva_list_lock: Custom GPUVA lock. -+ * -+ * Used to protect insertion of drm_gpuva elements to the -+ * drm_gem_object.gpuva.list list. -+ * -+ * We can't use the GEM resv for that, because drm_gpuva_link() is -+ * called in a dma-signaling path, where we're not allowed to take -+ * resv locks. -+ */ -+ struct mutex gpuva_list_lock; -+ -+ /** @flags: Combination of drm_panthor_bo_flags flags. */ -+ u32 flags; -+}; -+ -+/** -+ * struct panthor_kernel_bo - Kernel buffer object. -+ * -+ * These objects are only manipulated by the kernel driver and not -+ * directly exposed to the userspace. The GPU address of a kernel -+ * BO might be passed to userspace though. -+ */ -+struct panthor_kernel_bo { -+ /** -+ * @obj: The GEM object backing this kernel buffer object. -+ */ -+ struct drm_gem_object *obj; -+ -+ /** -+ * @va_node: VA space allocated to this GEM. -+ */ -+ struct drm_mm_node va_node; -+ -+ /** -+ * @kmap: Kernel CPU mapping of @gem. -+ */ -+ void *kmap; -+}; -+ -+static inline -+struct panthor_gem_object *to_panthor_bo(struct drm_gem_object *obj) -+{ -+ return container_of(to_drm_gem_shmem_obj(obj), struct panthor_gem_object, base); -+} -+ -+struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size); -+ -+struct drm_gem_object * -+panthor_gem_prime_import_sg_table(struct drm_device *ddev, -+ struct dma_buf_attachment *attach, -+ struct sg_table *sgt); -+ -+int -+panthor_gem_create_with_handle(struct drm_file *file, -+ struct drm_device *ddev, -+ struct panthor_vm *exclusive_vm, -+ u64 *size, u32 flags, uint32_t *handle); -+ -+static inline u64 -+panthor_kernel_bo_gpuva(struct panthor_kernel_bo *bo) -+{ -+ return bo->va_node.start; -+} -+ -+static inline size_t -+panthor_kernel_bo_size(struct panthor_kernel_bo *bo) -+{ -+ return bo->obj->size; -+} -+ -+static inline int -+panthor_kernel_bo_vmap(struct panthor_kernel_bo *bo) -+{ -+ struct iosys_map map; -+ int ret; -+ -+ if (bo->kmap) -+ return 0; -+ -+ ret = drm_gem_vmap_unlocked(bo->obj, &map); -+ if (ret) -+ return ret; -+ -+ bo->kmap = map.vaddr; -+ return 0; -+} -+ -+static inline void -+panthor_kernel_bo_vunmap(struct panthor_kernel_bo *bo) -+{ -+ if (bo->kmap) { -+ struct iosys_map map = IOSYS_MAP_INIT_VADDR(bo->kmap); -+ -+ drm_gem_vunmap_unlocked(bo->obj, &map); -+ bo->kmap = NULL; -+ } -+} -+ -+struct panthor_kernel_bo * -+panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm, -+ size_t size, u32 bo_flags, u32 vm_map_flags, -+ u64 gpu_va); -+ -+void panthor_kernel_bo_destroy(struct panthor_vm *vm, -+ struct panthor_kernel_bo *bo); -+ -+#endif /* __PANTHOR_GEM_H__ */ --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:20 +0100 -Subject: drm/panthor: Add the devfreq logical block - -Every thing related to devfreq in placed in panthor_devfreq.c, and -helpers that can be called by other logical blocks are exposed through -panthor_devfreq.h. - -This implementation is loosely based on the panfrost implementation, -the only difference being that we don't count device users, because -the idle/active state will be managed by the scheduler logic. - -v6: -- Add Maxime's and Heiko's acks -- Keep header inclusion alphabetically ordered - -v4: -- Add Clement's A-b for the relicensing - -v3: -- Add acks for the MIT/GPL2 relicensing - -v2: -- Added in v2 - -Cc: Clement Peron # MIT+GPL2 relicensing -Reviewed-by: Steven Price -Signed-off-by: Boris Brezillon -Acked-by: Steven Price # MIT+GPL2 relicensing,Arm -Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro -Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora -Acked-by: Clement Peron # MIT+GPL2 relicensing -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - drivers/gpu/drm/panthor/panthor_devfreq.c | 283 ++++++++++ - drivers/gpu/drm/panthor/panthor_devfreq.h | 21 + - 2 files changed, 304 insertions(+) - -diff --git a/drivers/gpu/drm/panthor/panthor_devfreq.c b/drivers/gpu/drm/panthor/panthor_devfreq.c -new file mode 100644 -index 000000000000..7ac4fa290f27 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_devfreq.c -@@ -0,0 +1,283 @@ -+// SPDX-License-Identifier: GPL-2.0 or MIT -+/* Copyright 2019 Collabora ltd. */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "panthor_devfreq.h" -+#include "panthor_device.h" -+ -+/** -+ * struct panthor_devfreq - Device frequency management -+ */ -+struct panthor_devfreq { -+ /** @devfreq: devfreq device. */ -+ struct devfreq *devfreq; -+ -+ /** @gov_data: Governor data. */ -+ struct devfreq_simple_ondemand_data gov_data; -+ -+ /** @busy_time: Busy time. */ -+ ktime_t busy_time; -+ -+ /** @idle_time: Idle time. */ -+ ktime_t idle_time; -+ -+ /** @time_last_update: Last update time. */ -+ ktime_t time_last_update; -+ -+ /** @last_busy_state: True if the GPU was busy last time we updated the state. */ -+ bool last_busy_state; -+ -+ /* -+ * @lock: Lock used to protect busy_time, idle_time, time_last_update and -+ * last_busy_state. -+ * -+ * These fields can be accessed concurrently by panthor_devfreq_get_dev_status() -+ * and panthor_devfreq_record_{busy,idle}(). -+ */ -+ spinlock_t lock; -+}; -+ -+static void panthor_devfreq_update_utilization(struct panthor_devfreq *pdevfreq) -+{ -+ ktime_t now, last; -+ -+ now = ktime_get(); -+ last = pdevfreq->time_last_update; -+ -+ if (pdevfreq->last_busy_state) -+ pdevfreq->busy_time += ktime_sub(now, last); -+ else -+ pdevfreq->idle_time += ktime_sub(now, last); -+ -+ pdevfreq->time_last_update = now; -+} -+ -+static int panthor_devfreq_target(struct device *dev, unsigned long *freq, -+ u32 flags) -+{ -+ struct dev_pm_opp *opp; -+ -+ opp = devfreq_recommended_opp(dev, freq, flags); -+ if (IS_ERR(opp)) -+ return PTR_ERR(opp); -+ dev_pm_opp_put(opp); -+ -+ return dev_pm_opp_set_rate(dev, *freq); -+} -+ -+static void panthor_devfreq_reset(struct panthor_devfreq *pdevfreq) -+{ -+ pdevfreq->busy_time = 0; -+ pdevfreq->idle_time = 0; -+ pdevfreq->time_last_update = ktime_get(); -+} -+ -+static int panthor_devfreq_get_dev_status(struct device *dev, -+ struct devfreq_dev_status *status) -+{ -+ struct panthor_device *ptdev = dev_get_drvdata(dev); -+ struct panthor_devfreq *pdevfreq = ptdev->devfreq; -+ unsigned long irqflags; -+ -+ status->current_frequency = clk_get_rate(ptdev->clks.core); -+ -+ spin_lock_irqsave(&pdevfreq->lock, irqflags); -+ -+ panthor_devfreq_update_utilization(pdevfreq); -+ -+ status->total_time = ktime_to_ns(ktime_add(pdevfreq->busy_time, -+ pdevfreq->idle_time)); -+ -+ status->busy_time = ktime_to_ns(pdevfreq->busy_time); -+ -+ panthor_devfreq_reset(pdevfreq); -+ -+ spin_unlock_irqrestore(&pdevfreq->lock, irqflags); -+ -+ drm_dbg(&ptdev->base, "busy %lu total %lu %lu %% freq %lu MHz\n", -+ status->busy_time, status->total_time, -+ status->busy_time / (status->total_time / 100), -+ status->current_frequency / 1000 / 1000); -+ -+ return 0; -+} -+ -+static struct devfreq_dev_profile panthor_devfreq_profile = { -+ .timer = DEVFREQ_TIMER_DELAYED, -+ .polling_ms = 50, /* ~3 frames */ -+ .target = panthor_devfreq_target, -+ .get_dev_status = panthor_devfreq_get_dev_status, -+}; -+ -+int panthor_devfreq_init(struct panthor_device *ptdev) -+{ -+ /* There's actually 2 regulators (mali and sram), but the OPP core only -+ * supports one. -+ * -+ * We assume the sram regulator is coupled with the mali one and let -+ * the coupling logic deal with voltage updates. -+ */ -+ static const char * const reg_names[] = { "mali", NULL }; -+ struct thermal_cooling_device *cooling; -+ struct device *dev = ptdev->base.dev; -+ struct panthor_devfreq *pdevfreq; -+ struct dev_pm_opp *opp; -+ unsigned long cur_freq; -+ int ret; -+ -+ pdevfreq = drmm_kzalloc(&ptdev->base, sizeof(*ptdev->devfreq), GFP_KERNEL); -+ if (!pdevfreq) -+ return -ENOMEM; -+ -+ ptdev->devfreq = pdevfreq; -+ -+ ret = devm_pm_opp_set_regulators(dev, reg_names); -+ if (ret) { -+ if (ret != -EPROBE_DEFER) -+ DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n"); -+ -+ return ret; -+ } -+ -+ ret = devm_pm_opp_of_add_table(dev); -+ if (ret) -+ return ret; -+ -+ spin_lock_init(&pdevfreq->lock); -+ -+ panthor_devfreq_reset(pdevfreq); -+ -+ cur_freq = clk_get_rate(ptdev->clks.core); -+ -+ opp = devfreq_recommended_opp(dev, &cur_freq, 0); -+ if (IS_ERR(opp)) -+ return PTR_ERR(opp); -+ -+ panthor_devfreq_profile.initial_freq = cur_freq; -+ -+ /* Regulator coupling only takes care of synchronizing/balancing voltage -+ * updates, but the coupled regulator needs to be enabled manually. -+ * -+ * We use devm_regulator_get_enable_optional() and keep the sram supply -+ * enabled until the device is removed, just like we do for the mali -+ * supply, which is enabled when dev_pm_opp_set_opp(dev, opp) is called, -+ * and disabled when the opp_table is torn down, using the devm action. -+ * -+ * If we really care about disabling regulators on suspend, we should: -+ * - use devm_regulator_get_optional() here -+ * - call dev_pm_opp_set_opp(dev, NULL) before leaving this function -+ * (this disables the regulator passed to the OPP layer) -+ * - call dev_pm_opp_set_opp(dev, NULL) and -+ * regulator_disable(ptdev->regulators.sram) in -+ * panthor_devfreq_suspend() -+ * - call dev_pm_opp_set_opp(dev, default_opp) and -+ * regulator_enable(ptdev->regulators.sram) in -+ * panthor_devfreq_resume() -+ * -+ * But without knowing if it's beneficial or not (in term of power -+ * consumption), or how much it slows down the suspend/resume steps, -+ * let's just keep regulators enabled for the device lifetime. -+ */ -+ ret = devm_regulator_get_enable_optional(dev, "sram"); -+ if (ret && ret != -ENODEV) { -+ if (ret != -EPROBE_DEFER) -+ DRM_DEV_ERROR(dev, "Couldn't retrieve/enable sram supply\n"); -+ return ret; -+ } -+ -+ /* -+ * Set the recommend OPP this will enable and configure the regulator -+ * if any and will avoid a switch off by regulator_late_cleanup() -+ */ -+ ret = dev_pm_opp_set_opp(dev, opp); -+ if (ret) { -+ DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n"); -+ return ret; -+ } -+ -+ dev_pm_opp_put(opp); -+ -+ /* -+ * Setup default thresholds for the simple_ondemand governor. -+ * The values are chosen based on experiments. -+ */ -+ pdevfreq->gov_data.upthreshold = 45; -+ pdevfreq->gov_data.downdifferential = 5; -+ -+ pdevfreq->devfreq = devm_devfreq_add_device(dev, &panthor_devfreq_profile, -+ DEVFREQ_GOV_SIMPLE_ONDEMAND, -+ &pdevfreq->gov_data); -+ if (IS_ERR(pdevfreq->devfreq)) { -+ DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n"); -+ ret = PTR_ERR(pdevfreq->devfreq); -+ pdevfreq->devfreq = NULL; -+ return ret; -+ } -+ -+ cooling = devfreq_cooling_em_register(pdevfreq->devfreq, NULL); -+ if (IS_ERR(cooling)) -+ DRM_DEV_INFO(dev, "Failed to register cooling device\n"); -+ -+ return 0; -+} -+ -+int panthor_devfreq_resume(struct panthor_device *ptdev) -+{ -+ struct panthor_devfreq *pdevfreq = ptdev->devfreq; -+ -+ if (!pdevfreq->devfreq) -+ return 0; -+ -+ panthor_devfreq_reset(pdevfreq); -+ -+ return devfreq_resume_device(pdevfreq->devfreq); -+} -+ -+int panthor_devfreq_suspend(struct panthor_device *ptdev) -+{ -+ struct panthor_devfreq *pdevfreq = ptdev->devfreq; -+ -+ if (!pdevfreq->devfreq) -+ return 0; -+ -+ return devfreq_suspend_device(pdevfreq->devfreq); -+} -+ -+void panthor_devfreq_record_busy(struct panthor_device *ptdev) -+{ -+ struct panthor_devfreq *pdevfreq = ptdev->devfreq; -+ unsigned long irqflags; -+ -+ if (!pdevfreq->devfreq) -+ return; -+ -+ spin_lock_irqsave(&pdevfreq->lock, irqflags); -+ -+ panthor_devfreq_update_utilization(pdevfreq); -+ pdevfreq->last_busy_state = true; -+ -+ spin_unlock_irqrestore(&pdevfreq->lock, irqflags); -+} -+ -+void panthor_devfreq_record_idle(struct panthor_device *ptdev) -+{ -+ struct panthor_devfreq *pdevfreq = ptdev->devfreq; -+ unsigned long irqflags; -+ -+ if (!pdevfreq->devfreq) -+ return; -+ -+ spin_lock_irqsave(&pdevfreq->lock, irqflags); -+ -+ panthor_devfreq_update_utilization(pdevfreq); -+ pdevfreq->last_busy_state = false; -+ -+ spin_unlock_irqrestore(&pdevfreq->lock, irqflags); -+} -diff --git a/drivers/gpu/drm/panthor/panthor_devfreq.h b/drivers/gpu/drm/panthor/panthor_devfreq.h -new file mode 100644 -index 000000000000..83a5c9522493 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_devfreq.h -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0 or MIT */ -+/* Copyright 2019 Collabora ltd. */ -+ -+#ifndef __PANTHOR_DEVFREQ_H__ -+#define __PANTHOR_DEVFREQ_H__ -+ -+struct devfreq; -+struct thermal_cooling_device; -+ -+struct panthor_device; -+struct panthor_devfreq; -+ -+int panthor_devfreq_init(struct panthor_device *ptdev); -+ -+int panthor_devfreq_resume(struct panthor_device *ptdev); -+int panthor_devfreq_suspend(struct panthor_device *ptdev); -+ -+void panthor_devfreq_record_busy(struct panthor_device *ptdev); -+void panthor_devfreq_record_idle(struct panthor_device *ptdev); -+ -+#endif /* __PANTHOR_DEVFREQ_H__ */ --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:21 +0100 -Subject: drm/panthor: Add the MMU/VM logical block - -MMU and VM management is related and placed in the same source file. - -Page table updates are delegated to the io-pgtable-arm driver that's in -the iommu subsystem. - -The VM management logic is based on drm_gpuva_mgr, and is assuming the -VA space is mostly managed by the usermode driver, except for a reserved -portion of this VA-space that's used for kernel objects (like the heap -contexts/chunks). - -Both asynchronous and synchronous VM operations are supported, and -internal helpers are exposed to allow other logical blocks to map their -buffers in the GPU VA space. - -There's one VM_BIND queue per-VM (meaning the Vulkan driver can only -expose one sparse-binding queue), and this bind queue is managed with -a 1:1 drm_sched_entity:drm_gpu_scheduler, such that each VM gets its own -independent execution queue, avoiding VM operation serialization at the -device level (things are still serialized at the VM level). - -The rest is just implementation details that are hopefully well explained -in the documentation. - -v6: -- Add Maxime's and Heiko's acks -- Add Steve's R-b -- Adjust the TRANSCFG value to account for SW VA space limitation on - 32-bit systems -- Keep header inclusion alphabetically ordered - -v5: -- Fix a double panthor_vm_cleanup_op_ctx() call -- Fix a race between panthor_vm_prepare_map_op_ctx() and - panthor_vm_bo_put() -- Fix panthor_vm_pool_destroy_vm() kernel doc -- Fix paddr adjustment in panthor_vm_map_pages() -- Fix bo_offset calculation in panthor_vm_get_bo_for_va() - -v4: -- Add an helper to return the VM state -- Check drmm_mutex_init() return code -- Remove the VM from the AS reclaim list when panthor_vm_active() is - called -- Count the number of active VM users instead of considering there's - at most one user (several scheduling groups can point to the same - vM) -- Pre-allocate a VMA object for unmap operations (unmaps can trigger - a sm_step_remap() call) -- Check vm->root_page_table instead of vm->pgtbl_ops to detect if - the io-pgtable is trying to allocate the root page table -- Don't memset() the va_node in panthor_vm_alloc_va(), make it a - caller requirement -- Fix the kernel doc in a few places -- Drop the panthor_vm::base offset constraint and modify - panthor_vm_put() to explicitly check for a NULL value -- Fix unbalanced vm_bo refcount in panthor_gpuva_sm_step_remap() -- Drop stale comments about the shared_bos list -- Patch mmu_features::va_bits on 32-bit builds to reflect the - io_pgtable limitation and let the UMD know about it - -v3: -- Add acks for the MIT/GPL2 relicensing -- Propagate MMU faults to the scheduler -- Move pages pinning/unpinning out of the dma_signalling path -- Fix 32-bit support -- Rework the user/kernel VA range calculation -- Make the auto-VA range explicit (auto-VA range doesn't cover the full - kernel-VA range on the MCU VM) -- Let callers of panthor_vm_alloc_va() allocate the drm_mm_node - (embedded in panthor_kernel_bo now) -- Adjust things to match the latest drm_gpuvm changes (extobj tracking, - resv prep and more) -- Drop the per-AS lock and use slots_lock (fixes a race on vm->as.id) -- Set as.id to -1 when reusing an address space from the LRU list -- Drop misleading comment about page faults -- Remove check for irq being assigned in panthor_mmu_unplug() - -Co-developed-by: Steven Price -Signed-off-by: Steven Price -Signed-off-by: Boris Brezillon -Acked-by: Steven Price # MIT+GPL2 relicensing,Arm -Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro -Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora -Reviewed-by: Steven Price -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - drivers/gpu/drm/panthor/panthor_mmu.c | 2768 ++++++++++ - drivers/gpu/drm/panthor/panthor_mmu.h | 102 + - 2 files changed, 2870 insertions(+) - -diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c -new file mode 100644 -index 000000000000..fdd35249169f ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_mmu.c -@@ -0,0 +1,2768 @@ -+// SPDX-License-Identifier: GPL-2.0 or MIT -+/* Copyright 2019 Linaro, Ltd, Rob Herring */ -+/* Copyright 2023 Collabora ltd. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "panthor_device.h" -+#include "panthor_gem.h" -+#include "panthor_heap.h" -+#include "panthor_mmu.h" -+#include "panthor_regs.h" -+#include "panthor_sched.h" -+ -+#define MAX_AS_SLOTS 32 -+ -+struct panthor_vm; -+ -+/** -+ * struct panthor_as_slot - Address space slot -+ */ -+struct panthor_as_slot { -+ /** @vm: VM bound to this slot. NULL is no VM is bound. */ -+ struct panthor_vm *vm; -+}; -+ -+/** -+ * struct panthor_mmu - MMU related data -+ */ -+struct panthor_mmu { -+ /** @irq: The MMU irq. */ -+ struct panthor_irq irq; -+ -+ /** @as: Address space related fields. -+ * -+ * The GPU has a limited number of address spaces (AS) slots, forcing -+ * us to re-assign them to re-assign slots on-demand. -+ */ -+ struct { -+ /** @slots_lock: Lock protecting access to all other AS fields. */ -+ struct mutex slots_lock; -+ -+ /** @alloc_mask: Bitmask encoding the allocated slots. */ -+ unsigned long alloc_mask; -+ -+ /** @faulty_mask: Bitmask encoding the faulty slots. */ -+ unsigned long faulty_mask; -+ -+ /** @slots: VMs currently bound to the AS slots. */ -+ struct panthor_as_slot slots[MAX_AS_SLOTS]; -+ -+ /** -+ * @lru_list: List of least recently used VMs. -+ * -+ * We use this list to pick a VM to evict when all slots are -+ * used. -+ * -+ * There should be no more active VMs than there are AS slots, -+ * so this LRU is just here to keep VMs bound until there's -+ * a need to release a slot, thus avoid unnecessary TLB/cache -+ * flushes. -+ */ -+ struct list_head lru_list; -+ } as; -+ -+ /** @vm: VMs management fields */ -+ struct { -+ /** @lock: Lock protecting access to list. */ -+ struct mutex lock; -+ -+ /** @list: List containing all VMs. */ -+ struct list_head list; -+ -+ /** @reset_in_progress: True if a reset is in progress. */ -+ bool reset_in_progress; -+ -+ /** @wq: Workqueue used for the VM_BIND queues. */ -+ struct workqueue_struct *wq; -+ } vm; -+}; -+ -+/** -+ * struct panthor_vm_pool - VM pool object -+ */ -+struct panthor_vm_pool { -+ /** @xa: Array used for VM handle tracking. */ -+ struct xarray xa; -+}; -+ -+/** -+ * struct panthor_vma - GPU mapping object -+ * -+ * This is used to track GEM mappings in GPU space. -+ */ -+struct panthor_vma { -+ /** @base: Inherits from drm_gpuva. */ -+ struct drm_gpuva base; -+ -+ /** @node: Used to implement deferred release of VMAs. */ -+ struct list_head node; -+ -+ /** -+ * @flags: Combination of drm_panthor_vm_bind_op_flags. -+ * -+ * Only map related flags are accepted. -+ */ -+ u32 flags; -+}; -+ -+/** -+ * struct panthor_vm_op_ctx - VM operation context -+ * -+ * With VM operations potentially taking place in a dma-signaling path, we -+ * need to make sure everything that might require resource allocation is -+ * pre-allocated upfront. This is what this operation context is far. -+ * -+ * We also collect resources that have been freed, so we can release them -+ * asynchronously, and let the VM_BIND scheduler process the next VM_BIND -+ * request. -+ */ -+struct panthor_vm_op_ctx { -+ /** @rsvd_page_tables: Pages reserved for the MMU page table update. */ -+ struct { -+ /** @count: Number of pages reserved. */ -+ u32 count; -+ -+ /** @ptr: Point to the first unused page in the @pages table. */ -+ u32 ptr; -+ -+ /** -+ * @page: Array of pages that can be used for an MMU page table update. -+ * -+ * After an VM operation, there might be free pages left in this array. -+ * They should be returned to the pt_cache as part of the op_ctx cleanup. -+ */ -+ void **pages; -+ } rsvd_page_tables; -+ -+ /** -+ * @preallocated_vmas: Pre-allocated VMAs to handle the remap case. -+ * -+ * Partial unmap requests or map requests overlapping existing mappings will -+ * trigger a remap call, which need to register up to three panthor_vma objects -+ * (one for the new mapping, and two for the previous and next mappings). -+ */ -+ struct panthor_vma *preallocated_vmas[3]; -+ -+ /** @flags: Combination of drm_panthor_vm_bind_op_flags. */ -+ u32 flags; -+ -+ /** @va: Virtual range targeted by the VM operation. */ -+ struct { -+ /** @addr: Start address. */ -+ u64 addr; -+ -+ /** @range: Range size. */ -+ u64 range; -+ } va; -+ -+ /** -+ * @returned_vmas: List of panthor_vma objects returned after a VM operation. -+ * -+ * For unmap operations, this will contain all VMAs that were covered by the -+ * specified VA range. -+ * -+ * For map operations, this will contain all VMAs that previously mapped to -+ * the specified VA range. -+ * -+ * Those VMAs, and the resources they point to will be released as part of -+ * the op_ctx cleanup operation. -+ */ -+ struct list_head returned_vmas; -+ -+ /** @map: Fields specific to a map operation. */ -+ struct { -+ /** @vm_bo: Buffer object to map. */ -+ struct drm_gpuvm_bo *vm_bo; -+ -+ /** @bo_offset: Offset in the buffer object. */ -+ u64 bo_offset; -+ -+ /** -+ * @sgt: sg-table pointing to pages backing the GEM object. -+ * -+ * This is gathered at job creation time, such that we don't have -+ * to allocate in ::run_job(). -+ */ -+ struct sg_table *sgt; -+ -+ /** -+ * @new_vma: The new VMA object that will be inserted to the VA tree. -+ */ -+ struct panthor_vma *new_vma; -+ } map; -+}; -+ -+/** -+ * struct panthor_vm - VM object -+ * -+ * A VM is an object representing a GPU (or MCU) virtual address space. -+ * It embeds the MMU page table for this address space, a tree containing -+ * all the virtual mappings of GEM objects, and other things needed to manage -+ * the VM. -+ * -+ * Except for the MCU VM, which is managed by the kernel, all other VMs are -+ * created by userspace and mostly managed by userspace, using the -+ * %DRM_IOCTL_PANTHOR_VM_BIND ioctl. -+ * -+ * A portion of the virtual address space is reserved for kernel objects, -+ * like heap chunks, and userspace gets to decide how much of the virtual -+ * address space is left to the kernel (half of the virtual address space -+ * by default). -+ */ -+struct panthor_vm { -+ /** -+ * @base: Inherit from drm_gpuvm. -+ * -+ * We delegate all the VA management to the common drm_gpuvm framework -+ * and only implement hooks to update the MMU page table. -+ */ -+ struct drm_gpuvm base; -+ -+ /** -+ * @sched: Scheduler used for asynchronous VM_BIND request. -+ * -+ * We use a 1:1 scheduler here. -+ */ -+ struct drm_gpu_scheduler sched; -+ -+ /** -+ * @entity: Scheduling entity representing the VM_BIND queue. -+ * -+ * There's currently one bind queue per VM. It doesn't make sense to -+ * allow more given the VM operations are serialized anyway. -+ */ -+ struct drm_sched_entity entity; -+ -+ /** @ptdev: Device. */ -+ struct panthor_device *ptdev; -+ -+ /** @memattr: Value to program to the AS_MEMATTR register. */ -+ u64 memattr; -+ -+ /** @pgtbl_ops: Page table operations. */ -+ struct io_pgtable_ops *pgtbl_ops; -+ -+ /** @root_page_table: Stores the root page table pointer. */ -+ void *root_page_table; -+ -+ /** -+ * @op_lock: Lock used to serialize operations on a VM. -+ * -+ * The serialization of jobs queued to the VM_BIND queue is already -+ * taken care of by drm_sched, but we need to serialize synchronous -+ * and asynchronous VM_BIND request. This is what this lock is for. -+ */ -+ struct mutex op_lock; -+ -+ /** -+ * @op_ctx: The context attached to the currently executing VM operation. -+ * -+ * NULL when no operation is in progress. -+ */ -+ struct panthor_vm_op_ctx *op_ctx; -+ -+ /** -+ * @mm: Memory management object representing the auto-VA/kernel-VA. -+ * -+ * Used to auto-allocate VA space for kernel-managed objects (tiler -+ * heaps, ...). -+ * -+ * For the MCU VM, this is managing the VA range that's used to map -+ * all shared interfaces. -+ * -+ * For user VMs, the range is specified by userspace, and must not -+ * exceed half of the VA space addressable. -+ */ -+ struct drm_mm mm; -+ -+ /** @mm_lock: Lock protecting the @mm field. */ -+ struct mutex mm_lock; -+ -+ /** @kernel_auto_va: Automatic VA-range for kernel BOs. */ -+ struct { -+ /** @start: Start of the automatic VA-range for kernel BOs. */ -+ u64 start; -+ -+ /** @size: Size of the automatic VA-range for kernel BOs. */ -+ u64 end; -+ } kernel_auto_va; -+ -+ /** @as: Address space related fields. */ -+ struct { -+ /** -+ * @id: ID of the address space this VM is bound to. -+ * -+ * A value of -1 means the VM is inactive/not bound. -+ */ -+ int id; -+ -+ /** @active_cnt: Number of active users of this VM. */ -+ refcount_t active_cnt; -+ -+ /** -+ * @lru_node: Used to instead the VM in the panthor_mmu::as::lru_list. -+ * -+ * Active VMs should not be inserted in the LRU list. -+ */ -+ struct list_head lru_node; -+ } as; -+ -+ /** -+ * @heaps: Tiler heap related fields. -+ */ -+ struct { -+ /** -+ * @pool: The heap pool attached to this VM. -+ * -+ * Will stay NULL until someone creates a heap context on this VM. -+ */ -+ struct panthor_heap_pool *pool; -+ -+ /** @lock: Lock used to protect access to @pool. */ -+ struct mutex lock; -+ } heaps; -+ -+ /** @node: Used to insert the VM in the panthor_mmu::vm::list. */ -+ struct list_head node; -+ -+ /** @for_mcu: True if this is the MCU VM. */ -+ bool for_mcu; -+ -+ /** -+ * @destroyed: True if the VM was destroyed. -+ * -+ * No further bind requests should be queued to a destroyed VM. -+ */ -+ bool destroyed; -+ -+ /** -+ * @unusable: True if the VM has turned unusable because something -+ * bad happened during an asynchronous request. -+ * -+ * We don't try to recover from such failures, because this implies -+ * informing userspace about the specific operation that failed, and -+ * hoping the userspace driver can replay things from there. This all -+ * sounds very complicated for little gain. -+ * -+ * Instead, we should just flag the VM as unusable, and fail any -+ * further request targeting this VM. -+ * -+ * We also provide a way to query a VM state, so userspace can destroy -+ * it and create a new one. -+ * -+ * As an analogy, this would be mapped to a VK_ERROR_DEVICE_LOST -+ * situation, where the logical device needs to be re-created. -+ */ -+ bool unusable; -+ -+ /** -+ * @unhandled_fault: Unhandled fault happened. -+ * -+ * This should be reported to the scheduler, and the queue/group be -+ * flagged as faulty as a result. -+ */ -+ bool unhandled_fault; -+}; -+ -+/** -+ * struct panthor_vm_bind_job - VM bind job -+ */ -+struct panthor_vm_bind_job { -+ /** @base: Inherit from drm_sched_job. */ -+ struct drm_sched_job base; -+ -+ /** @refcount: Reference count. */ -+ struct kref refcount; -+ -+ /** @cleanup_op_ctx_work: Work used to cleanup the VM operation context. */ -+ struct work_struct cleanup_op_ctx_work; -+ -+ /** @vm: VM targeted by the VM operation. */ -+ struct panthor_vm *vm; -+ -+ /** @ctx: Operation context. */ -+ struct panthor_vm_op_ctx ctx; -+}; -+ -+/** -+ * @pt_cache: Cache used to allocate MMU page tables. -+ * -+ * The pre-allocation pattern forces us to over-allocate to plan for -+ * the worst case scenario, and return the pages we didn't use. -+ * -+ * Having a kmem_cache allows us to speed allocations. -+ */ -+static struct kmem_cache *pt_cache; -+ -+/** -+ * alloc_pt() - Custom page table allocator -+ * @cookie: Cookie passed at page table allocation time. -+ * @size: Size of the page table. This size should be fixed, -+ * and determined at creation time based on the granule size. -+ * @gfp: GFP flags. -+ * -+ * We want a custom allocator so we can use a cache for page table -+ * allocations and amortize the cost of the over-reservation that's -+ * done to allow asynchronous VM operations. -+ * -+ * Return: non-NULL on success, NULL if the allocation failed for any -+ * reason. -+ */ -+static void *alloc_pt(void *cookie, size_t size, gfp_t gfp) -+{ -+ struct panthor_vm *vm = cookie; -+ void *page; -+ -+ /* Allocation of the root page table happening during init. */ -+ if (unlikely(!vm->root_page_table)) { -+ struct page *p; -+ -+ drm_WARN_ON(&vm->ptdev->base, vm->op_ctx); -+ p = alloc_pages_node(dev_to_node(vm->ptdev->base.dev), -+ gfp | __GFP_ZERO, get_order(size)); -+ page = p ? page_address(p) : NULL; -+ vm->root_page_table = page; -+ return page; -+ } -+ -+ /* We're not supposed to have anything bigger than 4k here, because we picked a -+ * 4k granule size at init time. -+ */ -+ if (drm_WARN_ON(&vm->ptdev->base, size != SZ_4K)) -+ return NULL; -+ -+ /* We must have some op_ctx attached to the VM and it must have at least one -+ * free page. -+ */ -+ if (drm_WARN_ON(&vm->ptdev->base, !vm->op_ctx) || -+ drm_WARN_ON(&vm->ptdev->base, -+ vm->op_ctx->rsvd_page_tables.ptr >= vm->op_ctx->rsvd_page_tables.count)) -+ return NULL; -+ -+ page = vm->op_ctx->rsvd_page_tables.pages[vm->op_ctx->rsvd_page_tables.ptr++]; -+ memset(page, 0, SZ_4K); -+ -+ /* Page table entries don't use virtual addresses, which trips out -+ * kmemleak. kmemleak_alloc_phys() might work, but physical addresses -+ * are mixed with other fields, and I fear kmemleak won't detect that -+ * either. -+ * -+ * Let's just ignore memory passed to the page-table driver for now. -+ */ -+ kmemleak_ignore(page); -+ return page; -+} -+ -+/** -+ * @free_pt() - Custom page table free function -+ * @cookie: Cookie passed at page table allocation time. -+ * @data: Page table to free. -+ * @size: Size of the page table. This size should be fixed, -+ * and determined at creation time based on the granule size. -+ */ -+static void free_pt(void *cookie, void *data, size_t size) -+{ -+ struct panthor_vm *vm = cookie; -+ -+ if (unlikely(vm->root_page_table == data)) { -+ free_pages((unsigned long)data, get_order(size)); -+ vm->root_page_table = NULL; -+ return; -+ } -+ -+ if (drm_WARN_ON(&vm->ptdev->base, size != SZ_4K)) -+ return; -+ -+ /* Return the page to the pt_cache. */ -+ kmem_cache_free(pt_cache, data); -+} -+ -+static int wait_ready(struct panthor_device *ptdev, u32 as_nr) -+{ -+ int ret; -+ u32 val; -+ -+ /* Wait for the MMU status to indicate there is no active command, in -+ * case one is pending. -+ */ -+ ret = readl_relaxed_poll_timeout_atomic(ptdev->iomem + AS_STATUS(as_nr), -+ val, !(val & AS_STATUS_AS_ACTIVE), -+ 10, 100000); -+ -+ if (ret) { -+ panthor_device_schedule_reset(ptdev); -+ drm_err(&ptdev->base, "AS_ACTIVE bit stuck\n"); -+ } -+ -+ return ret; -+} -+ -+static int write_cmd(struct panthor_device *ptdev, u32 as_nr, u32 cmd) -+{ -+ int status; -+ -+ /* write AS_COMMAND when MMU is ready to accept another command */ -+ status = wait_ready(ptdev, as_nr); -+ if (!status) -+ gpu_write(ptdev, AS_COMMAND(as_nr), cmd); -+ -+ return status; -+} -+ -+static void lock_region(struct panthor_device *ptdev, u32 as_nr, -+ u64 region_start, u64 size) -+{ -+ u8 region_width; -+ u64 region; -+ u64 region_end = region_start + size; -+ -+ if (!size) -+ return; -+ -+ /* -+ * The locked region is a naturally aligned power of 2 block encoded as -+ * log2 minus(1). -+ * Calculate the desired start/end and look for the highest bit which -+ * differs. The smallest naturally aligned block must include this bit -+ * change, the desired region starts with this bit (and subsequent bits) -+ * zeroed and ends with the bit (and subsequent bits) set to one. -+ */ -+ region_width = max(fls64(region_start ^ (region_end - 1)), -+ const_ilog2(AS_LOCK_REGION_MIN_SIZE)) - 1; -+ -+ /* -+ * Mask off the low bits of region_start (which would be ignored by -+ * the hardware anyway) -+ */ -+ region_start &= GENMASK_ULL(63, region_width); -+ -+ region = region_width | region_start; -+ -+ /* Lock the region that needs to be updated */ -+ gpu_write(ptdev, AS_LOCKADDR_LO(as_nr), lower_32_bits(region)); -+ gpu_write(ptdev, AS_LOCKADDR_HI(as_nr), upper_32_bits(region)); -+ write_cmd(ptdev, as_nr, AS_COMMAND_LOCK); -+} -+ -+static int mmu_hw_do_operation_locked(struct panthor_device *ptdev, int as_nr, -+ u64 iova, u64 size, u32 op) -+{ -+ lockdep_assert_held(&ptdev->mmu->as.slots_lock); -+ -+ if (as_nr < 0) -+ return 0; -+ -+ if (op != AS_COMMAND_UNLOCK) -+ lock_region(ptdev, as_nr, iova, size); -+ -+ /* Run the MMU operation */ -+ write_cmd(ptdev, as_nr, op); -+ -+ /* Wait for the flush to complete */ -+ return wait_ready(ptdev, as_nr); -+} -+ -+static int mmu_hw_do_operation(struct panthor_vm *vm, -+ u64 iova, u64 size, u32 op) -+{ -+ struct panthor_device *ptdev = vm->ptdev; -+ int ret; -+ -+ mutex_lock(&ptdev->mmu->as.slots_lock); -+ ret = mmu_hw_do_operation_locked(ptdev, vm->as.id, iova, size, op); -+ mutex_unlock(&ptdev->mmu->as.slots_lock); -+ -+ return ret; -+} -+ -+static int panthor_mmu_as_enable(struct panthor_device *ptdev, u32 as_nr, -+ u64 transtab, u64 transcfg, u64 memattr) -+{ -+ int ret; -+ -+ ret = mmu_hw_do_operation_locked(ptdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM); -+ if (ret) -+ return ret; -+ -+ gpu_write(ptdev, AS_TRANSTAB_LO(as_nr), lower_32_bits(transtab)); -+ gpu_write(ptdev, AS_TRANSTAB_HI(as_nr), upper_32_bits(transtab)); -+ -+ gpu_write(ptdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr)); -+ gpu_write(ptdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr)); -+ -+ gpu_write(ptdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg)); -+ gpu_write(ptdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg)); -+ -+ return write_cmd(ptdev, as_nr, AS_COMMAND_UPDATE); -+} -+ -+static int panthor_mmu_as_disable(struct panthor_device *ptdev, u32 as_nr) -+{ -+ int ret; -+ -+ ret = mmu_hw_do_operation_locked(ptdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM); -+ if (ret) -+ return ret; -+ -+ gpu_write(ptdev, AS_TRANSTAB_LO(as_nr), 0); -+ gpu_write(ptdev, AS_TRANSTAB_HI(as_nr), 0); -+ -+ gpu_write(ptdev, AS_MEMATTR_LO(as_nr), 0); -+ gpu_write(ptdev, AS_MEMATTR_HI(as_nr), 0); -+ -+ gpu_write(ptdev, AS_TRANSCFG_LO(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED); -+ gpu_write(ptdev, AS_TRANSCFG_HI(as_nr), 0); -+ -+ return write_cmd(ptdev, as_nr, AS_COMMAND_UPDATE); -+} -+ -+static u32 panthor_mmu_fault_mask(struct panthor_device *ptdev, u32 value) -+{ -+ /* Bits 16 to 31 mean REQ_COMPLETE. */ -+ return value & GENMASK(15, 0); -+} -+ -+static u32 panthor_mmu_as_fault_mask(struct panthor_device *ptdev, u32 as) -+{ -+ return BIT(as); -+} -+ -+/** -+ * panthor_vm_has_unhandled_faults() - Check if a VM has unhandled faults -+ * @vm: VM to check. -+ * -+ * Return: true if the VM has unhandled faults, false otherwise. -+ */ -+bool panthor_vm_has_unhandled_faults(struct panthor_vm *vm) -+{ -+ return vm->unhandled_fault; -+} -+ -+/** -+ * panthor_vm_is_unusable() - Check if the VM is still usable -+ * @vm: VM to check. -+ * -+ * Return: true if the VM is unusable, false otherwise. -+ */ -+bool panthor_vm_is_unusable(struct panthor_vm *vm) -+{ -+ return vm->unusable; -+} -+ -+static void panthor_vm_release_as_locked(struct panthor_vm *vm) -+{ -+ struct panthor_device *ptdev = vm->ptdev; -+ -+ lockdep_assert_held(&ptdev->mmu->as.slots_lock); -+ -+ if (drm_WARN_ON(&ptdev->base, vm->as.id < 0)) -+ return; -+ -+ ptdev->mmu->as.slots[vm->as.id].vm = NULL; -+ clear_bit(vm->as.id, &ptdev->mmu->as.alloc_mask); -+ refcount_set(&vm->as.active_cnt, 0); -+ list_del_init(&vm->as.lru_node); -+ vm->as.id = -1; -+} -+ -+/** -+ * panthor_vm_active() - Flag a VM as active -+ * @VM: VM to flag as active. -+ * -+ * Assigns an address space to a VM so it can be used by the GPU/MCU. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_vm_active(struct panthor_vm *vm) -+{ -+ struct panthor_device *ptdev = vm->ptdev; -+ u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features); -+ struct io_pgtable_cfg *cfg = &io_pgtable_ops_to_pgtable(vm->pgtbl_ops)->cfg; -+ int ret = 0, as, cookie; -+ u64 transtab, transcfg; -+ -+ if (!drm_dev_enter(&ptdev->base, &cookie)) -+ return -ENODEV; -+ -+ if (refcount_inc_not_zero(&vm->as.active_cnt)) -+ goto out_dev_exit; -+ -+ mutex_lock(&ptdev->mmu->as.slots_lock); -+ -+ if (refcount_inc_not_zero(&vm->as.active_cnt)) -+ goto out_unlock; -+ -+ as = vm->as.id; -+ if (as >= 0) { -+ /* Unhandled pagefault on this AS, the MMU was disabled. We need to -+ * re-enable the MMU after clearing+unmasking the AS interrupts. -+ */ -+ if (ptdev->mmu->as.faulty_mask & panthor_mmu_as_fault_mask(ptdev, as)) -+ goto out_enable_as; -+ -+ goto out_make_active; -+ } -+ -+ /* Check for a free AS */ -+ if (vm->for_mcu) { -+ drm_WARN_ON(&ptdev->base, ptdev->mmu->as.alloc_mask & BIT(0)); -+ as = 0; -+ } else { -+ as = ffz(ptdev->mmu->as.alloc_mask | BIT(0)); -+ } -+ -+ if (!(BIT(as) & ptdev->gpu_info.as_present)) { -+ struct panthor_vm *lru_vm; -+ -+ lru_vm = list_first_entry_or_null(&ptdev->mmu->as.lru_list, -+ struct panthor_vm, -+ as.lru_node); -+ if (drm_WARN_ON(&ptdev->base, !lru_vm)) { -+ ret = -EBUSY; -+ goto out_unlock; -+ } -+ -+ drm_WARN_ON(&ptdev->base, refcount_read(&lru_vm->as.active_cnt)); -+ as = lru_vm->as.id; -+ panthor_vm_release_as_locked(lru_vm); -+ } -+ -+ /* Assign the free or reclaimed AS to the FD */ -+ vm->as.id = as; -+ set_bit(as, &ptdev->mmu->as.alloc_mask); -+ ptdev->mmu->as.slots[as].vm = vm; -+ -+out_enable_as: -+ transtab = cfg->arm_lpae_s1_cfg.ttbr; -+ transcfg = AS_TRANSCFG_PTW_MEMATTR_WB | -+ AS_TRANSCFG_PTW_RA | -+ AS_TRANSCFG_ADRMODE_AARCH64_4K | -+ AS_TRANSCFG_INA_BITS(55 - va_bits); -+ if (ptdev->coherent) -+ transcfg |= AS_TRANSCFG_PTW_SH_OS; -+ -+ /* If the VM is re-activated, we clear the fault. */ -+ vm->unhandled_fault = false; -+ -+ /* Unhandled pagefault on this AS, clear the fault and re-enable interrupts -+ * before enabling the AS. -+ */ -+ if (ptdev->mmu->as.faulty_mask & panthor_mmu_as_fault_mask(ptdev, as)) { -+ gpu_write(ptdev, MMU_INT_CLEAR, panthor_mmu_as_fault_mask(ptdev, as)); -+ ptdev->mmu->as.faulty_mask &= ~panthor_mmu_as_fault_mask(ptdev, as); -+ gpu_write(ptdev, MMU_INT_MASK, ~ptdev->mmu->as.faulty_mask); -+ } -+ -+ ret = panthor_mmu_as_enable(vm->ptdev, vm->as.id, transtab, transcfg, vm->memattr); -+ -+out_make_active: -+ if (!ret) { -+ refcount_set(&vm->as.active_cnt, 1); -+ list_del_init(&vm->as.lru_node); -+ } -+ -+out_unlock: -+ mutex_unlock(&ptdev->mmu->as.slots_lock); -+ -+out_dev_exit: -+ drm_dev_exit(cookie); -+ return ret; -+} -+ -+/** -+ * panthor_vm_idle() - Flag a VM idle -+ * @VM: VM to flag as idle. -+ * -+ * When we know the GPU is done with the VM (no more jobs to process), -+ * we can relinquish the AS slot attached to this VM, if any. -+ * -+ * We don't release the slot immediately, but instead place the VM in -+ * the LRU list, so it can be evicted if another VM needs an AS slot. -+ * This way, VMs keep attached to the AS they were given until we run -+ * out of free slot, limiting the number of MMU operations (TLB flush -+ * and other AS updates). -+ */ -+void panthor_vm_idle(struct panthor_vm *vm) -+{ -+ struct panthor_device *ptdev = vm->ptdev; -+ -+ if (!refcount_dec_and_mutex_lock(&vm->as.active_cnt, &ptdev->mmu->as.slots_lock)) -+ return; -+ -+ if (!drm_WARN_ON(&ptdev->base, vm->as.id == -1 || !list_empty(&vm->as.lru_node))) -+ list_add_tail(&vm->as.lru_node, &ptdev->mmu->as.lru_list); -+ -+ refcount_set(&vm->as.active_cnt, 0); -+ mutex_unlock(&ptdev->mmu->as.slots_lock); -+} -+ -+static void panthor_vm_stop(struct panthor_vm *vm) -+{ -+ drm_sched_stop(&vm->sched, NULL); -+} -+ -+static void panthor_vm_start(struct panthor_vm *vm) -+{ -+ drm_sched_start(&vm->sched, true); -+} -+ -+/** -+ * panthor_vm_as() - Get the AS slot attached to a VM -+ * @vm: VM to get the AS slot of. -+ * -+ * Return: -1 if the VM is not assigned an AS slot yet, >= 0 otherwise. -+ */ -+int panthor_vm_as(struct panthor_vm *vm) -+{ -+ return vm->as.id; -+} -+ -+static size_t get_pgsize(u64 addr, size_t size, size_t *count) -+{ -+ /* -+ * io-pgtable only operates on multiple pages within a single table -+ * entry, so we need to split at boundaries of the table size, i.e. -+ * the next block size up. The distance from address A to the next -+ * boundary of block size B is logically B - A % B, but in unsigned -+ * two's complement where B is a power of two we get the equivalence -+ * B - A % B == (B - A) % B == (n * B - A) % B, and choose n = 0 :) -+ */ -+ size_t blk_offset = -addr % SZ_2M; -+ -+ if (blk_offset || size < SZ_2M) { -+ *count = min_not_zero(blk_offset, size) / SZ_4K; -+ return SZ_4K; -+ } -+ blk_offset = -addr % SZ_1G ?: SZ_1G; -+ *count = min(blk_offset, size) / SZ_2M; -+ return SZ_2M; -+} -+ -+static int panthor_vm_flush_range(struct panthor_vm *vm, u64 iova, u64 size) -+{ -+ struct panthor_device *ptdev = vm->ptdev; -+ int ret = 0, cookie; -+ -+ if (vm->as.id < 0) -+ return 0; -+ -+ /* If the device is unplugged, we just silently skip the flush. */ -+ if (!drm_dev_enter(&ptdev->base, &cookie)) -+ return 0; -+ -+ /* Flush the PTs only if we're already awake */ -+ if (pm_runtime_active(ptdev->base.dev)) -+ ret = mmu_hw_do_operation(vm, iova, size, AS_COMMAND_FLUSH_PT); -+ -+ drm_dev_exit(cookie); -+ return ret; -+} -+ -+static int panthor_vm_unmap_pages(struct panthor_vm *vm, u64 iova, u64 size) -+{ -+ struct panthor_device *ptdev = vm->ptdev; -+ struct io_pgtable_ops *ops = vm->pgtbl_ops; -+ u64 offset = 0; -+ -+ drm_dbg(&ptdev->base, "unmap: as=%d, iova=%llx, len=%llx", vm->as.id, iova, size); -+ -+ while (offset < size) { -+ size_t unmapped_sz = 0, pgcount; -+ size_t pgsize = get_pgsize(iova + offset, size - offset, &pgcount); -+ -+ unmapped_sz = ops->unmap_pages(ops, iova + offset, pgsize, pgcount, NULL); -+ -+ if (drm_WARN_ON(&ptdev->base, unmapped_sz != pgsize * pgcount)) { -+ drm_err(&ptdev->base, "failed to unmap range %llx-%llx (requested range %llx-%llx)\n", -+ iova + offset + unmapped_sz, -+ iova + offset + pgsize * pgcount, -+ iova, iova + size); -+ panthor_vm_flush_range(vm, iova, offset + unmapped_sz); -+ return -EINVAL; -+ } -+ offset += unmapped_sz; -+ } -+ -+ return panthor_vm_flush_range(vm, iova, size); -+} -+ -+static int -+panthor_vm_map_pages(struct panthor_vm *vm, u64 iova, int prot, -+ struct sg_table *sgt, u64 offset, u64 size) -+{ -+ struct panthor_device *ptdev = vm->ptdev; -+ unsigned int count; -+ struct scatterlist *sgl; -+ struct io_pgtable_ops *ops = vm->pgtbl_ops; -+ u64 start_iova = iova; -+ int ret; -+ -+ if (!size) -+ return 0; -+ -+ for_each_sgtable_dma_sg(sgt, sgl, count) { -+ dma_addr_t paddr = sg_dma_address(sgl); -+ size_t len = sg_dma_len(sgl); -+ -+ if (len <= offset) { -+ offset -= len; -+ continue; -+ } -+ -+ paddr += offset; -+ len -= offset; -+ len = min_t(size_t, len, size); -+ size -= len; -+ -+ drm_dbg(&ptdev->base, "map: as=%d, iova=%llx, paddr=%pad, len=%zx", -+ vm->as.id, iova, &paddr, len); -+ -+ while (len) { -+ size_t pgcount, mapped = 0; -+ size_t pgsize = get_pgsize(iova | paddr, len, &pgcount); -+ -+ ret = ops->map_pages(ops, iova, paddr, pgsize, pgcount, prot, -+ GFP_KERNEL, &mapped); -+ iova += mapped; -+ paddr += mapped; -+ len -= mapped; -+ -+ if (drm_WARN_ON(&ptdev->base, !ret && !mapped)) -+ ret = -ENOMEM; -+ -+ if (ret) { -+ /* If something failed, unmap what we've already mapped before -+ * returning. The unmap call is not supposed to fail. -+ */ -+ drm_WARN_ON(&ptdev->base, -+ panthor_vm_unmap_pages(vm, start_iova, -+ iova - start_iova)); -+ return ret; -+ } -+ } -+ -+ if (!size) -+ break; -+ } -+ -+ return panthor_vm_flush_range(vm, start_iova, iova - start_iova); -+} -+ -+static int flags_to_prot(u32 flags) -+{ -+ int prot = 0; -+ -+ if (flags & DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC) -+ prot |= IOMMU_NOEXEC; -+ -+ if (!(flags & DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED)) -+ prot |= IOMMU_CACHE; -+ -+ if (flags & DRM_PANTHOR_VM_BIND_OP_MAP_READONLY) -+ prot |= IOMMU_READ; -+ else -+ prot |= IOMMU_READ | IOMMU_WRITE; -+ -+ return prot; -+} -+ -+/** -+ * panthor_vm_alloc_va() - Allocate a region in the auto-va space -+ * @VM: VM to allocate a region on. -+ * @va: start of the VA range. Can be PANTHOR_VM_KERNEL_AUTO_VA if the user -+ * wants the VA to be automatically allocated from the auto-VA range. -+ * @size: size of the VA range. -+ * @va_node: drm_mm_node to initialize. Must be zero-initialized. -+ * -+ * Some GPU objects, like heap chunks, are fully managed by the kernel and -+ * need to be mapped to the userspace VM, in the region reserved for kernel -+ * objects. -+ * -+ * This function takes care of allocating a region in the kernel auto-VA space. -+ * -+ * Return: 0 on success, an error code otherwise. -+ */ -+int -+panthor_vm_alloc_va(struct panthor_vm *vm, u64 va, u64 size, -+ struct drm_mm_node *va_node) -+{ -+ int ret; -+ -+ if (!size || (size & ~PAGE_MASK)) -+ return -EINVAL; -+ -+ if (va != PANTHOR_VM_KERNEL_AUTO_VA && (va & ~PAGE_MASK)) -+ return -EINVAL; -+ -+ mutex_lock(&vm->mm_lock); -+ if (va != PANTHOR_VM_KERNEL_AUTO_VA) { -+ va_node->start = va; -+ va_node->size = size; -+ ret = drm_mm_reserve_node(&vm->mm, va_node); -+ } else { -+ ret = drm_mm_insert_node_in_range(&vm->mm, va_node, size, -+ size >= SZ_2M ? SZ_2M : SZ_4K, -+ 0, vm->kernel_auto_va.start, -+ vm->kernel_auto_va.end, -+ DRM_MM_INSERT_BEST); -+ } -+ mutex_unlock(&vm->mm_lock); -+ -+ return ret; -+} -+ -+/** -+ * panthor_vm_free_va() - Free a region allocated with panthor_vm_alloc_va() -+ * @VM: VM to free the region on. -+ * @va_node: Memory node representing the region to free. -+ */ -+void panthor_vm_free_va(struct panthor_vm *vm, struct drm_mm_node *va_node) -+{ -+ mutex_lock(&vm->mm_lock); -+ drm_mm_remove_node(va_node); -+ mutex_unlock(&vm->mm_lock); -+} -+ -+static void panthor_vm_bo_put(struct drm_gpuvm_bo *vm_bo) -+{ -+ struct panthor_gem_object *bo = to_panthor_bo(vm_bo->obj); -+ struct drm_gpuvm *vm = vm_bo->vm; -+ bool unpin; -+ -+ /* We must retain the GEM before calling drm_gpuvm_bo_put(), -+ * otherwise the mutex might be destroyed while we hold it. -+ * Same goes for the VM, since we take the VM resv lock. -+ */ -+ drm_gem_object_get(&bo->base.base); -+ drm_gpuvm_get(vm); -+ -+ /* We take the resv lock to protect against concurrent accesses to the -+ * gpuvm evicted/extobj lists that are modified in -+ * drm_gpuvm_bo_destroy(), which is called if drm_gpuvm_bo_put() -+ * releases sthe last vm_bo reference. -+ * We take the BO GPUVA list lock to protect the vm_bo removal from the -+ * GEM vm_bo list. -+ */ -+ dma_resv_lock(drm_gpuvm_resv(vm), NULL); -+ mutex_lock(&bo->gpuva_list_lock); -+ unpin = drm_gpuvm_bo_put(vm_bo); -+ mutex_unlock(&bo->gpuva_list_lock); -+ dma_resv_unlock(drm_gpuvm_resv(vm)); -+ -+ /* If the vm_bo object was destroyed, release the pin reference that -+ * was hold by this object. -+ */ -+ if (unpin && !bo->base.base.import_attach) -+ drm_gem_shmem_unpin(&bo->base); -+ -+ drm_gpuvm_put(vm); -+ drm_gem_object_put(&bo->base.base); -+} -+ -+static void panthor_vm_cleanup_op_ctx(struct panthor_vm_op_ctx *op_ctx, -+ struct panthor_vm *vm) -+{ -+ struct panthor_vma *vma, *tmp_vma; -+ -+ u32 remaining_pt_count = op_ctx->rsvd_page_tables.count - -+ op_ctx->rsvd_page_tables.ptr; -+ -+ if (remaining_pt_count) { -+ kmem_cache_free_bulk(pt_cache, remaining_pt_count, -+ op_ctx->rsvd_page_tables.pages + -+ op_ctx->rsvd_page_tables.ptr); -+ } -+ -+ kfree(op_ctx->rsvd_page_tables.pages); -+ -+ if (op_ctx->map.vm_bo) -+ panthor_vm_bo_put(op_ctx->map.vm_bo); -+ -+ for (u32 i = 0; i < ARRAY_SIZE(op_ctx->preallocated_vmas); i++) -+ kfree(op_ctx->preallocated_vmas[i]); -+ -+ list_for_each_entry_safe(vma, tmp_vma, &op_ctx->returned_vmas, node) { -+ list_del(&vma->node); -+ panthor_vm_bo_put(vma->base.vm_bo); -+ kfree(vma); -+ } -+} -+ -+static struct panthor_vma * -+panthor_vm_op_ctx_get_vma(struct panthor_vm_op_ctx *op_ctx) -+{ -+ for (u32 i = 0; i < ARRAY_SIZE(op_ctx->preallocated_vmas); i++) { -+ struct panthor_vma *vma = op_ctx->preallocated_vmas[i]; -+ -+ if (vma) { -+ op_ctx->preallocated_vmas[i] = NULL; -+ return vma; -+ } -+ } -+ -+ return NULL; -+} -+ -+static int -+panthor_vm_op_ctx_prealloc_vmas(struct panthor_vm_op_ctx *op_ctx) -+{ -+ u32 vma_count; -+ -+ switch (op_ctx->flags & DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) { -+ case DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: -+ /* One VMA for the new mapping, and two more VMAs for the remap case -+ * which might contain both a prev and next VA. -+ */ -+ vma_count = 3; -+ break; -+ -+ case DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP: -+ /* Partial unmaps might trigger a remap with either a prev or a next VA, -+ * but not both. -+ */ -+ vma_count = 1; -+ break; -+ -+ default: -+ return 0; -+ } -+ -+ for (u32 i = 0; i < vma_count; i++) { -+ struct panthor_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL); -+ -+ if (!vma) -+ return -ENOMEM; -+ -+ op_ctx->preallocated_vmas[i] = vma; -+ } -+ -+ return 0; -+} -+ -+#define PANTHOR_VM_BIND_OP_MAP_FLAGS \ -+ (DRM_PANTHOR_VM_BIND_OP_MAP_READONLY | \ -+ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | \ -+ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED | \ -+ DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) -+ -+static int panthor_vm_prepare_map_op_ctx(struct panthor_vm_op_ctx *op_ctx, -+ struct panthor_vm *vm, -+ struct panthor_gem_object *bo, -+ u64 offset, -+ u64 size, u64 va, -+ u32 flags) -+{ -+ struct drm_gpuvm_bo *preallocated_vm_bo; -+ struct sg_table *sgt = NULL; -+ u64 pt_count; -+ int ret; -+ -+ if (!bo) -+ return -EINVAL; -+ -+ if ((flags & ~PANTHOR_VM_BIND_OP_MAP_FLAGS) || -+ (flags & DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) != DRM_PANTHOR_VM_BIND_OP_TYPE_MAP) -+ return -EINVAL; -+ -+ /* Make sure the VA and size are aligned and in-bounds. */ -+ if (size > bo->base.base.size || offset > bo->base.base.size - size) -+ return -EINVAL; -+ -+ /* If the BO has an exclusive VM attached, it can't be mapped to other VMs. */ -+ if (bo->exclusive_vm_root_gem && -+ bo->exclusive_vm_root_gem != panthor_vm_root_gem(vm)) -+ return -EINVAL; -+ -+ memset(op_ctx, 0, sizeof(*op_ctx)); -+ INIT_LIST_HEAD(&op_ctx->returned_vmas); -+ op_ctx->flags = flags; -+ op_ctx->va.range = size; -+ op_ctx->va.addr = va; -+ -+ ret = panthor_vm_op_ctx_prealloc_vmas(op_ctx); -+ if (ret) -+ goto err_cleanup; -+ -+ if (!bo->base.base.import_attach) { -+ /* Pre-reserve the BO pages, so the map operation doesn't have to -+ * allocate. -+ */ -+ ret = drm_gem_shmem_pin(&bo->base); -+ if (ret) -+ goto err_cleanup; -+ } -+ -+ sgt = drm_gem_shmem_get_pages_sgt(&bo->base); -+ if (IS_ERR(sgt)) { -+ if (!bo->base.base.import_attach) -+ drm_gem_shmem_unpin(&bo->base); -+ -+ ret = PTR_ERR(sgt); -+ goto err_cleanup; -+ } -+ -+ op_ctx->map.sgt = sgt; -+ -+ preallocated_vm_bo = drm_gpuvm_bo_create(&vm->base, &bo->base.base); -+ if (!preallocated_vm_bo) { -+ if (!bo->base.base.import_attach) -+ drm_gem_shmem_unpin(&bo->base); -+ -+ ret = -ENOMEM; -+ goto err_cleanup; -+ } -+ -+ mutex_lock(&bo->gpuva_list_lock); -+ op_ctx->map.vm_bo = drm_gpuvm_bo_obtain_prealloc(preallocated_vm_bo); -+ mutex_unlock(&bo->gpuva_list_lock); -+ -+ /* If the a vm_bo for this combination exists, it already -+ * retains a pin ref, and we can release the one we took earlier. -+ * -+ * If our pre-allocated vm_bo is picked, it now retains the pin ref, -+ * which will be released in panthor_vm_bo_put(). -+ */ -+ if (preallocated_vm_bo != op_ctx->map.vm_bo && -+ !bo->base.base.import_attach) -+ drm_gem_shmem_unpin(&bo->base); -+ -+ op_ctx->map.bo_offset = offset; -+ -+ /* L1, L2 and L3 page tables. -+ * We could optimize L3 allocation by iterating over the sgt and merging -+ * 2M contiguous blocks, but it's simpler to over-provision and return -+ * the pages if they're not used. -+ */ -+ pt_count = ((ALIGN(va + size, 1ull << 39) - ALIGN_DOWN(va, 1ull << 39)) >> 39) + -+ ((ALIGN(va + size, 1ull << 30) - ALIGN_DOWN(va, 1ull << 30)) >> 30) + -+ ((ALIGN(va + size, 1ull << 21) - ALIGN_DOWN(va, 1ull << 21)) >> 21); -+ -+ op_ctx->rsvd_page_tables.pages = kcalloc(pt_count, -+ sizeof(*op_ctx->rsvd_page_tables.pages), -+ GFP_KERNEL); -+ if (!op_ctx->rsvd_page_tables.pages) -+ goto err_cleanup; -+ -+ ret = kmem_cache_alloc_bulk(pt_cache, GFP_KERNEL, pt_count, -+ op_ctx->rsvd_page_tables.pages); -+ op_ctx->rsvd_page_tables.count = ret; -+ if (ret != pt_count) { -+ ret = -ENOMEM; -+ goto err_cleanup; -+ } -+ -+ /* Insert BO into the extobj list last, when we know nothing can fail. */ -+ dma_resv_lock(panthor_vm_resv(vm), NULL); -+ drm_gpuvm_bo_extobj_add(op_ctx->map.vm_bo); -+ dma_resv_unlock(panthor_vm_resv(vm)); -+ -+ return 0; -+ -+err_cleanup: -+ panthor_vm_cleanup_op_ctx(op_ctx, vm); -+ return ret; -+} -+ -+static int panthor_vm_prepare_unmap_op_ctx(struct panthor_vm_op_ctx *op_ctx, -+ struct panthor_vm *vm, -+ u64 va, u64 size) -+{ -+ u32 pt_count = 0; -+ int ret; -+ -+ memset(op_ctx, 0, sizeof(*op_ctx)); -+ INIT_LIST_HEAD(&op_ctx->returned_vmas); -+ op_ctx->va.range = size; -+ op_ctx->va.addr = va; -+ op_ctx->flags = DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP; -+ -+ /* Pre-allocate L3 page tables to account for the split-2M-block -+ * situation on unmap. -+ */ -+ if (va != ALIGN(va, SZ_2M)) -+ pt_count++; -+ -+ if (va + size != ALIGN(va + size, SZ_2M) && -+ ALIGN(va + size, SZ_2M) != ALIGN(va, SZ_2M)) -+ pt_count++; -+ -+ ret = panthor_vm_op_ctx_prealloc_vmas(op_ctx); -+ if (ret) -+ goto err_cleanup; -+ -+ if (pt_count) { -+ op_ctx->rsvd_page_tables.pages = kcalloc(pt_count, -+ sizeof(*op_ctx->rsvd_page_tables.pages), -+ GFP_KERNEL); -+ if (!op_ctx->rsvd_page_tables.pages) -+ goto err_cleanup; -+ -+ ret = kmem_cache_alloc_bulk(pt_cache, GFP_KERNEL, pt_count, -+ op_ctx->rsvd_page_tables.pages); -+ if (ret != pt_count) { -+ ret = -ENOMEM; -+ goto err_cleanup; -+ } -+ op_ctx->rsvd_page_tables.count = pt_count; -+ } -+ -+ return 0; -+ -+err_cleanup: -+ panthor_vm_cleanup_op_ctx(op_ctx, vm); -+ return ret; -+} -+ -+static void panthor_vm_prepare_sync_only_op_ctx(struct panthor_vm_op_ctx *op_ctx, -+ struct panthor_vm *vm) -+{ -+ memset(op_ctx, 0, sizeof(*op_ctx)); -+ INIT_LIST_HEAD(&op_ctx->returned_vmas); -+ op_ctx->flags = DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY; -+} -+ -+/** -+ * panthor_vm_get_bo_for_va() - Get the GEM object mapped at a virtual address -+ * @vm: VM to look into. -+ * @va: Virtual address to search for. -+ * @bo_offset: Offset of the GEM object mapped at this virtual address. -+ * Only valid on success. -+ * -+ * The object returned by this function might no longer be mapped when the -+ * function returns. It's the caller responsibility to ensure there's no -+ * concurrent map/unmap operations making the returned value invalid, or -+ * make sure it doesn't matter if the object is no longer mapped. -+ * -+ * Return: A valid pointer on success, an ERR_PTR() otherwise. -+ */ -+struct panthor_gem_object * -+panthor_vm_get_bo_for_va(struct panthor_vm *vm, u64 va, u64 *bo_offset) -+{ -+ struct panthor_gem_object *bo = ERR_PTR(-ENOENT); -+ struct drm_gpuva *gpuva; -+ struct panthor_vma *vma; -+ -+ /* Take the VM lock to prevent concurrent map/unmap operations. */ -+ mutex_lock(&vm->op_lock); -+ gpuva = drm_gpuva_find_first(&vm->base, va, 1); -+ vma = gpuva ? container_of(gpuva, struct panthor_vma, base) : NULL; -+ if (vma && vma->base.gem.obj) { -+ drm_gem_object_get(vma->base.gem.obj); -+ bo = to_panthor_bo(vma->base.gem.obj); -+ *bo_offset = vma->base.gem.offset + (va - vma->base.va.addr); -+ } -+ mutex_unlock(&vm->op_lock); -+ -+ return bo; -+} -+ -+#define PANTHOR_VM_MIN_KERNEL_VA_SIZE SZ_256M -+ -+static u64 -+panthor_vm_create_get_user_va_range(const struct drm_panthor_vm_create *args, -+ u64 full_va_range) -+{ -+ u64 user_va_range; -+ -+ /* Make sure we have a minimum amount of VA space for kernel objects. */ -+ if (full_va_range < PANTHOR_VM_MIN_KERNEL_VA_SIZE) -+ return 0; -+ -+ if (args->user_va_range) { -+ /* Use the user provided value if != 0. */ -+ user_va_range = args->user_va_range; -+ } else if (TASK_SIZE_OF(current) < full_va_range) { -+ /* If the task VM size is smaller than the GPU VA range, pick this -+ * as our default user VA range, so userspace can CPU/GPU map buffers -+ * at the same address. -+ */ -+ user_va_range = TASK_SIZE_OF(current); -+ } else { -+ /* If the GPU VA range is smaller than the task VM size, we -+ * just have to live with the fact we won't be able to map -+ * all buffers at the same GPU/CPU address. -+ * -+ * If the GPU VA range is bigger than 4G (more than 32-bit of -+ * VA), we split the range in two, and assign half of it to -+ * the user and the other half to the kernel, if it's not, we -+ * keep the kernel VA space as small as possible. -+ */ -+ user_va_range = full_va_range > SZ_4G ? -+ full_va_range / 2 : -+ full_va_range - PANTHOR_VM_MIN_KERNEL_VA_SIZE; -+ } -+ -+ if (full_va_range - PANTHOR_VM_MIN_KERNEL_VA_SIZE < user_va_range) -+ user_va_range = full_va_range - PANTHOR_VM_MIN_KERNEL_VA_SIZE; -+ -+ return user_va_range; -+} -+ -+#define PANTHOR_VM_CREATE_FLAGS 0 -+ -+static int -+panthor_vm_create_check_args(const struct panthor_device *ptdev, -+ const struct drm_panthor_vm_create *args, -+ u64 *kernel_va_start, u64 *kernel_va_range) -+{ -+ u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features); -+ u64 full_va_range = 1ull << va_bits; -+ u64 user_va_range; -+ -+ if (args->flags & ~PANTHOR_VM_CREATE_FLAGS) -+ return -EINVAL; -+ -+ user_va_range = panthor_vm_create_get_user_va_range(args, full_va_range); -+ if (!user_va_range || (args->user_va_range && args->user_va_range > user_va_range)) -+ return -EINVAL; -+ -+ /* Pick a kernel VA range that's a power of two, to have a clear split. */ -+ *kernel_va_range = rounddown_pow_of_two(full_va_range - user_va_range); -+ *kernel_va_start = full_va_range - *kernel_va_range; -+ return 0; -+} -+ -+/* -+ * Only 32 VMs per open file. If that becomes a limiting factor, we can -+ * increase this number. -+ */ -+#define PANTHOR_MAX_VMS_PER_FILE 32 -+ -+/** -+ * panthor_vm_pool_create_vm() - Create a VM -+ * @pool: The VM to create this VM on. -+ * @kernel_va_start: Start of the region reserved for kernel objects. -+ * @kernel_va_range: Size of the region reserved for kernel objects. -+ * -+ * Return: a positive VM ID on success, a negative error code otherwise. -+ */ -+int panthor_vm_pool_create_vm(struct panthor_device *ptdev, -+ struct panthor_vm_pool *pool, -+ struct drm_panthor_vm_create *args) -+{ -+ u64 kernel_va_start, kernel_va_range; -+ struct panthor_vm *vm; -+ int ret; -+ u32 id; -+ -+ ret = panthor_vm_create_check_args(ptdev, args, &kernel_va_start, &kernel_va_range); -+ if (ret) -+ return ret; -+ -+ vm = panthor_vm_create(ptdev, false, kernel_va_start, kernel_va_range, -+ kernel_va_start, kernel_va_range); -+ if (IS_ERR(vm)) -+ return PTR_ERR(vm); -+ -+ ret = xa_alloc(&pool->xa, &id, vm, -+ XA_LIMIT(1, PANTHOR_MAX_VMS_PER_FILE), GFP_KERNEL); -+ -+ if (ret) { -+ panthor_vm_put(vm); -+ return ret; -+ } -+ -+ args->user_va_range = kernel_va_start; -+ return id; -+} -+ -+static void panthor_vm_destroy(struct panthor_vm *vm) -+{ -+ if (!vm) -+ return; -+ -+ vm->destroyed = true; -+ -+ mutex_lock(&vm->heaps.lock); -+ panthor_heap_pool_destroy(vm->heaps.pool); -+ vm->heaps.pool = NULL; -+ mutex_unlock(&vm->heaps.lock); -+ -+ drm_WARN_ON(&vm->ptdev->base, -+ panthor_vm_unmap_range(vm, vm->base.mm_start, vm->base.mm_range)); -+ panthor_vm_put(vm); -+} -+ -+/** -+ * panthor_vm_pool_destroy_vm() - Destroy a VM. -+ * @pool: VM pool. -+ * @handle: VM handle. -+ * -+ * This function doesn't free the VM object or its resources, it just kills -+ * all mappings, and makes sure nothing can be mapped after that point. -+ * -+ * If there was any active jobs at the time this function is called, these -+ * jobs should experience page faults and be killed as a result. -+ * -+ * The VM resources are freed when the last reference on the VM object is -+ * dropped. -+ */ -+int panthor_vm_pool_destroy_vm(struct panthor_vm_pool *pool, u32 handle) -+{ -+ struct panthor_vm *vm; -+ -+ vm = xa_erase(&pool->xa, handle); -+ -+ panthor_vm_destroy(vm); -+ -+ return vm ? 0 : -EINVAL; -+} -+ -+/** -+ * panthor_vm_pool_get_vm() - Retrieve VM object bound to a VM handle -+ * @pool: VM pool to check. -+ * @handle: Handle of the VM to retrieve. -+ * -+ * Return: A valid pointer if the VM exists, NULL otherwise. -+ */ -+struct panthor_vm * -+panthor_vm_pool_get_vm(struct panthor_vm_pool *pool, u32 handle) -+{ -+ struct panthor_vm *vm; -+ -+ vm = panthor_vm_get(xa_load(&pool->xa, handle)); -+ -+ return vm; -+} -+ -+/** -+ * panthor_vm_pool_destroy() - Destroy a VM pool. -+ * @pfile: File. -+ * -+ * Destroy all VMs in the pool, and release the pool resources. -+ * -+ * Note that VMs can outlive the pool they were created from if other -+ * objects hold a reference to there VMs. -+ */ -+void panthor_vm_pool_destroy(struct panthor_file *pfile) -+{ -+ struct panthor_vm *vm; -+ unsigned long i; -+ -+ if (!pfile->vms) -+ return; -+ -+ xa_for_each(&pfile->vms->xa, i, vm) -+ panthor_vm_destroy(vm); -+ -+ xa_destroy(&pfile->vms->xa); -+ kfree(pfile->vms); -+} -+ -+/** -+ * panthor_vm_pool_create() - Create a VM pool -+ * @pfile: File. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_vm_pool_create(struct panthor_file *pfile) -+{ -+ pfile->vms = kzalloc(sizeof(*pfile->vms), GFP_KERNEL); -+ if (!pfile->vms) -+ return -ENOMEM; -+ -+ xa_init_flags(&pfile->vms->xa, XA_FLAGS_ALLOC1); -+ return 0; -+} -+ -+/* dummy TLB ops, the real TLB flush happens in panthor_vm_flush_range() */ -+static void mmu_tlb_flush_all(void *cookie) -+{ -+} -+ -+static void mmu_tlb_flush_walk(unsigned long iova, size_t size, size_t granule, void *cookie) -+{ -+} -+ -+static const struct iommu_flush_ops mmu_tlb_ops = { -+ .tlb_flush_all = mmu_tlb_flush_all, -+ .tlb_flush_walk = mmu_tlb_flush_walk, -+}; -+ -+static const char *access_type_name(struct panthor_device *ptdev, -+ u32 fault_status) -+{ -+ switch (fault_status & AS_FAULTSTATUS_ACCESS_TYPE_MASK) { -+ case AS_FAULTSTATUS_ACCESS_TYPE_ATOMIC: -+ return "ATOMIC"; -+ case AS_FAULTSTATUS_ACCESS_TYPE_READ: -+ return "READ"; -+ case AS_FAULTSTATUS_ACCESS_TYPE_WRITE: -+ return "WRITE"; -+ case AS_FAULTSTATUS_ACCESS_TYPE_EX: -+ return "EXECUTE"; -+ default: -+ drm_WARN_ON(&ptdev->base, 1); -+ return NULL; -+ } -+} -+ -+static void panthor_mmu_irq_handler(struct panthor_device *ptdev, u32 status) -+{ -+ bool has_unhandled_faults = false; -+ -+ status = panthor_mmu_fault_mask(ptdev, status); -+ while (status) { -+ u32 as = ffs(status | (status >> 16)) - 1; -+ u32 mask = panthor_mmu_as_fault_mask(ptdev, as); -+ u32 new_int_mask; -+ u64 addr; -+ u32 fault_status; -+ u32 exception_type; -+ u32 access_type; -+ u32 source_id; -+ -+ fault_status = gpu_read(ptdev, AS_FAULTSTATUS(as)); -+ addr = gpu_read(ptdev, AS_FAULTADDRESS_LO(as)); -+ addr |= (u64)gpu_read(ptdev, AS_FAULTADDRESS_HI(as)) << 32; -+ -+ /* decode the fault status */ -+ exception_type = fault_status & 0xFF; -+ access_type = (fault_status >> 8) & 0x3; -+ source_id = (fault_status >> 16); -+ -+ mutex_lock(&ptdev->mmu->as.slots_lock); -+ -+ ptdev->mmu->as.faulty_mask |= mask; -+ new_int_mask = -+ panthor_mmu_fault_mask(ptdev, ~ptdev->mmu->as.faulty_mask); -+ -+ /* terminal fault, print info about the fault */ -+ drm_err(&ptdev->base, -+ "Unhandled Page fault in AS%d at VA 0x%016llX\n" -+ "raw fault status: 0x%X\n" -+ "decoded fault status: %s\n" -+ "exception type 0x%X: %s\n" -+ "access type 0x%X: %s\n" -+ "source id 0x%X\n", -+ as, addr, -+ fault_status, -+ (fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"), -+ exception_type, panthor_exception_name(ptdev, exception_type), -+ access_type, access_type_name(ptdev, fault_status), -+ source_id); -+ -+ /* Ignore MMU interrupts on this AS until it's been -+ * re-enabled. -+ */ -+ ptdev->mmu->irq.mask = new_int_mask; -+ gpu_write(ptdev, MMU_INT_MASK, new_int_mask); -+ -+ if (ptdev->mmu->as.slots[as].vm) -+ ptdev->mmu->as.slots[as].vm->unhandled_fault = true; -+ -+ /* Disable the MMU to kill jobs on this AS. */ -+ panthor_mmu_as_disable(ptdev, as); -+ mutex_unlock(&ptdev->mmu->as.slots_lock); -+ -+ status &= ~mask; -+ has_unhandled_faults = true; -+ } -+ -+ if (has_unhandled_faults) -+ panthor_sched_report_mmu_fault(ptdev); -+} -+PANTHOR_IRQ_HANDLER(mmu, MMU, panthor_mmu_irq_handler); -+ -+/** -+ * panthor_mmu_suspend() - Suspend the MMU logic -+ * @ptdev: Device. -+ * -+ * All we do here is de-assign the AS slots on all active VMs, so things -+ * get flushed to the main memory, and no further access to these VMs are -+ * possible. -+ * -+ * We also suspend the MMU IRQ. -+ */ -+void panthor_mmu_suspend(struct panthor_device *ptdev) -+{ -+ mutex_lock(&ptdev->mmu->as.slots_lock); -+ for (u32 i = 0; i < ARRAY_SIZE(ptdev->mmu->as.slots); i++) { -+ struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm; -+ -+ if (vm) { -+ drm_WARN_ON(&ptdev->base, panthor_mmu_as_disable(ptdev, i)); -+ panthor_vm_release_as_locked(vm); -+ } -+ } -+ mutex_unlock(&ptdev->mmu->as.slots_lock); -+ -+ panthor_mmu_irq_suspend(&ptdev->mmu->irq); -+} -+ -+/** -+ * panthor_mmu_resume() - Resume the MMU logic -+ * @ptdev: Device. -+ * -+ * Resume the IRQ. -+ * -+ * We don't re-enable previously active VMs. We assume other parts of the -+ * driver will call panthor_vm_active() on the VMs they intend to use. -+ */ -+void panthor_mmu_resume(struct panthor_device *ptdev) -+{ -+ mutex_lock(&ptdev->mmu->as.slots_lock); -+ ptdev->mmu->as.alloc_mask = 0; -+ ptdev->mmu->as.faulty_mask = 0; -+ mutex_unlock(&ptdev->mmu->as.slots_lock); -+ -+ panthor_mmu_irq_resume(&ptdev->mmu->irq, panthor_mmu_fault_mask(ptdev, ~0)); -+} -+ -+/** -+ * panthor_mmu_pre_reset() - Prepare for a reset -+ * @ptdev: Device. -+ * -+ * Suspend the IRQ, and make sure all VM_BIND queues are stopped, so we -+ * don't get asked to do a VM operation while the GPU is down. -+ * -+ * We don't cleanly shutdown the AS slots here, because the reset might -+ * come from an AS_ACTIVE_BIT stuck situation. -+ */ -+void panthor_mmu_pre_reset(struct panthor_device *ptdev) -+{ -+ struct panthor_vm *vm; -+ -+ panthor_mmu_irq_suspend(&ptdev->mmu->irq); -+ -+ mutex_lock(&ptdev->mmu->vm.lock); -+ ptdev->mmu->vm.reset_in_progress = true; -+ list_for_each_entry(vm, &ptdev->mmu->vm.list, node) -+ panthor_vm_stop(vm); -+ mutex_unlock(&ptdev->mmu->vm.lock); -+} -+ -+/** -+ * panthor_mmu_post_reset() - Restore things after a reset -+ * @ptdev: Device. -+ * -+ * Put the MMU logic back in action after a reset. That implies resuming the -+ * IRQ and re-enabling the VM_BIND queues. -+ */ -+void panthor_mmu_post_reset(struct panthor_device *ptdev) -+{ -+ struct panthor_vm *vm; -+ -+ mutex_lock(&ptdev->mmu->as.slots_lock); -+ -+ /* Now that the reset is effective, we can assume that none of the -+ * AS slots are setup, and clear the faulty flags too. -+ */ -+ ptdev->mmu->as.alloc_mask = 0; -+ ptdev->mmu->as.faulty_mask = 0; -+ -+ for (u32 i = 0; i < ARRAY_SIZE(ptdev->mmu->as.slots); i++) { -+ struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm; -+ -+ if (vm) -+ panthor_vm_release_as_locked(vm); -+ } -+ -+ mutex_unlock(&ptdev->mmu->as.slots_lock); -+ -+ panthor_mmu_irq_resume(&ptdev->mmu->irq, panthor_mmu_fault_mask(ptdev, ~0)); -+ -+ /* Restart the VM_BIND queues. */ -+ mutex_lock(&ptdev->mmu->vm.lock); -+ list_for_each_entry(vm, &ptdev->mmu->vm.list, node) { -+ panthor_vm_start(vm); -+ } -+ ptdev->mmu->vm.reset_in_progress = false; -+ mutex_unlock(&ptdev->mmu->vm.lock); -+} -+ -+static void panthor_vm_free(struct drm_gpuvm *gpuvm) -+{ -+ struct panthor_vm *vm = container_of(gpuvm, struct panthor_vm, base); -+ struct panthor_device *ptdev = vm->ptdev; -+ -+ mutex_lock(&vm->heaps.lock); -+ if (drm_WARN_ON(&ptdev->base, vm->heaps.pool)) -+ panthor_heap_pool_destroy(vm->heaps.pool); -+ mutex_unlock(&vm->heaps.lock); -+ mutex_destroy(&vm->heaps.lock); -+ -+ mutex_lock(&ptdev->mmu->vm.lock); -+ list_del(&vm->node); -+ /* Restore the scheduler state so we can call drm_sched_entity_destroy() -+ * and drm_sched_fini(). If get there, that means we have no job left -+ * and no new jobs can be queued, so we can start the scheduler without -+ * risking interfering with the reset. -+ */ -+ if (ptdev->mmu->vm.reset_in_progress) -+ panthor_vm_start(vm); -+ mutex_unlock(&ptdev->mmu->vm.lock); -+ -+ drm_sched_entity_destroy(&vm->entity); -+ drm_sched_fini(&vm->sched); -+ -+ mutex_lock(&ptdev->mmu->as.slots_lock); -+ if (vm->as.id >= 0) { -+ int cookie; -+ -+ if (drm_dev_enter(&ptdev->base, &cookie)) { -+ panthor_mmu_as_disable(ptdev, vm->as.id); -+ drm_dev_exit(cookie); -+ } -+ -+ ptdev->mmu->as.slots[vm->as.id].vm = NULL; -+ clear_bit(vm->as.id, &ptdev->mmu->as.alloc_mask); -+ list_del(&vm->as.lru_node); -+ } -+ mutex_unlock(&ptdev->mmu->as.slots_lock); -+ -+ free_io_pgtable_ops(vm->pgtbl_ops); -+ -+ drm_mm_takedown(&vm->mm); -+ kfree(vm); -+} -+ -+/** -+ * panthor_vm_put() - Release a reference on a VM -+ * @vm: VM to release the reference on. Can be NULL. -+ */ -+void panthor_vm_put(struct panthor_vm *vm) -+{ -+ drm_gpuvm_put(vm ? &vm->base : NULL); -+} -+ -+/** -+ * panthor_vm_get() - Get a VM reference -+ * @vm: VM to get the reference on. Can be NULL. -+ * -+ * Return: @vm value. -+ */ -+struct panthor_vm *panthor_vm_get(struct panthor_vm *vm) -+{ -+ if (vm) -+ drm_gpuvm_get(&vm->base); -+ -+ return vm; -+} -+ -+/** -+ * panthor_vm_get_heap_pool() - Get the heap pool attached to a VM -+ * @vm: VM to query the heap pool on. -+ * @create: True if the heap pool should be created when it doesn't exist. -+ * -+ * Heap pools are per-VM. This function allows one to retrieve the heap pool -+ * attached to a VM. -+ * -+ * If no heap pool exists yet, and @create is true, we create one. -+ * -+ * The returned panthor_heap_pool should be released with panthor_heap_pool_put(). -+ * -+ * Return: A valid pointer on success, an ERR_PTR() otherwise. -+ */ -+struct panthor_heap_pool *panthor_vm_get_heap_pool(struct panthor_vm *vm, bool create) -+{ -+ struct panthor_heap_pool *pool; -+ -+ mutex_lock(&vm->heaps.lock); -+ if (!vm->heaps.pool && create) { -+ if (vm->destroyed) -+ pool = ERR_PTR(-EINVAL); -+ else -+ pool = panthor_heap_pool_create(vm->ptdev, vm); -+ -+ if (!IS_ERR(pool)) -+ vm->heaps.pool = panthor_heap_pool_get(pool); -+ } else { -+ pool = panthor_heap_pool_get(vm->heaps.pool); -+ } -+ mutex_unlock(&vm->heaps.lock); -+ -+ return pool; -+} -+ -+static u64 mair_to_memattr(u64 mair) -+{ -+ u64 memattr = 0; -+ u32 i; -+ -+ for (i = 0; i < 8; i++) { -+ u8 in_attr = mair >> (8 * i), out_attr; -+ u8 outer = in_attr >> 4, inner = in_attr & 0xf; -+ -+ /* For caching to be enabled, inner and outer caching policy -+ * have to be both write-back, if one of them is write-through -+ * or non-cacheable, we just choose non-cacheable. Device -+ * memory is also translated to non-cacheable. -+ */ -+ if (!(outer & 3) || !(outer & 4) || !(inner & 4)) { -+ out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_NC | -+ AS_MEMATTR_AARCH64_SH_MIDGARD_INNER | -+ AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(false, false); -+ } else { -+ /* Use SH_CPU_INNER mode so SH_IS, which is used when -+ * IOMMU_CACHE is set, actually maps to the standard -+ * definition of inner-shareable and not Mali's -+ * internal-shareable mode. -+ */ -+ out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_WB | -+ AS_MEMATTR_AARCH64_SH_CPU_INNER | -+ AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(inner & 1, inner & 2); -+ } -+ -+ memattr |= (u64)out_attr << (8 * i); -+ } -+ -+ return memattr; -+} -+ -+static void panthor_vma_link(struct panthor_vm *vm, -+ struct panthor_vma *vma, -+ struct drm_gpuvm_bo *vm_bo) -+{ -+ struct panthor_gem_object *bo = to_panthor_bo(vma->base.gem.obj); -+ -+ mutex_lock(&bo->gpuva_list_lock); -+ drm_gpuva_link(&vma->base, vm_bo); -+ drm_WARN_ON(&vm->ptdev->base, drm_gpuvm_bo_put(vm_bo)); -+ mutex_unlock(&bo->gpuva_list_lock); -+} -+ -+static void panthor_vma_unlink(struct panthor_vm *vm, -+ struct panthor_vma *vma) -+{ -+ struct panthor_gem_object *bo = to_panthor_bo(vma->base.gem.obj); -+ struct drm_gpuvm_bo *vm_bo = drm_gpuvm_bo_get(vma->base.vm_bo); -+ -+ mutex_lock(&bo->gpuva_list_lock); -+ drm_gpuva_unlink(&vma->base); -+ mutex_unlock(&bo->gpuva_list_lock); -+ -+ /* drm_gpuva_unlink() release the vm_bo, but we manually retained it -+ * when entering this function, so we can implement deferred VMA -+ * destruction. Re-assign it here. -+ */ -+ vma->base.vm_bo = vm_bo; -+ list_add_tail(&vma->node, &vm->op_ctx->returned_vmas); -+} -+ -+static void panthor_vma_init(struct panthor_vma *vma, u32 flags) -+{ -+ INIT_LIST_HEAD(&vma->node); -+ vma->flags = flags; -+} -+ -+#define PANTHOR_VM_MAP_FLAGS \ -+ (DRM_PANTHOR_VM_BIND_OP_MAP_READONLY | \ -+ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | \ -+ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED) -+ -+static int panthor_gpuva_sm_step_map(struct drm_gpuva_op *op, void *priv) -+{ -+ struct panthor_vm *vm = priv; -+ struct panthor_vm_op_ctx *op_ctx = vm->op_ctx; -+ struct panthor_vma *vma = panthor_vm_op_ctx_get_vma(op_ctx); -+ int ret; -+ -+ if (!vma) -+ return -EINVAL; -+ -+ panthor_vma_init(vma, op_ctx->flags & PANTHOR_VM_MAP_FLAGS); -+ -+ ret = panthor_vm_map_pages(vm, op->map.va.addr, flags_to_prot(vma->flags), -+ op_ctx->map.sgt, op->map.gem.offset, -+ op->map.va.range); -+ if (ret) -+ return ret; -+ -+ /* Ref owned by the mapping now, clear the obj field so we don't release the -+ * pinning/obj ref behind GPUVA's back. -+ */ -+ drm_gpuva_map(&vm->base, &vma->base, &op->map); -+ panthor_vma_link(vm, vma, op_ctx->map.vm_bo); -+ op_ctx->map.vm_bo = NULL; -+ return 0; -+} -+ -+static int panthor_gpuva_sm_step_remap(struct drm_gpuva_op *op, -+ void *priv) -+{ -+ struct panthor_vma *unmap_vma = container_of(op->remap.unmap->va, struct panthor_vma, base); -+ struct panthor_vm *vm = priv; -+ struct panthor_vm_op_ctx *op_ctx = vm->op_ctx; -+ struct panthor_vma *prev_vma = NULL, *next_vma = NULL; -+ u64 unmap_start, unmap_range; -+ int ret; -+ -+ drm_gpuva_op_remap_to_unmap_range(&op->remap, &unmap_start, &unmap_range); -+ ret = panthor_vm_unmap_pages(vm, unmap_start, unmap_range); -+ if (ret) -+ return ret; -+ -+ if (op->remap.prev) { -+ prev_vma = panthor_vm_op_ctx_get_vma(op_ctx); -+ panthor_vma_init(prev_vma, unmap_vma->flags); -+ } -+ -+ if (op->remap.next) { -+ next_vma = panthor_vm_op_ctx_get_vma(op_ctx); -+ panthor_vma_init(next_vma, unmap_vma->flags); -+ } -+ -+ drm_gpuva_remap(prev_vma ? &prev_vma->base : NULL, -+ next_vma ? &next_vma->base : NULL, -+ &op->remap); -+ -+ if (prev_vma) { -+ /* panthor_vma_link() transfers the vm_bo ownership to -+ * the VMA object. Since the vm_bo we're passing is still -+ * owned by the old mapping which will be released when this -+ * mapping is destroyed, we need to grab a ref here. -+ */ -+ panthor_vma_link(vm, prev_vma, -+ drm_gpuvm_bo_get(op->remap.unmap->va->vm_bo)); -+ } -+ -+ if (next_vma) { -+ panthor_vma_link(vm, next_vma, -+ drm_gpuvm_bo_get(op->remap.unmap->va->vm_bo)); -+ } -+ -+ panthor_vma_unlink(vm, unmap_vma); -+ return 0; -+} -+ -+static int panthor_gpuva_sm_step_unmap(struct drm_gpuva_op *op, -+ void *priv) -+{ -+ struct panthor_vma *unmap_vma = container_of(op->unmap.va, struct panthor_vma, base); -+ struct panthor_vm *vm = priv; -+ int ret; -+ -+ ret = panthor_vm_unmap_pages(vm, unmap_vma->base.va.addr, -+ unmap_vma->base.va.range); -+ if (drm_WARN_ON(&vm->ptdev->base, ret)) -+ return ret; -+ -+ drm_gpuva_unmap(&op->unmap); -+ panthor_vma_unlink(vm, unmap_vma); -+ return 0; -+} -+ -+static const struct drm_gpuvm_ops panthor_gpuvm_ops = { -+ .vm_free = panthor_vm_free, -+ .sm_step_map = panthor_gpuva_sm_step_map, -+ .sm_step_remap = panthor_gpuva_sm_step_remap, -+ .sm_step_unmap = panthor_gpuva_sm_step_unmap, -+}; -+ -+/** -+ * panthor_vm_resv() - Get the dma_resv object attached to a VM. -+ * @vm: VM to get the dma_resv of. -+ * -+ * Return: A dma_resv object. -+ */ -+struct dma_resv *panthor_vm_resv(struct panthor_vm *vm) -+{ -+ return drm_gpuvm_resv(&vm->base); -+} -+ -+struct drm_gem_object *panthor_vm_root_gem(struct panthor_vm *vm) -+{ -+ if (!vm) -+ return NULL; -+ -+ return vm->base.r_obj; -+} -+ -+static int -+panthor_vm_exec_op(struct panthor_vm *vm, struct panthor_vm_op_ctx *op, -+ bool flag_vm_unusable_on_failure) -+{ -+ u32 op_type = op->flags & DRM_PANTHOR_VM_BIND_OP_TYPE_MASK; -+ int ret; -+ -+ if (op_type == DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY) -+ return 0; -+ -+ mutex_lock(&vm->op_lock); -+ vm->op_ctx = op; -+ switch (op_type) { -+ case DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: -+ if (vm->unusable) { -+ ret = -EINVAL; -+ break; -+ } -+ -+ ret = drm_gpuvm_sm_map(&vm->base, vm, op->va.addr, op->va.range, -+ op->map.vm_bo->obj, op->map.bo_offset); -+ break; -+ -+ case DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP: -+ ret = drm_gpuvm_sm_unmap(&vm->base, vm, op->va.addr, op->va.range); -+ break; -+ -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ if (ret && flag_vm_unusable_on_failure) -+ vm->unusable = true; -+ -+ vm->op_ctx = NULL; -+ mutex_unlock(&vm->op_lock); -+ -+ return ret; -+} -+ -+static struct dma_fence * -+panthor_vm_bind_run_job(struct drm_sched_job *sched_job) -+{ -+ struct panthor_vm_bind_job *job = container_of(sched_job, struct panthor_vm_bind_job, base); -+ bool cookie; -+ int ret; -+ -+ /* Not only we report an error whose result is propagated to the -+ * drm_sched finished fence, but we also flag the VM as unusable, because -+ * a failure in the async VM_BIND results in an inconsistent state. VM needs -+ * to be destroyed and recreated. -+ */ -+ cookie = dma_fence_begin_signalling(); -+ ret = panthor_vm_exec_op(job->vm, &job->ctx, true); -+ dma_fence_end_signalling(cookie); -+ -+ return ret ? ERR_PTR(ret) : NULL; -+} -+ -+static void panthor_vm_bind_job_release(struct kref *kref) -+{ -+ struct panthor_vm_bind_job *job = container_of(kref, struct panthor_vm_bind_job, refcount); -+ -+ if (job->base.s_fence) -+ drm_sched_job_cleanup(&job->base); -+ -+ panthor_vm_cleanup_op_ctx(&job->ctx, job->vm); -+ panthor_vm_put(job->vm); -+ kfree(job); -+} -+ -+/** -+ * panthor_vm_bind_job_put() - Release a VM_BIND job reference -+ * @sched_job: Job to release the reference on. -+ */ -+void panthor_vm_bind_job_put(struct drm_sched_job *sched_job) -+{ -+ struct panthor_vm_bind_job *job = -+ container_of(sched_job, struct panthor_vm_bind_job, base); -+ -+ if (sched_job) -+ kref_put(&job->refcount, panthor_vm_bind_job_release); -+} -+ -+static void -+panthor_vm_bind_free_job(struct drm_sched_job *sched_job) -+{ -+ struct panthor_vm_bind_job *job = -+ container_of(sched_job, struct panthor_vm_bind_job, base); -+ -+ drm_sched_job_cleanup(sched_job); -+ -+ /* Do the heavy cleanups asynchronously, so we're out of the -+ * dma-signaling path and can acquire dma-resv locks safely. -+ */ -+ queue_work(panthor_cleanup_wq, &job->cleanup_op_ctx_work); -+} -+ -+static enum drm_gpu_sched_stat -+panthor_vm_bind_timedout_job(struct drm_sched_job *sched_job) -+{ -+ WARN(1, "VM_BIND ops are synchronous for now, there should be no timeout!"); -+ return DRM_GPU_SCHED_STAT_NOMINAL; -+} -+ -+static const struct drm_sched_backend_ops panthor_vm_bind_ops = { -+ .run_job = panthor_vm_bind_run_job, -+ .free_job = panthor_vm_bind_free_job, -+ .timedout_job = panthor_vm_bind_timedout_job, -+}; -+ -+/** -+ * panthor_vm_create() - Create a VM -+ * @ptdev: Device. -+ * @for_mcu: True if this is the FW MCU VM. -+ * @kernel_va_start: Start of the range reserved for kernel BO mapping. -+ * @kernel_va_size: Size of the range reserved for kernel BO mapping. -+ * @auto_kernel_va_start: Start of the auto-VA kernel range. -+ * @auto_kernel_va_size: Size of the auto-VA kernel range. -+ * -+ * Return: A valid pointer on success, an ERR_PTR() otherwise. -+ */ -+struct panthor_vm * -+panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, -+ u64 kernel_va_start, u64 kernel_va_size, -+ u64 auto_kernel_va_start, u64 auto_kernel_va_size) -+{ -+ u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features); -+ u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(ptdev->gpu_info.mmu_features); -+ u64 full_va_range = 1ull << va_bits; -+ struct drm_gem_object *dummy_gem; -+ struct drm_gpu_scheduler *sched; -+ struct io_pgtable_cfg pgtbl_cfg; -+ u64 mair, min_va, va_range; -+ struct panthor_vm *vm; -+ int ret; -+ -+ vm = kzalloc(sizeof(*vm), GFP_KERNEL); -+ if (!vm) -+ return ERR_PTR(-ENOMEM); -+ -+ /* We allocate a dummy GEM for the VM. */ -+ dummy_gem = drm_gpuvm_resv_object_alloc(&ptdev->base); -+ if (!dummy_gem) { -+ ret = -ENOMEM; -+ goto err_free_vm; -+ } -+ -+ mutex_init(&vm->heaps.lock); -+ vm->for_mcu = for_mcu; -+ vm->ptdev = ptdev; -+ mutex_init(&vm->op_lock); -+ -+ if (for_mcu) { -+ /* CSF MCU is a cortex M7, and can only address 4G */ -+ min_va = 0; -+ va_range = SZ_4G; -+ } else { -+ min_va = 0; -+ va_range = full_va_range; -+ } -+ -+ mutex_init(&vm->mm_lock); -+ drm_mm_init(&vm->mm, kernel_va_start, kernel_va_size); -+ vm->kernel_auto_va.start = auto_kernel_va_start; -+ vm->kernel_auto_va.end = vm->kernel_auto_va.start + auto_kernel_va_size - 1; -+ -+ INIT_LIST_HEAD(&vm->node); -+ INIT_LIST_HEAD(&vm->as.lru_node); -+ vm->as.id = -1; -+ refcount_set(&vm->as.active_cnt, 0); -+ -+ pgtbl_cfg = (struct io_pgtable_cfg) { -+ .pgsize_bitmap = SZ_4K | SZ_2M, -+ .ias = va_bits, -+ .oas = pa_bits, -+ .coherent_walk = ptdev->coherent, -+ .tlb = &mmu_tlb_ops, -+ .iommu_dev = ptdev->base.dev, -+ .alloc = alloc_pt, -+ .free = free_pt, -+ }; -+ -+ vm->pgtbl_ops = alloc_io_pgtable_ops(ARM_64_LPAE_S1, &pgtbl_cfg, vm); -+ if (!vm->pgtbl_ops) { -+ ret = -EINVAL; -+ goto err_mm_takedown; -+ } -+ -+ /* Bind operations are synchronous for now, no timeout needed. */ -+ ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, ptdev->mmu->vm.wq, -+ 1, 1, 0, -+ MAX_SCHEDULE_TIMEOUT, NULL, NULL, -+ "panthor-vm-bind", ptdev->base.dev); -+ if (ret) -+ goto err_free_io_pgtable; -+ -+ sched = &vm->sched; -+ ret = drm_sched_entity_init(&vm->entity, 0, &sched, 1, NULL); -+ if (ret) -+ goto err_sched_fini; -+ -+ mair = io_pgtable_ops_to_pgtable(vm->pgtbl_ops)->cfg.arm_lpae_s1_cfg.mair; -+ vm->memattr = mair_to_memattr(mair); -+ -+ mutex_lock(&ptdev->mmu->vm.lock); -+ list_add_tail(&vm->node, &ptdev->mmu->vm.list); -+ -+ /* If a reset is in progress, stop the scheduler. */ -+ if (ptdev->mmu->vm.reset_in_progress) -+ panthor_vm_stop(vm); -+ mutex_unlock(&ptdev->mmu->vm.lock); -+ -+ /* We intentionally leave the reserved range to zero, because we want kernel VMAs -+ * to be handled the same way user VMAs are. -+ */ -+ drm_gpuvm_init(&vm->base, for_mcu ? "panthor-MCU-VM" : "panthor-GPU-VM", -+ DRM_GPUVM_RESV_PROTECTED, &ptdev->base, dummy_gem, -+ min_va, va_range, 0, 0, &panthor_gpuvm_ops); -+ drm_gem_object_put(dummy_gem); -+ return vm; -+ -+err_sched_fini: -+ drm_sched_fini(&vm->sched); -+ -+err_free_io_pgtable: -+ free_io_pgtable_ops(vm->pgtbl_ops); -+ -+err_mm_takedown: -+ drm_mm_takedown(&vm->mm); -+ drm_gem_object_put(dummy_gem); -+ -+err_free_vm: -+ kfree(vm); -+ return ERR_PTR(ret); -+} -+ -+static int -+panthor_vm_bind_prepare_op_ctx(struct drm_file *file, -+ struct panthor_vm *vm, -+ const struct drm_panthor_vm_bind_op *op, -+ struct panthor_vm_op_ctx *op_ctx) -+{ -+ struct drm_gem_object *gem; -+ int ret; -+ -+ /* Aligned on page size. */ -+ if ((op->va | op->size) & ~PAGE_MASK) -+ return -EINVAL; -+ -+ switch (op->flags & DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) { -+ case DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: -+ gem = drm_gem_object_lookup(file, op->bo_handle); -+ ret = panthor_vm_prepare_map_op_ctx(op_ctx, vm, -+ gem ? to_panthor_bo(gem) : NULL, -+ op->bo_offset, -+ op->size, -+ op->va, -+ op->flags); -+ drm_gem_object_put(gem); -+ return ret; -+ -+ case DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP: -+ if (op->flags & ~DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) -+ return -EINVAL; -+ -+ if (op->bo_handle || op->bo_offset) -+ return -EINVAL; -+ -+ return panthor_vm_prepare_unmap_op_ctx(op_ctx, vm, op->va, op->size); -+ -+ case DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY: -+ if (op->flags & ~DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) -+ return -EINVAL; -+ -+ if (op->bo_handle || op->bo_offset) -+ return -EINVAL; -+ -+ if (op->va || op->size) -+ return -EINVAL; -+ -+ if (!op->syncs.count) -+ return -EINVAL; -+ -+ panthor_vm_prepare_sync_only_op_ctx(op_ctx, vm); -+ return 0; -+ -+ default: -+ return -EINVAL; -+ } -+} -+ -+static void panthor_vm_bind_job_cleanup_op_ctx_work(struct work_struct *work) -+{ -+ struct panthor_vm_bind_job *job = -+ container_of(work, struct panthor_vm_bind_job, cleanup_op_ctx_work); -+ -+ panthor_vm_bind_job_put(&job->base); -+} -+ -+/** -+ * panthor_vm_bind_job_create() - Create a VM_BIND job -+ * @file: File. -+ * @vm: VM targeted by the VM_BIND job. -+ * @op: VM operation data. -+ * -+ * Return: A valid pointer on success, an ERR_PTR() otherwise. -+ */ -+struct drm_sched_job * -+panthor_vm_bind_job_create(struct drm_file *file, -+ struct panthor_vm *vm, -+ const struct drm_panthor_vm_bind_op *op) -+{ -+ struct panthor_vm_bind_job *job; -+ int ret; -+ -+ if (!vm) -+ return ERR_PTR(-EINVAL); -+ -+ if (vm->destroyed || vm->unusable) -+ return ERR_PTR(-EINVAL); -+ -+ job = kzalloc(sizeof(*job), GFP_KERNEL); -+ if (!job) -+ return ERR_PTR(-ENOMEM); -+ -+ ret = panthor_vm_bind_prepare_op_ctx(file, vm, op, &job->ctx); -+ if (ret) { -+ kfree(job); -+ return ERR_PTR(ret); -+ } -+ -+ INIT_WORK(&job->cleanup_op_ctx_work, panthor_vm_bind_job_cleanup_op_ctx_work); -+ kref_init(&job->refcount); -+ job->vm = panthor_vm_get(vm); -+ -+ ret = drm_sched_job_init(&job->base, &vm->entity, 1, vm); -+ if (ret) -+ goto err_put_job; -+ -+ return &job->base; -+ -+err_put_job: -+ panthor_vm_bind_job_put(&job->base); -+ return ERR_PTR(ret); -+} -+ -+/** -+ * panthor_vm_bind_job_prepare_resvs() - Prepare VM_BIND job dma_resvs -+ * @exec: The locking/preparation context. -+ * @sched_job: The job to prepare resvs on. -+ * -+ * Locks and prepare the VM resv. -+ * -+ * If this is a map operation, locks and prepares the GEM resv. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_vm_bind_job_prepare_resvs(struct drm_exec *exec, -+ struct drm_sched_job *sched_job) -+{ -+ struct panthor_vm_bind_job *job = container_of(sched_job, struct panthor_vm_bind_job, base); -+ int ret; -+ -+ /* Acquire the VM lock an reserve a slot for this VM bind job. */ -+ ret = drm_gpuvm_prepare_vm(&job->vm->base, exec, 1); -+ if (ret) -+ return ret; -+ -+ if (job->ctx.map.vm_bo) { -+ /* Lock/prepare the GEM being mapped. */ -+ ret = drm_exec_prepare_obj(exec, job->ctx.map.vm_bo->obj, 1); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * panthor_vm_bind_job_update_resvs() - Update the resv objects touched by a job -+ * @exec: drm_exec context. -+ * @sched_job: Job to update the resvs on. -+ */ -+void panthor_vm_bind_job_update_resvs(struct drm_exec *exec, -+ struct drm_sched_job *sched_job) -+{ -+ struct panthor_vm_bind_job *job = container_of(sched_job, struct panthor_vm_bind_job, base); -+ -+ /* Explicit sync => we just register our job finished fence as bookkeep. */ -+ drm_gpuvm_resv_add_fence(&job->vm->base, exec, -+ &sched_job->s_fence->finished, -+ DMA_RESV_USAGE_BOOKKEEP, -+ DMA_RESV_USAGE_BOOKKEEP); -+} -+ -+void panthor_vm_update_resvs(struct panthor_vm *vm, struct drm_exec *exec, -+ struct dma_fence *fence, -+ enum dma_resv_usage private_usage, -+ enum dma_resv_usage extobj_usage) -+{ -+ drm_gpuvm_resv_add_fence(&vm->base, exec, fence, private_usage, extobj_usage); -+} -+ -+/** -+ * panthor_vm_bind_exec_sync_op() - Execute a VM_BIND operation synchronously. -+ * @file: File. -+ * @vm: VM targeted by the VM operation. -+ * @op: Data describing the VM operation. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_vm_bind_exec_sync_op(struct drm_file *file, -+ struct panthor_vm *vm, -+ struct drm_panthor_vm_bind_op *op) -+{ -+ struct panthor_vm_op_ctx op_ctx; -+ int ret; -+ -+ /* No sync objects allowed on synchronous operations. */ -+ if (op->syncs.count) -+ return -EINVAL; -+ -+ if (!op->size) -+ return 0; -+ -+ ret = panthor_vm_bind_prepare_op_ctx(file, vm, op, &op_ctx); -+ if (ret) -+ return ret; -+ -+ ret = panthor_vm_exec_op(vm, &op_ctx, false); -+ panthor_vm_cleanup_op_ctx(&op_ctx, vm); -+ -+ return ret; -+} -+ -+/** -+ * panthor_vm_map_bo_range() - Map a GEM object range to a VM -+ * @vm: VM to map the GEM to. -+ * @bo: GEM object to map. -+ * @offset: Offset in the GEM object. -+ * @size: Size to map. -+ * @va: Virtual address to map the object to. -+ * @flags: Combination of drm_panthor_vm_bind_op_flags flags. -+ * Only map-related flags are valid. -+ * -+ * Internal use only. For userspace requests, use -+ * panthor_vm_bind_exec_sync_op() instead. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_vm_map_bo_range(struct panthor_vm *vm, struct panthor_gem_object *bo, -+ u64 offset, u64 size, u64 va, u32 flags) -+{ -+ struct panthor_vm_op_ctx op_ctx; -+ int ret; -+ -+ ret = panthor_vm_prepare_map_op_ctx(&op_ctx, vm, bo, offset, size, va, flags); -+ if (ret) -+ return ret; -+ -+ ret = panthor_vm_exec_op(vm, &op_ctx, false); -+ panthor_vm_cleanup_op_ctx(&op_ctx, vm); -+ -+ return ret; -+} -+ -+/** -+ * panthor_vm_unmap_range() - Unmap a portion of the VA space -+ * @vm: VM to unmap the region from. -+ * @va: Virtual address to unmap. Must be 4k aligned. -+ * @size: Size of the region to unmap. Must be 4k aligned. -+ * -+ * Internal use only. For userspace requests, use -+ * panthor_vm_bind_exec_sync_op() instead. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_vm_unmap_range(struct panthor_vm *vm, u64 va, u64 size) -+{ -+ struct panthor_vm_op_ctx op_ctx; -+ int ret; -+ -+ ret = panthor_vm_prepare_unmap_op_ctx(&op_ctx, vm, va, size); -+ if (ret) -+ return ret; -+ -+ ret = panthor_vm_exec_op(vm, &op_ctx, false); -+ panthor_vm_cleanup_op_ctx(&op_ctx, vm); -+ -+ return ret; -+} -+ -+/** -+ * panthor_vm_prepare_mapped_bos_resvs() - Prepare resvs on VM BOs. -+ * @exec: Locking/preparation context. -+ * @vm: VM targeted by the GPU job. -+ * @slot_count: Number of slots to reserve. -+ * -+ * GPU jobs assume all BOs bound to the VM at the time the job is submitted -+ * are available when the job is executed. In order to guarantee that, we -+ * need to reserve a slot on all BOs mapped to a VM and update this slot with -+ * the job fence after its submission. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_vm_prepare_mapped_bos_resvs(struct drm_exec *exec, struct panthor_vm *vm, -+ u32 slot_count) -+{ -+ int ret; -+ -+ /* Acquire the VM lock and reserve a slot for this GPU job. */ -+ ret = drm_gpuvm_prepare_vm(&vm->base, exec, slot_count); -+ if (ret) -+ return ret; -+ -+ return drm_gpuvm_prepare_objects(&vm->base, exec, slot_count); -+} -+ -+/** -+ * panthor_mmu_unplug() - Unplug the MMU logic -+ * @ptdev: Device. -+ * -+ * No access to the MMU regs should be done after this function is called. -+ * We suspend the IRQ and disable all VMs to guarantee that. -+ */ -+void panthor_mmu_unplug(struct panthor_device *ptdev) -+{ -+ panthor_mmu_irq_suspend(&ptdev->mmu->irq); -+ -+ mutex_lock(&ptdev->mmu->as.slots_lock); -+ for (u32 i = 0; i < ARRAY_SIZE(ptdev->mmu->as.slots); i++) { -+ struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm; -+ -+ if (vm) { -+ drm_WARN_ON(&ptdev->base, panthor_mmu_as_disable(ptdev, i)); -+ panthor_vm_release_as_locked(vm); -+ } -+ } -+ mutex_unlock(&ptdev->mmu->as.slots_lock); -+} -+ -+static void panthor_mmu_release_wq(struct drm_device *ddev, void *res) -+{ -+ destroy_workqueue(res); -+} -+ -+/** -+ * panthor_mmu_init() - Initialize the MMU logic. -+ * @ptdev: Device. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_mmu_init(struct panthor_device *ptdev) -+{ -+ u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features); -+ struct panthor_mmu *mmu; -+ int ret, irq; -+ -+ mmu = drmm_kzalloc(&ptdev->base, sizeof(*mmu), GFP_KERNEL); -+ if (!mmu) -+ return -ENOMEM; -+ -+ INIT_LIST_HEAD(&mmu->as.lru_list); -+ -+ ret = drmm_mutex_init(&ptdev->base, &mmu->as.slots_lock); -+ if (ret) -+ return ret; -+ -+ INIT_LIST_HEAD(&mmu->vm.list); -+ ret = drmm_mutex_init(&ptdev->base, &mmu->vm.lock); -+ if (ret) -+ return ret; -+ -+ ptdev->mmu = mmu; -+ -+ irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "mmu"); -+ if (irq <= 0) -+ return -ENODEV; -+ -+ ret = panthor_request_mmu_irq(ptdev, &mmu->irq, irq, -+ panthor_mmu_fault_mask(ptdev, ~0)); -+ if (ret) -+ return ret; -+ -+ mmu->vm.wq = alloc_workqueue("panthor-vm-bind", WQ_UNBOUND, 0); -+ if (!mmu->vm.wq) -+ return -ENOMEM; -+ -+ /* On 32-bit kernels, the VA space is limited by the io_pgtable_ops abstraction, -+ * which passes iova as an unsigned long. Patch the mmu_features to reflect this -+ * limitation. -+ */ -+ if (sizeof(unsigned long) * 8 < va_bits) { -+ ptdev->gpu_info.mmu_features &= ~GENMASK(7, 0); -+ ptdev->gpu_info.mmu_features |= sizeof(unsigned long) * 8; -+ } -+ -+ return drmm_add_action_or_reset(&ptdev->base, panthor_mmu_release_wq, mmu->vm.wq); -+} -+ -+#ifdef CONFIG_DEBUG_FS -+static int show_vm_gpuvas(struct panthor_vm *vm, struct seq_file *m) -+{ -+ int ret; -+ -+ mutex_lock(&vm->op_lock); -+ ret = drm_debugfs_gpuva_info(m, &vm->base); -+ mutex_unlock(&vm->op_lock); -+ -+ return ret; -+} -+ -+static int show_each_vm(struct seq_file *m, void *arg) -+{ -+ struct drm_info_node *node = (struct drm_info_node *)m->private; -+ struct drm_device *ddev = node->minor->dev; -+ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); -+ int (*show)(struct panthor_vm *, struct seq_file *) = node->info_ent->data; -+ struct panthor_vm *vm; -+ int ret = 0; -+ -+ mutex_lock(&ptdev->mmu->vm.lock); -+ list_for_each_entry(vm, &ptdev->mmu->vm.list, node) { -+ ret = show(vm, m); -+ if (ret < 0) -+ break; -+ -+ seq_puts(m, "\n"); -+ } -+ mutex_unlock(&ptdev->mmu->vm.lock); -+ -+ return ret; -+} -+ -+static struct drm_info_list panthor_mmu_debugfs_list[] = { -+ DRM_DEBUGFS_GPUVA_INFO(show_each_vm, show_vm_gpuvas), -+}; -+ -+/** -+ * panthor_mmu_debugfs_init() - Initialize MMU debugfs entries -+ * @minor: Minor. -+ */ -+void panthor_mmu_debugfs_init(struct drm_minor *minor) -+{ -+ drm_debugfs_create_files(panthor_mmu_debugfs_list, -+ ARRAY_SIZE(panthor_mmu_debugfs_list), -+ minor->debugfs_root, minor); -+} -+#endif /* CONFIG_DEBUG_FS */ -+ -+/** -+ * panthor_mmu_pt_cache_init() - Initialize the page table cache. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_mmu_pt_cache_init(void) -+{ -+ pt_cache = kmem_cache_create("panthor-mmu-pt", SZ_4K, SZ_4K, 0, NULL); -+ if (!pt_cache) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+/** -+ * panthor_mmu_pt_cache_fini() - Destroy the page table cache. -+ */ -+void panthor_mmu_pt_cache_fini(void) -+{ -+ kmem_cache_destroy(pt_cache); -+} -diff --git a/drivers/gpu/drm/panthor/panthor_mmu.h b/drivers/gpu/drm/panthor/panthor_mmu.h -new file mode 100644 -index 000000000000..f3c1ed19f973 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_mmu.h -@@ -0,0 +1,102 @@ -+/* SPDX-License-Identifier: GPL-2.0 or MIT */ -+/* Copyright 2019 Linaro, Ltd, Rob Herring */ -+/* Copyright 2023 Collabora ltd. */ -+ -+#ifndef __PANTHOR_MMU_H__ -+#define __PANTHOR_MMU_H__ -+ -+#include -+ -+struct drm_exec; -+struct drm_sched_job; -+struct panthor_gem_object; -+struct panthor_heap_pool; -+struct panthor_vm; -+struct panthor_vma; -+struct panthor_mmu; -+ -+int panthor_mmu_init(struct panthor_device *ptdev); -+void panthor_mmu_unplug(struct panthor_device *ptdev); -+void panthor_mmu_pre_reset(struct panthor_device *ptdev); -+void panthor_mmu_post_reset(struct panthor_device *ptdev); -+void panthor_mmu_suspend(struct panthor_device *ptdev); -+void panthor_mmu_resume(struct panthor_device *ptdev); -+ -+int panthor_vm_map_bo_range(struct panthor_vm *vm, struct panthor_gem_object *bo, -+ u64 offset, u64 size, u64 va, u32 flags); -+int panthor_vm_unmap_range(struct panthor_vm *vm, u64 va, u64 size); -+struct panthor_gem_object * -+panthor_vm_get_bo_for_va(struct panthor_vm *vm, u64 va, u64 *bo_offset); -+ -+int panthor_vm_active(struct panthor_vm *vm); -+void panthor_vm_idle(struct panthor_vm *vm); -+int panthor_vm_as(struct panthor_vm *vm); -+ -+struct panthor_heap_pool * -+panthor_vm_get_heap_pool(struct panthor_vm *vm, bool create); -+ -+struct panthor_vm *panthor_vm_get(struct panthor_vm *vm); -+void panthor_vm_put(struct panthor_vm *vm); -+struct panthor_vm *panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, -+ u64 kernel_va_start, u64 kernel_va_size, -+ u64 kernel_auto_va_start, -+ u64 kernel_auto_va_size); -+ -+int panthor_vm_prepare_mapped_bos_resvs(struct drm_exec *exec, -+ struct panthor_vm *vm, -+ u32 slot_count); -+int panthor_vm_add_bos_resvs_deps_to_job(struct panthor_vm *vm, -+ struct drm_sched_job *job); -+void panthor_vm_add_job_fence_to_bos_resvs(struct panthor_vm *vm, -+ struct drm_sched_job *job); -+ -+struct dma_resv *panthor_vm_resv(struct panthor_vm *vm); -+struct drm_gem_object *panthor_vm_root_gem(struct panthor_vm *vm); -+ -+void panthor_vm_pool_destroy(struct panthor_file *pfile); -+int panthor_vm_pool_create(struct panthor_file *pfile); -+int panthor_vm_pool_create_vm(struct panthor_device *ptdev, -+ struct panthor_vm_pool *pool, -+ struct drm_panthor_vm_create *args); -+int panthor_vm_pool_destroy_vm(struct panthor_vm_pool *pool, u32 handle); -+struct panthor_vm *panthor_vm_pool_get_vm(struct panthor_vm_pool *pool, u32 handle); -+ -+bool panthor_vm_has_unhandled_faults(struct panthor_vm *vm); -+bool panthor_vm_is_unusable(struct panthor_vm *vm); -+ -+/* -+ * PANTHOR_VM_KERNEL_AUTO_VA: Use this magic address when you want the GEM -+ * logic to auto-allocate the virtual address in the reserved kernel VA range. -+ */ -+#define PANTHOR_VM_KERNEL_AUTO_VA ~0ull -+ -+int panthor_vm_alloc_va(struct panthor_vm *vm, u64 va, u64 size, -+ struct drm_mm_node *va_node); -+void panthor_vm_free_va(struct panthor_vm *vm, struct drm_mm_node *va_node); -+ -+int panthor_vm_bind_exec_sync_op(struct drm_file *file, -+ struct panthor_vm *vm, -+ struct drm_panthor_vm_bind_op *op); -+ -+struct drm_sched_job * -+panthor_vm_bind_job_create(struct drm_file *file, -+ struct panthor_vm *vm, -+ const struct drm_panthor_vm_bind_op *op); -+void panthor_vm_bind_job_put(struct drm_sched_job *job); -+int panthor_vm_bind_job_prepare_resvs(struct drm_exec *exec, -+ struct drm_sched_job *job); -+void panthor_vm_bind_job_update_resvs(struct drm_exec *exec, struct drm_sched_job *job); -+ -+void panthor_vm_update_resvs(struct panthor_vm *vm, struct drm_exec *exec, -+ struct dma_fence *fence, -+ enum dma_resv_usage private_usage, -+ enum dma_resv_usage extobj_usage); -+ -+int panthor_mmu_pt_cache_init(void); -+void panthor_mmu_pt_cache_fini(void); -+ -+#ifdef CONFIG_DEBUG_FS -+void panthor_mmu_debugfs_init(struct drm_minor *minor); -+#endif -+ -+#endif --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:22 +0100 -Subject: drm/panthor: Add the FW logical block - -Contains everything that's FW related, that includes the code dealing -with the microcontroller unit (MCU) that's running the FW, and anything -related to allocating memory shared between the FW and the CPU. - -A few global FW events are processed in the IRQ handler, the rest is -forwarded to the scheduler, since scheduling is the primary reason for -the FW existence, and also the main source of FW <-> kernel -interactions. - -v6: -- Add Maxime's and Heiko's acks -- Keep header inclusion alphabetically ordered - -v5: -- Fix typo in GLB_PERFCNT_SAMPLE definition -- Fix unbalanced panthor_vm_idle/active() calls -- Fallback to a slow reset when the fast reset fails -- Add extra information when reporting a FW boot failure - -v4: -- Add a MODULE_FIRMWARE() entry for gen 10.8 -- Fix a wrong return ERR_PTR() in panthor_fw_load_section_entry() -- Fix typos -- Add Steve's R-b - -v3: -- Make the FW path more future-proof (Liviu) -- Use one waitqueue for all FW events -- Simplify propagation of FW events to the scheduler logic -- Drop the panthor_fw_mem abstraction and use panthor_kernel_bo instead -- Account for the panthor_vm changes -- Replace magic number with 0x7fffffff with ~0 to better signify that - it's the maximum permitted value. -- More accurate rounding when computing the firmware timeout. -- Add a 'sub iterator' helper function. This also adds a check that a - firmware entry doesn't overflow the firmware image. -- Drop __packed from FW structures, natural alignment is good enough. -- Other minor code improvements. - -Co-developed-by: Steven Price -Signed-off-by: Steven Price -Signed-off-by: Boris Brezillon -Reviewed-by: Steven Price -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - drivers/gpu/drm/panthor/panthor_fw.c | 1362 ++++++++++ - drivers/gpu/drm/panthor/panthor_fw.h | 503 ++++ - 2 files changed, 1865 insertions(+) - -diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c -new file mode 100644 -index 000000000000..33c87a59834e ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_fw.c -@@ -0,0 +1,1362 @@ -+// SPDX-License-Identifier: GPL-2.0 or MIT -+/* Copyright 2023 Collabora ltd. */ -+ -+#ifdef CONFIG_ARM_ARCH_TIMER -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "panthor_device.h" -+#include "panthor_fw.h" -+#include "panthor_gem.h" -+#include "panthor_gpu.h" -+#include "panthor_mmu.h" -+#include "panthor_regs.h" -+#include "panthor_sched.h" -+ -+#define CSF_FW_NAME "mali_csffw.bin" -+ -+#define PING_INTERVAL_MS 12000 -+#define PROGRESS_TIMEOUT_CYCLES (5ull * 500 * 1024 * 1024) -+#define PROGRESS_TIMEOUT_SCALE_SHIFT 10 -+#define IDLE_HYSTERESIS_US 800 -+#define PWROFF_HYSTERESIS_US 10000 -+ -+/** -+ * struct panthor_fw_binary_hdr - Firmware binary header. -+ */ -+struct panthor_fw_binary_hdr { -+ /** @magic: Magic value to check binary validity. */ -+ u32 magic; -+#define CSF_FW_BINARY_HEADER_MAGIC 0xc3f13a6e -+ -+ /** @minor: Minor FW version. */ -+ u8 minor; -+ -+ /** @major: Major FW version. */ -+ u8 major; -+#define CSF_FW_BINARY_HEADER_MAJOR_MAX 0 -+ -+ /** @padding1: MBZ. */ -+ u16 padding1; -+ -+ /** @version_hash: FW version hash. */ -+ u32 version_hash; -+ -+ /** @padding2: MBZ. */ -+ u32 padding2; -+ -+ /** @size: FW binary size. */ -+ u32 size; -+}; -+ -+/** -+ * enum panthor_fw_binary_entry_type - Firmware binary entry type -+ */ -+enum panthor_fw_binary_entry_type { -+ /** @CSF_FW_BINARY_ENTRY_TYPE_IFACE: Host <-> FW interface. */ -+ CSF_FW_BINARY_ENTRY_TYPE_IFACE = 0, -+ -+ /** @CSF_FW_BINARY_ENTRY_TYPE_CONFIG: FW config. */ -+ CSF_FW_BINARY_ENTRY_TYPE_CONFIG = 1, -+ -+ /** @CSF_FW_BINARY_ENTRY_TYPE_FUTF_TEST: Unit-tests. */ -+ CSF_FW_BINARY_ENTRY_TYPE_FUTF_TEST = 2, -+ -+ /** @CSF_FW_BINARY_ENTRY_TYPE_TRACE_BUFFER: Trace buffer interface. */ -+ CSF_FW_BINARY_ENTRY_TYPE_TRACE_BUFFER = 3, -+ -+ /** @CSF_FW_BINARY_ENTRY_TYPE_TIMELINE_METADATA: Timeline metadata interface. */ -+ CSF_FW_BINARY_ENTRY_TYPE_TIMELINE_METADATA = 4, -+}; -+ -+#define CSF_FW_BINARY_ENTRY_TYPE(ehdr) ((ehdr) & 0xff) -+#define CSF_FW_BINARY_ENTRY_SIZE(ehdr) (((ehdr) >> 8) & 0xff) -+#define CSF_FW_BINARY_ENTRY_UPDATE BIT(30) -+#define CSF_FW_BINARY_ENTRY_OPTIONAL BIT(31) -+ -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_RD BIT(0) -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_WR BIT(1) -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_EX BIT(2) -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_NONE (0 << 3) -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_CACHED (1 << 3) -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_UNCACHED_COHERENT (2 << 3) -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_CACHED_COHERENT (3 << 3) -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_MASK GENMASK(4, 3) -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_PROT BIT(5) -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_SHARED BIT(30) -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_ZERO BIT(31) -+ -+#define CSF_FW_BINARY_IFACE_ENTRY_RD_SUPPORTED_FLAGS \ -+ (CSF_FW_BINARY_IFACE_ENTRY_RD_RD | \ -+ CSF_FW_BINARY_IFACE_ENTRY_RD_WR | \ -+ CSF_FW_BINARY_IFACE_ENTRY_RD_EX | \ -+ CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_MASK | \ -+ CSF_FW_BINARY_IFACE_ENTRY_RD_PROT | \ -+ CSF_FW_BINARY_IFACE_ENTRY_RD_SHARED | \ -+ CSF_FW_BINARY_IFACE_ENTRY_RD_ZERO) -+ -+/** -+ * struct panthor_fw_binary_section_entry_hdr - Describes a section of FW binary -+ */ -+struct panthor_fw_binary_section_entry_hdr { -+ /** @flags: Section flags. */ -+ u32 flags; -+ -+ /** @va: MCU virtual range to map this binary section to. */ -+ struct { -+ /** @start: Start address. */ -+ u32 start; -+ -+ /** @end: End address. */ -+ u32 end; -+ } va; -+ -+ /** @data: Data to initialize the FW section with. */ -+ struct { -+ /** @start: Start offset in the FW binary. */ -+ u32 start; -+ -+ /** @end: End offset in the FW binary. */ -+ u32 end; -+ } data; -+}; -+ -+/** -+ * struct panthor_fw_binary_iter - Firmware binary iterator -+ * -+ * Used to parse a firmware binary. -+ */ -+struct panthor_fw_binary_iter { -+ /** @data: FW binary data. */ -+ const void *data; -+ -+ /** @size: FW binary size. */ -+ size_t size; -+ -+ /** @offset: Iterator offset. */ -+ size_t offset; -+}; -+ -+/** -+ * struct panthor_fw_section - FW section -+ */ -+struct panthor_fw_section { -+ /** @node: Used to keep track of FW sections. */ -+ struct list_head node; -+ -+ /** @flags: Section flags, as encoded in the FW binary. */ -+ u32 flags; -+ -+ /** @mem: Section memory. */ -+ struct panthor_kernel_bo *mem; -+ -+ /** -+ * @name: Name of the section, as specified in the binary. -+ * -+ * Can be NULL. -+ */ -+ const char *name; -+ -+ /** -+ * @data: Initial data copied to the FW memory. -+ * -+ * We keep data around so we can reload sections after a reset. -+ */ -+ struct { -+ /** @buf: Buffed used to store init data. */ -+ const void *buf; -+ -+ /** @size: Size of @buf in bytes. */ -+ size_t size; -+ } data; -+}; -+ -+#define CSF_MCU_SHARED_REGION_START 0x04000000ULL -+#define CSF_MCU_SHARED_REGION_SIZE 0x04000000ULL -+ -+#define MIN_CS_PER_CSG 8 -+#define MIN_CSGS 3 -+#define MAX_CSG_PRIO 0xf -+ -+#define CSF_IFACE_VERSION(major, minor, patch) \ -+ (((major) << 24) | ((minor) << 16) | (patch)) -+#define CSF_IFACE_VERSION_MAJOR(v) ((v) >> 24) -+#define CSF_IFACE_VERSION_MINOR(v) (((v) >> 16) & 0xff) -+#define CSF_IFACE_VERSION_PATCH(v) ((v) & 0xffff) -+ -+#define CSF_GROUP_CONTROL_OFFSET 0x1000 -+#define CSF_STREAM_CONTROL_OFFSET 0x40 -+#define CSF_UNPRESERVED_REG_COUNT 4 -+ -+/** -+ * struct panthor_fw_iface - FW interfaces -+ */ -+struct panthor_fw_iface { -+ /** @global: Global interface. */ -+ struct panthor_fw_global_iface global; -+ -+ /** @groups: Group slot interfaces. */ -+ struct panthor_fw_csg_iface groups[MAX_CSGS]; -+ -+ /** @streams: Command stream slot interfaces. */ -+ struct panthor_fw_cs_iface streams[MAX_CSGS][MAX_CS_PER_CSG]; -+}; -+ -+/** -+ * struct panthor_fw - Firmware management -+ */ -+struct panthor_fw { -+ /** @vm: MCU VM. */ -+ struct panthor_vm *vm; -+ -+ /** @sections: List of FW sections. */ -+ struct list_head sections; -+ -+ /** @shared_section: The section containing the FW interfaces. */ -+ struct panthor_fw_section *shared_section; -+ -+ /** @iface: FW interfaces. */ -+ struct panthor_fw_iface iface; -+ -+ /** @watchdog: Collection of fields relating to the FW watchdog. */ -+ struct { -+ /** @ping_work: Delayed work used to ping the FW. */ -+ struct delayed_work ping_work; -+ } watchdog; -+ -+ /** -+ * @req_waitqueue: FW request waitqueue. -+ * -+ * Everytime a request is sent to a command stream group or the global -+ * interface, the caller will first busy wait for the request to be -+ * acknowledged, and then fallback to a sleeping wait. -+ * -+ * This wait queue is here to support the sleeping wait flavor. -+ */ -+ wait_queue_head_t req_waitqueue; -+ -+ /** @booted: True is the FW is booted */ -+ bool booted; -+ -+ /** -+ * @fast_reset: True if the post_reset logic can proceed with a fast reset. -+ * -+ * A fast reset is just a reset where the driver doesn't reload the FW sections. -+ * -+ * Any time the firmware is properly suspended, a fast reset can take place. -+ * On the other hand, if the halt operation failed, the driver will reload -+ * all sections to make sure we start from a fresh state. -+ */ -+ bool fast_reset; -+ -+ /** @irq: Job irq data. */ -+ struct panthor_irq irq; -+}; -+ -+struct panthor_vm *panthor_fw_vm(struct panthor_device *ptdev) -+{ -+ return ptdev->fw->vm; -+} -+ -+/** -+ * panthor_fw_get_glb_iface() - Get the global interface -+ * @ptdev: Device. -+ * -+ * Return: The global interface. -+ */ -+struct panthor_fw_global_iface * -+panthor_fw_get_glb_iface(struct panthor_device *ptdev) -+{ -+ return &ptdev->fw->iface.global; -+} -+ -+/** -+ * panthor_fw_get_csg_iface() - Get a command stream group slot interface -+ * @ptdev: Device. -+ * @csg_slot: Index of the command stream group slot. -+ * -+ * Return: The command stream group slot interface. -+ */ -+struct panthor_fw_csg_iface * -+panthor_fw_get_csg_iface(struct panthor_device *ptdev, u32 csg_slot) -+{ -+ if (drm_WARN_ON(&ptdev->base, csg_slot >= MAX_CSGS)) -+ return NULL; -+ -+ return &ptdev->fw->iface.groups[csg_slot]; -+} -+ -+/** -+ * panthor_fw_get_cs_iface() - Get a command stream slot interface -+ * @ptdev: Device. -+ * @csg_slot: Index of the command stream group slot. -+ * @cs_slot: Index of the command stream slot. -+ * -+ * Return: The command stream slot interface. -+ */ -+struct panthor_fw_cs_iface * -+panthor_fw_get_cs_iface(struct panthor_device *ptdev, u32 csg_slot, u32 cs_slot) -+{ -+ if (drm_WARN_ON(&ptdev->base, csg_slot >= MAX_CSGS || cs_slot > MAX_CS_PER_CSG)) -+ return NULL; -+ -+ return &ptdev->fw->iface.streams[csg_slot][cs_slot]; -+} -+ -+/** -+ * panthor_fw_conv_timeout() - Convert a timeout into a cycle-count -+ * @ptdev: Device. -+ * @timeout_us: Timeout expressed in micro-seconds. -+ * -+ * The FW has two timer sources: the GPU counter or arch-timer. We need -+ * to express timeouts in term of number of cycles and specify which -+ * timer source should be used. -+ * -+ * Return: A value suitable for timeout fields in the global interface. -+ */ -+static u32 panthor_fw_conv_timeout(struct panthor_device *ptdev, u32 timeout_us) -+{ -+ bool use_cycle_counter = false; -+ u32 timer_rate = 0; -+ u64 mod_cycles; -+ -+#ifdef CONFIG_ARM_ARCH_TIMER -+ timer_rate = arch_timer_get_cntfrq(); -+#endif -+ -+ if (!timer_rate) { -+ use_cycle_counter = true; -+ timer_rate = clk_get_rate(ptdev->clks.core); -+ } -+ -+ if (drm_WARN_ON(&ptdev->base, !timer_rate)) { -+ /* We couldn't get a valid clock rate, let's just pick the -+ * maximum value so the FW still handles the core -+ * power on/off requests. -+ */ -+ return GLB_TIMER_VAL(~0) | -+ GLB_TIMER_SOURCE_GPU_COUNTER; -+ } -+ -+ mod_cycles = DIV_ROUND_UP_ULL((u64)timeout_us * timer_rate, -+ 1000000ull << 10); -+ if (drm_WARN_ON(&ptdev->base, mod_cycles > GLB_TIMER_VAL(~0))) -+ mod_cycles = GLB_TIMER_VAL(~0); -+ -+ return GLB_TIMER_VAL(mod_cycles) | -+ (use_cycle_counter ? GLB_TIMER_SOURCE_GPU_COUNTER : 0); -+} -+ -+static int panthor_fw_binary_iter_read(struct panthor_device *ptdev, -+ struct panthor_fw_binary_iter *iter, -+ void *out, size_t size) -+{ -+ size_t new_offset = iter->offset + size; -+ -+ if (new_offset > iter->size || new_offset < iter->offset) { -+ drm_err(&ptdev->base, "Firmware too small\n"); -+ return -EINVAL; -+ } -+ -+ memcpy(out, iter->data + iter->offset, size); -+ iter->offset = new_offset; -+ return 0; -+} -+ -+static int panthor_fw_binary_sub_iter_init(struct panthor_device *ptdev, -+ struct panthor_fw_binary_iter *iter, -+ struct panthor_fw_binary_iter *sub_iter, -+ size_t size) -+{ -+ size_t new_offset = iter->offset + size; -+ -+ if (new_offset > iter->size || new_offset < iter->offset) { -+ drm_err(&ptdev->base, "Firmware entry too long\n"); -+ return -EINVAL; -+ } -+ -+ sub_iter->offset = 0; -+ sub_iter->data = iter->data + iter->offset; -+ sub_iter->size = size; -+ iter->offset = new_offset; -+ return 0; -+} -+ -+static void panthor_fw_init_section_mem(struct panthor_device *ptdev, -+ struct panthor_fw_section *section) -+{ -+ bool was_mapped = !!section->mem->kmap; -+ int ret; -+ -+ if (!section->data.size && -+ !(section->flags & CSF_FW_BINARY_IFACE_ENTRY_RD_ZERO)) -+ return; -+ -+ ret = panthor_kernel_bo_vmap(section->mem); -+ if (drm_WARN_ON(&ptdev->base, ret)) -+ return; -+ -+ memcpy(section->mem->kmap, section->data.buf, section->data.size); -+ if (section->flags & CSF_FW_BINARY_IFACE_ENTRY_RD_ZERO) { -+ memset(section->mem->kmap + section->data.size, 0, -+ panthor_kernel_bo_size(section->mem) - section->data.size); -+ } -+ -+ if (!was_mapped) -+ panthor_kernel_bo_vunmap(section->mem); -+} -+ -+/** -+ * panthor_fw_alloc_queue_iface_mem() - Allocate a ring-buffer interfaces. -+ * @ptdev: Device. -+ * @input: Pointer holding the input interface on success. -+ * Should be ignored on failure. -+ * @output: Pointer holding the output interface on success. -+ * Should be ignored on failure. -+ * @input_fw_va: Pointer holding the input interface FW VA on success. -+ * Should be ignored on failure. -+ * @output_fw_va: Pointer holding the output interface FW VA on success. -+ * Should be ignored on failure. -+ * -+ * Allocates panthor_fw_ringbuf_{input,out}_iface interfaces. The input -+ * interface is at offset 0, and the output interface at offset 4096. -+ * -+ * Return: A valid pointer in case of success, an ERR_PTR() otherwise. -+ */ -+struct panthor_kernel_bo * -+panthor_fw_alloc_queue_iface_mem(struct panthor_device *ptdev, -+ struct panthor_fw_ringbuf_input_iface **input, -+ const struct panthor_fw_ringbuf_output_iface **output, -+ u32 *input_fw_va, u32 *output_fw_va) -+{ -+ struct panthor_kernel_bo *mem; -+ int ret; -+ -+ mem = panthor_kernel_bo_create(ptdev, ptdev->fw->vm, SZ_8K, -+ DRM_PANTHOR_BO_NO_MMAP, -+ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | -+ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED, -+ PANTHOR_VM_KERNEL_AUTO_VA); -+ if (IS_ERR(mem)) -+ return mem; -+ -+ ret = panthor_kernel_bo_vmap(mem); -+ if (ret) { -+ panthor_kernel_bo_destroy(panthor_fw_vm(ptdev), mem); -+ return ERR_PTR(ret); -+ } -+ -+ memset(mem->kmap, 0, panthor_kernel_bo_size(mem)); -+ *input = mem->kmap; -+ *output = mem->kmap + SZ_4K; -+ *input_fw_va = panthor_kernel_bo_gpuva(mem); -+ *output_fw_va = *input_fw_va + SZ_4K; -+ -+ return mem; -+} -+ -+/** -+ * panthor_fw_alloc_suspend_buf_mem() - Allocate a suspend buffer for a command stream group. -+ * @ptdev: Device. -+ * @size: Size of the suspend buffer. -+ * -+ * Return: A valid pointer in case of success, an ERR_PTR() otherwise. -+ */ -+struct panthor_kernel_bo * -+panthor_fw_alloc_suspend_buf_mem(struct panthor_device *ptdev, size_t size) -+{ -+ return panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), size, -+ DRM_PANTHOR_BO_NO_MMAP, -+ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC, -+ PANTHOR_VM_KERNEL_AUTO_VA); -+} -+ -+static int panthor_fw_load_section_entry(struct panthor_device *ptdev, -+ const struct firmware *fw, -+ struct panthor_fw_binary_iter *iter, -+ u32 ehdr) -+{ -+ struct panthor_fw_binary_section_entry_hdr hdr; -+ struct panthor_fw_section *section; -+ u32 section_size; -+ u32 name_len; -+ int ret; -+ -+ ret = panthor_fw_binary_iter_read(ptdev, iter, &hdr, sizeof(hdr)); -+ if (ret) -+ return ret; -+ -+ if (hdr.data.end < hdr.data.start) { -+ drm_err(&ptdev->base, "Firmware corrupted, data.end < data.start (0x%x < 0x%x)\n", -+ hdr.data.end, hdr.data.start); -+ return -EINVAL; -+ } -+ -+ if (hdr.va.end < hdr.va.start) { -+ drm_err(&ptdev->base, "Firmware corrupted, hdr.va.end < hdr.va.start (0x%x < 0x%x)\n", -+ hdr.va.end, hdr.va.start); -+ return -EINVAL; -+ } -+ -+ if (hdr.data.end > fw->size) { -+ drm_err(&ptdev->base, "Firmware corrupted, file truncated? data_end=0x%x > fw size=0x%zx\n", -+ hdr.data.end, fw->size); -+ return -EINVAL; -+ } -+ -+ if ((hdr.va.start & ~PAGE_MASK) != 0 || -+ (hdr.va.end & ~PAGE_MASK) != 0) { -+ drm_err(&ptdev->base, "Firmware corrupted, virtual addresses not page aligned: 0x%x-0x%x\n", -+ hdr.va.start, hdr.va.end); -+ return -EINVAL; -+ } -+ -+ if (hdr.flags & ~CSF_FW_BINARY_IFACE_ENTRY_RD_SUPPORTED_FLAGS) { -+ drm_err(&ptdev->base, "Firmware contains interface with unsupported flags (0x%x)\n", -+ hdr.flags); -+ return -EINVAL; -+ } -+ -+ if (hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_RD_PROT) { -+ drm_warn(&ptdev->base, -+ "Firmware protected mode entry not be supported, ignoring"); -+ return 0; -+ } -+ -+ if (hdr.va.start == CSF_MCU_SHARED_REGION_START && -+ !(hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_RD_SHARED)) { -+ drm_err(&ptdev->base, -+ "Interface at 0x%llx must be shared", CSF_MCU_SHARED_REGION_START); -+ return -EINVAL; -+ } -+ -+ name_len = iter->size - iter->offset; -+ -+ section = drmm_kzalloc(&ptdev->base, sizeof(*section), GFP_KERNEL); -+ if (!section) -+ return -ENOMEM; -+ -+ list_add_tail(§ion->node, &ptdev->fw->sections); -+ section->flags = hdr.flags; -+ section->data.size = hdr.data.end - hdr.data.start; -+ -+ if (section->data.size > 0) { -+ void *data = drmm_kmalloc(&ptdev->base, section->data.size, GFP_KERNEL); -+ -+ if (!data) -+ return -ENOMEM; -+ -+ memcpy(data, fw->data + hdr.data.start, section->data.size); -+ section->data.buf = data; -+ } -+ -+ if (name_len > 0) { -+ char *name = drmm_kmalloc(&ptdev->base, name_len + 1, GFP_KERNEL); -+ -+ if (!name) -+ return -ENOMEM; -+ -+ memcpy(name, iter->data + iter->offset, name_len); -+ name[name_len] = '\0'; -+ section->name = name; -+ } -+ -+ section_size = hdr.va.end - hdr.va.start; -+ if (section_size) { -+ u32 cache_mode = hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_MASK; -+ struct panthor_gem_object *bo; -+ u32 vm_map_flags = 0; -+ struct sg_table *sgt; -+ u64 va = hdr.va.start; -+ -+ if (!(hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_RD_WR)) -+ vm_map_flags |= DRM_PANTHOR_VM_BIND_OP_MAP_READONLY; -+ -+ if (!(hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_RD_EX)) -+ vm_map_flags |= DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC; -+ -+ /* TODO: CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_*_COHERENT are mapped to -+ * non-cacheable for now. We might want to introduce a new -+ * IOMMU_xxx flag (or abuse IOMMU_MMIO, which maps to device -+ * memory and is currently not used by our driver) for -+ * AS_MEMATTR_AARCH64_SHARED memory, so we can take benefit -+ * of IO-coherent systems. -+ */ -+ if (cache_mode != CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_CACHED) -+ vm_map_flags |= DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED; -+ -+ section->mem = panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), -+ section_size, -+ DRM_PANTHOR_BO_NO_MMAP, -+ vm_map_flags, va); -+ if (IS_ERR(section->mem)) -+ return PTR_ERR(section->mem); -+ -+ if (drm_WARN_ON(&ptdev->base, section->mem->va_node.start != hdr.va.start)) -+ return -EINVAL; -+ -+ if (section->flags & CSF_FW_BINARY_IFACE_ENTRY_RD_SHARED) { -+ ret = panthor_kernel_bo_vmap(section->mem); -+ if (ret) -+ return ret; -+ } -+ -+ panthor_fw_init_section_mem(ptdev, section); -+ -+ bo = to_panthor_bo(section->mem->obj); -+ sgt = drm_gem_shmem_get_pages_sgt(&bo->base); -+ if (IS_ERR(sgt)) -+ return PTR_ERR(sgt); -+ -+ dma_sync_sgtable_for_device(ptdev->base.dev, sgt, DMA_TO_DEVICE); -+ } -+ -+ if (hdr.va.start == CSF_MCU_SHARED_REGION_START) -+ ptdev->fw->shared_section = section; -+ -+ return 0; -+} -+ -+static void -+panthor_reload_fw_sections(struct panthor_device *ptdev, bool full_reload) -+{ -+ struct panthor_fw_section *section; -+ -+ list_for_each_entry(section, &ptdev->fw->sections, node) { -+ struct sg_table *sgt; -+ -+ if (!full_reload && !(section->flags & CSF_FW_BINARY_IFACE_ENTRY_RD_WR)) -+ continue; -+ -+ panthor_fw_init_section_mem(ptdev, section); -+ sgt = drm_gem_shmem_get_pages_sgt(&to_panthor_bo(section->mem->obj)->base); -+ if (!drm_WARN_ON(&ptdev->base, IS_ERR_OR_NULL(sgt))) -+ dma_sync_sgtable_for_device(ptdev->base.dev, sgt, DMA_TO_DEVICE); -+ } -+} -+ -+static int panthor_fw_load_entry(struct panthor_device *ptdev, -+ const struct firmware *fw, -+ struct panthor_fw_binary_iter *iter) -+{ -+ struct panthor_fw_binary_iter eiter; -+ u32 ehdr; -+ int ret; -+ -+ ret = panthor_fw_binary_iter_read(ptdev, iter, &ehdr, sizeof(ehdr)); -+ if (ret) -+ return ret; -+ -+ if ((iter->offset % sizeof(u32)) || -+ (CSF_FW_BINARY_ENTRY_SIZE(ehdr) % sizeof(u32))) { -+ drm_err(&ptdev->base, "Firmware entry isn't 32 bit aligned, offset=0x%x size=0x%x\n", -+ (u32)(iter->offset - sizeof(u32)), CSF_FW_BINARY_ENTRY_SIZE(ehdr)); -+ return -EINVAL; -+ } -+ -+ if (panthor_fw_binary_sub_iter_init(ptdev, iter, &eiter, -+ CSF_FW_BINARY_ENTRY_SIZE(ehdr) - sizeof(ehdr))) -+ return -EINVAL; -+ -+ switch (CSF_FW_BINARY_ENTRY_TYPE(ehdr)) { -+ case CSF_FW_BINARY_ENTRY_TYPE_IFACE: -+ return panthor_fw_load_section_entry(ptdev, fw, &eiter, ehdr); -+ -+ /* FIXME: handle those entry types? */ -+ case CSF_FW_BINARY_ENTRY_TYPE_CONFIG: -+ case CSF_FW_BINARY_ENTRY_TYPE_FUTF_TEST: -+ case CSF_FW_BINARY_ENTRY_TYPE_TRACE_BUFFER: -+ case CSF_FW_BINARY_ENTRY_TYPE_TIMELINE_METADATA: -+ return 0; -+ default: -+ break; -+ } -+ -+ if (ehdr & CSF_FW_BINARY_ENTRY_OPTIONAL) -+ return 0; -+ -+ drm_err(&ptdev->base, -+ "Unsupported non-optional entry type %u in firmware\n", -+ CSF_FW_BINARY_ENTRY_TYPE(ehdr)); -+ return -EINVAL; -+} -+ -+static int panthor_fw_load(struct panthor_device *ptdev) -+{ -+ const struct firmware *fw = NULL; -+ struct panthor_fw_binary_iter iter = {}; -+ struct panthor_fw_binary_hdr hdr; -+ char fw_path[128]; -+ int ret; -+ -+ snprintf(fw_path, sizeof(fw_path), "arm/mali/arch%d.%d/%s", -+ (u32)GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id), -+ (u32)GPU_ARCH_MINOR(ptdev->gpu_info.gpu_id), -+ CSF_FW_NAME); -+ -+ ret = request_firmware(&fw, fw_path, ptdev->base.dev); -+ if (ret) { -+ drm_err(&ptdev->base, "Failed to load firmware image '%s'\n", -+ CSF_FW_NAME); -+ return ret; -+ } -+ -+ iter.data = fw->data; -+ iter.size = fw->size; -+ ret = panthor_fw_binary_iter_read(ptdev, &iter, &hdr, sizeof(hdr)); -+ if (ret) -+ goto out; -+ -+ if (hdr.magic != CSF_FW_BINARY_HEADER_MAGIC) { -+ ret = -EINVAL; -+ drm_err(&ptdev->base, "Invalid firmware magic\n"); -+ goto out; -+ } -+ -+ if (hdr.major != CSF_FW_BINARY_HEADER_MAJOR_MAX) { -+ ret = -EINVAL; -+ drm_err(&ptdev->base, "Unsupported firmware binary header version %d.%d (expected %d.x)\n", -+ hdr.major, hdr.minor, CSF_FW_BINARY_HEADER_MAJOR_MAX); -+ goto out; -+ } -+ -+ if (hdr.size > iter.size) { -+ drm_err(&ptdev->base, "Firmware image is truncated\n"); -+ goto out; -+ } -+ -+ iter.size = hdr.size; -+ -+ while (iter.offset < hdr.size) { -+ ret = panthor_fw_load_entry(ptdev, fw, &iter); -+ if (ret) -+ goto out; -+ } -+ -+ if (!ptdev->fw->shared_section) { -+ drm_err(&ptdev->base, "Shared interface region not found\n"); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+out: -+ release_firmware(fw); -+ return ret; -+} -+ -+/** -+ * iface_fw_to_cpu_addr() - Turn an MCU address into a CPU address -+ * @ptdev: Device. -+ * @mcu_va: MCU address. -+ * -+ * Return: NULL if the address is not part of the shared section, non-NULL otherwise. -+ */ -+static void *iface_fw_to_cpu_addr(struct panthor_device *ptdev, u32 mcu_va) -+{ -+ u64 shared_mem_start = panthor_kernel_bo_gpuva(ptdev->fw->shared_section->mem); -+ u64 shared_mem_end = shared_mem_start + -+ panthor_kernel_bo_size(ptdev->fw->shared_section->mem); -+ if (mcu_va < shared_mem_start || mcu_va >= shared_mem_end) -+ return NULL; -+ -+ return ptdev->fw->shared_section->mem->kmap + (mcu_va - shared_mem_start); -+} -+ -+static int panthor_init_cs_iface(struct panthor_device *ptdev, -+ unsigned int csg_idx, unsigned int cs_idx) -+{ -+ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); -+ struct panthor_fw_csg_iface *csg_iface = panthor_fw_get_csg_iface(ptdev, csg_idx); -+ struct panthor_fw_cs_iface *cs_iface = &ptdev->fw->iface.streams[csg_idx][cs_idx]; -+ u64 shared_section_sz = panthor_kernel_bo_size(ptdev->fw->shared_section->mem); -+ u32 iface_offset = CSF_GROUP_CONTROL_OFFSET + -+ (csg_idx * glb_iface->control->group_stride) + -+ CSF_STREAM_CONTROL_OFFSET + -+ (cs_idx * csg_iface->control->stream_stride); -+ struct panthor_fw_cs_iface *first_cs_iface = -+ panthor_fw_get_cs_iface(ptdev, 0, 0); -+ -+ if (iface_offset + sizeof(*cs_iface) >= shared_section_sz) -+ return -EINVAL; -+ -+ spin_lock_init(&cs_iface->lock); -+ cs_iface->control = ptdev->fw->shared_section->mem->kmap + iface_offset; -+ cs_iface->input = iface_fw_to_cpu_addr(ptdev, cs_iface->control->input_va); -+ cs_iface->output = iface_fw_to_cpu_addr(ptdev, cs_iface->control->output_va); -+ -+ if (!cs_iface->input || !cs_iface->output) { -+ drm_err(&ptdev->base, "Invalid stream control interface input/output VA"); -+ return -EINVAL; -+ } -+ -+ if (cs_iface != first_cs_iface) { -+ if (cs_iface->control->features != first_cs_iface->control->features) { -+ drm_err(&ptdev->base, "Expecting identical CS slots"); -+ return -EINVAL; -+ } -+ } else { -+ u32 reg_count = CS_FEATURES_WORK_REGS(cs_iface->control->features); -+ -+ ptdev->csif_info.cs_reg_count = reg_count; -+ ptdev->csif_info.unpreserved_cs_reg_count = CSF_UNPRESERVED_REG_COUNT; -+ } -+ -+ return 0; -+} -+ -+static bool compare_csg(const struct panthor_fw_csg_control_iface *a, -+ const struct panthor_fw_csg_control_iface *b) -+{ -+ if (a->features != b->features) -+ return false; -+ if (a->suspend_size != b->suspend_size) -+ return false; -+ if (a->protm_suspend_size != b->protm_suspend_size) -+ return false; -+ if (a->stream_num != b->stream_num) -+ return false; -+ return true; -+} -+ -+static int panthor_init_csg_iface(struct panthor_device *ptdev, -+ unsigned int csg_idx) -+{ -+ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); -+ struct panthor_fw_csg_iface *csg_iface = &ptdev->fw->iface.groups[csg_idx]; -+ u64 shared_section_sz = panthor_kernel_bo_size(ptdev->fw->shared_section->mem); -+ u32 iface_offset = CSF_GROUP_CONTROL_OFFSET + (csg_idx * glb_iface->control->group_stride); -+ unsigned int i; -+ -+ if (iface_offset + sizeof(*csg_iface) >= shared_section_sz) -+ return -EINVAL; -+ -+ spin_lock_init(&csg_iface->lock); -+ csg_iface->control = ptdev->fw->shared_section->mem->kmap + iface_offset; -+ csg_iface->input = iface_fw_to_cpu_addr(ptdev, csg_iface->control->input_va); -+ csg_iface->output = iface_fw_to_cpu_addr(ptdev, csg_iface->control->output_va); -+ -+ if (csg_iface->control->stream_num < MIN_CS_PER_CSG || -+ csg_iface->control->stream_num > MAX_CS_PER_CSG) -+ return -EINVAL; -+ -+ if (!csg_iface->input || !csg_iface->output) { -+ drm_err(&ptdev->base, "Invalid group control interface input/output VA"); -+ return -EINVAL; -+ } -+ -+ if (csg_idx > 0) { -+ struct panthor_fw_csg_iface *first_csg_iface = -+ panthor_fw_get_csg_iface(ptdev, 0); -+ -+ if (!compare_csg(first_csg_iface->control, csg_iface->control)) { -+ drm_err(&ptdev->base, "Expecting identical CSG slots"); -+ return -EINVAL; -+ } -+ } -+ -+ for (i = 0; i < csg_iface->control->stream_num; i++) { -+ int ret = panthor_init_cs_iface(ptdev, csg_idx, i); -+ -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static u32 panthor_get_instr_features(struct panthor_device *ptdev) -+{ -+ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); -+ -+ if (glb_iface->control->version < CSF_IFACE_VERSION(1, 1, 0)) -+ return 0; -+ -+ return glb_iface->control->instr_features; -+} -+ -+static int panthor_fw_init_ifaces(struct panthor_device *ptdev) -+{ -+ struct panthor_fw_global_iface *glb_iface = &ptdev->fw->iface.global; -+ unsigned int i; -+ -+ if (!ptdev->fw->shared_section->mem->kmap) -+ return -EINVAL; -+ -+ spin_lock_init(&glb_iface->lock); -+ glb_iface->control = ptdev->fw->shared_section->mem->kmap; -+ -+ if (!glb_iface->control->version) { -+ drm_err(&ptdev->base, "Firmware version is 0. Firmware may have failed to boot"); -+ return -EINVAL; -+ } -+ -+ glb_iface->input = iface_fw_to_cpu_addr(ptdev, glb_iface->control->input_va); -+ glb_iface->output = iface_fw_to_cpu_addr(ptdev, glb_iface->control->output_va); -+ if (!glb_iface->input || !glb_iface->output) { -+ drm_err(&ptdev->base, "Invalid global control interface input/output VA"); -+ return -EINVAL; -+ } -+ -+ if (glb_iface->control->group_num > MAX_CSGS || -+ glb_iface->control->group_num < MIN_CSGS) { -+ drm_err(&ptdev->base, "Invalid number of control groups"); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < glb_iface->control->group_num; i++) { -+ int ret = panthor_init_csg_iface(ptdev, i); -+ -+ if (ret) -+ return ret; -+ } -+ -+ drm_info(&ptdev->base, "CSF FW v%d.%d.%d, Features %#x Instrumentation features %#x", -+ CSF_IFACE_VERSION_MAJOR(glb_iface->control->version), -+ CSF_IFACE_VERSION_MINOR(glb_iface->control->version), -+ CSF_IFACE_VERSION_PATCH(glb_iface->control->version), -+ glb_iface->control->features, -+ panthor_get_instr_features(ptdev)); -+ return 0; -+} -+ -+static void panthor_fw_init_global_iface(struct panthor_device *ptdev) -+{ -+ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); -+ -+ /* Enable all cores. */ -+ glb_iface->input->core_en_mask = ptdev->gpu_info.shader_present; -+ -+ /* Setup timers. */ -+ glb_iface->input->poweroff_timer = panthor_fw_conv_timeout(ptdev, PWROFF_HYSTERESIS_US); -+ glb_iface->input->progress_timer = PROGRESS_TIMEOUT_CYCLES >> PROGRESS_TIMEOUT_SCALE_SHIFT; -+ glb_iface->input->idle_timer = panthor_fw_conv_timeout(ptdev, IDLE_HYSTERESIS_US); -+ -+ /* Enable interrupts we care about. */ -+ glb_iface->input->ack_irq_mask = GLB_CFG_ALLOC_EN | -+ GLB_PING | -+ GLB_CFG_PROGRESS_TIMER | -+ GLB_CFG_POWEROFF_TIMER | -+ GLB_IDLE_EN | -+ GLB_IDLE; -+ -+ panthor_fw_update_reqs(glb_iface, req, GLB_IDLE_EN, GLB_IDLE_EN); -+ panthor_fw_toggle_reqs(glb_iface, req, ack, -+ GLB_CFG_ALLOC_EN | -+ GLB_CFG_POWEROFF_TIMER | -+ GLB_CFG_PROGRESS_TIMER); -+ -+ gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1); -+ -+ /* Kick the watchdog. */ -+ mod_delayed_work(ptdev->reset.wq, &ptdev->fw->watchdog.ping_work, -+ msecs_to_jiffies(PING_INTERVAL_MS)); -+} -+ -+static void panthor_job_irq_handler(struct panthor_device *ptdev, u32 status) -+{ -+ if (!ptdev->fw->booted && (status & JOB_INT_GLOBAL_IF)) -+ ptdev->fw->booted = true; -+ -+ wake_up_all(&ptdev->fw->req_waitqueue); -+ -+ /* If the FW is not booted, don't process IRQs, just flag the FW as booted. */ -+ if (!ptdev->fw->booted) -+ return; -+ -+ panthor_sched_report_fw_events(ptdev, status); -+} -+PANTHOR_IRQ_HANDLER(job, JOB, panthor_job_irq_handler); -+ -+static int panthor_fw_start(struct panthor_device *ptdev) -+{ -+ bool timedout = false; -+ -+ ptdev->fw->booted = false; -+ panthor_job_irq_resume(&ptdev->fw->irq, ~0); -+ gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_AUTO); -+ -+ if (!wait_event_timeout(ptdev->fw->req_waitqueue, -+ ptdev->fw->booted, -+ msecs_to_jiffies(1000))) { -+ if (!ptdev->fw->booted && -+ !(gpu_read(ptdev, JOB_INT_STAT) & JOB_INT_GLOBAL_IF)) -+ timedout = true; -+ } -+ -+ if (timedout) { -+ static const char * const status_str[] = { -+ [MCU_STATUS_DISABLED] = "disabled", -+ [MCU_STATUS_ENABLED] = "enabled", -+ [MCU_STATUS_HALT] = "halt", -+ [MCU_STATUS_FATAL] = "fatal", -+ }; -+ u32 status = gpu_read(ptdev, MCU_STATUS); -+ -+ drm_err(&ptdev->base, "Failed to boot MCU (status=%s)", -+ status < ARRAY_SIZE(status_str) ? status_str[status] : "unknown"); -+ return -ETIMEDOUT; -+ } -+ -+ return 0; -+} -+ -+static void panthor_fw_stop(struct panthor_device *ptdev) -+{ -+ u32 status; -+ -+ gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_DISABLE); -+ if (readl_poll_timeout(ptdev->iomem + MCU_STATUS, status, -+ status == MCU_STATUS_DISABLED, 10, 100000)) -+ drm_err(&ptdev->base, "Failed to stop MCU"); -+} -+ -+/** -+ * panthor_fw_pre_reset() - Call before a reset. -+ * @ptdev: Device. -+ * @on_hang: true if the reset was triggered on a GPU hang. -+ * -+ * If the reset is not triggered on a hang, we try to gracefully halt the -+ * MCU, so we can do a fast-reset when panthor_fw_post_reset() is called. -+ */ -+void panthor_fw_pre_reset(struct panthor_device *ptdev, bool on_hang) -+{ -+ /* Make sure we won't be woken up by a ping. */ -+ cancel_delayed_work_sync(&ptdev->fw->watchdog.ping_work); -+ -+ ptdev->fw->fast_reset = false; -+ -+ if (!on_hang) { -+ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); -+ u32 status; -+ -+ panthor_fw_update_reqs(glb_iface, req, GLB_HALT, GLB_HALT); -+ gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1); -+ if (!readl_poll_timeout(ptdev->iomem + MCU_STATUS, status, -+ status == MCU_STATUS_HALT, 10, 100000) && -+ glb_iface->output->halt_status == PANTHOR_FW_HALT_OK) { -+ ptdev->fw->fast_reset = true; -+ } else { -+ drm_warn(&ptdev->base, "Failed to cleanly suspend MCU"); -+ } -+ -+ /* The FW detects 0 -> 1 transitions. Make sure we reset -+ * the HALT bit before the FW is rebooted. -+ */ -+ panthor_fw_update_reqs(glb_iface, req, 0, GLB_HALT); -+ } -+ -+ panthor_job_irq_suspend(&ptdev->fw->irq); -+} -+ -+/** -+ * panthor_fw_post_reset() - Call after a reset. -+ * @ptdev: Device. -+ * -+ * Start the FW. If this is not a fast reset, all FW sections are reloaded to -+ * make sure we can recover from a memory corruption. -+ */ -+int panthor_fw_post_reset(struct panthor_device *ptdev) -+{ -+ int ret; -+ -+ /* Make the MCU VM active. */ -+ ret = panthor_vm_active(ptdev->fw->vm); -+ if (ret) -+ return ret; -+ -+ /* If this is a fast reset, try to start the MCU without reloading -+ * the FW sections. If it fails, go for a full reset. -+ */ -+ if (ptdev->fw->fast_reset) { -+ ret = panthor_fw_start(ptdev); -+ if (!ret) -+ goto out; -+ -+ /* Force a disable, so we get a fresh boot on the next -+ * panthor_fw_start() call. -+ */ -+ gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_DISABLE); -+ drm_err(&ptdev->base, "FW fast reset failed, trying a slow reset"); -+ } -+ -+ /* Reload all sections, including RO ones. We're not supposed -+ * to end up here anyway, let's just assume the overhead of -+ * reloading everything is acceptable. -+ */ -+ panthor_reload_fw_sections(ptdev, true); -+ -+ ret = panthor_fw_start(ptdev); -+ if (ret) { -+ drm_err(&ptdev->base, "FW slow reset failed"); -+ return ret; -+ } -+ -+out: -+ /* We must re-initialize the global interface even on fast-reset. */ -+ panthor_fw_init_global_iface(ptdev); -+ return 0; -+} -+ -+/** -+ * panthor_fw_unplug() - Called when the device is unplugged. -+ * @ptdev: Device. -+ * -+ * This function must make sure all pending operations are flushed before -+ * will release device resources, thus preventing any interaction with -+ * the HW. -+ * -+ * If there is still FW-related work running after this function returns, -+ * they must use drm_dev_{enter,exit}() and skip any HW access when -+ * drm_dev_enter() returns false. -+ */ -+void panthor_fw_unplug(struct panthor_device *ptdev) -+{ -+ struct panthor_fw_section *section; -+ -+ cancel_delayed_work_sync(&ptdev->fw->watchdog.ping_work); -+ -+ /* Make sure the IRQ handler can be called after that point. */ -+ if (ptdev->fw->irq.irq) -+ panthor_job_irq_suspend(&ptdev->fw->irq); -+ -+ panthor_fw_stop(ptdev); -+ -+ list_for_each_entry(section, &ptdev->fw->sections, node) -+ panthor_kernel_bo_destroy(panthor_fw_vm(ptdev), section->mem); -+ -+ /* We intentionally don't call panthor_vm_idle() and let -+ * panthor_mmu_unplug() release the AS we acquired with -+ * panthor_vm_active() so we don't have to track the VM active/idle -+ * state to keep the active_refcnt balanced. -+ */ -+ panthor_vm_put(ptdev->fw->vm); -+ -+ panthor_gpu_power_off(ptdev, L2, ptdev->gpu_info.l2_present, 20000); -+} -+ -+/** -+ * panthor_fw_wait_acks() - Wait for requests to be acknowledged by the FW. -+ * @req_ptr: Pointer to the req register. -+ * @ack_ptr: Pointer to the ack register. -+ * @wq: Wait queue to use for the sleeping wait. -+ * @req_mask: Mask of requests to wait for. -+ * @acked: Pointer to field that's updated with the acked requests. -+ * If the function returns 0, *acked == req_mask. -+ * @timeout_ms: Timeout expressed in milliseconds. -+ * -+ * Return: 0 on success, -ETIMEDOUT otherwise. -+ */ -+static int panthor_fw_wait_acks(const u32 *req_ptr, const u32 *ack_ptr, -+ wait_queue_head_t *wq, -+ u32 req_mask, u32 *acked, -+ u32 timeout_ms) -+{ -+ u32 ack, req = READ_ONCE(*req_ptr) & req_mask; -+ int ret; -+ -+ /* Busy wait for a few µsecs before falling back to a sleeping wait. */ -+ *acked = req_mask; -+ ret = read_poll_timeout_atomic(READ_ONCE, ack, -+ (ack & req_mask) == req, -+ 0, 10, 0, -+ *ack_ptr); -+ if (!ret) -+ return 0; -+ -+ if (wait_event_timeout(*wq, (READ_ONCE(*ack_ptr) & req_mask) == req, -+ msecs_to_jiffies(timeout_ms))) -+ return 0; -+ -+ /* Check one last time, in case we were not woken up for some reason. */ -+ ack = READ_ONCE(*ack_ptr); -+ if ((ack & req_mask) == req) -+ return 0; -+ -+ *acked = ~(req ^ ack) & req_mask; -+ return -ETIMEDOUT; -+} -+ -+/** -+ * panthor_fw_glb_wait_acks() - Wait for global requests to be acknowledged. -+ * @ptdev: Device. -+ * @req_mask: Mask of requests to wait for. -+ * @acked: Pointer to field that's updated with the acked requests. -+ * If the function returns 0, *acked == req_mask. -+ * @timeout_ms: Timeout expressed in milliseconds. -+ * -+ * Return: 0 on success, -ETIMEDOUT otherwise. -+ */ -+int panthor_fw_glb_wait_acks(struct panthor_device *ptdev, -+ u32 req_mask, u32 *acked, -+ u32 timeout_ms) -+{ -+ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); -+ -+ /* GLB_HALT doesn't get acked through the FW interface. */ -+ if (drm_WARN_ON(&ptdev->base, req_mask & (~GLB_REQ_MASK | GLB_HALT))) -+ return -EINVAL; -+ -+ return panthor_fw_wait_acks(&glb_iface->input->req, -+ &glb_iface->output->ack, -+ &ptdev->fw->req_waitqueue, -+ req_mask, acked, timeout_ms); -+} -+ -+/** -+ * panthor_fw_csg_wait_acks() - Wait for command stream group requests to be acknowledged. -+ * @ptdev: Device. -+ * @csg_slot: CSG slot ID. -+ * @req_mask: Mask of requests to wait for. -+ * @acked: Pointer to field that's updated with the acked requests. -+ * If the function returns 0, *acked == req_mask. -+ * @timeout_ms: Timeout expressed in milliseconds. -+ * -+ * Return: 0 on success, -ETIMEDOUT otherwise. -+ */ -+int panthor_fw_csg_wait_acks(struct panthor_device *ptdev, u32 csg_slot, -+ u32 req_mask, u32 *acked, u32 timeout_ms) -+{ -+ struct panthor_fw_csg_iface *csg_iface = panthor_fw_get_csg_iface(ptdev, csg_slot); -+ int ret; -+ -+ if (drm_WARN_ON(&ptdev->base, req_mask & ~CSG_REQ_MASK)) -+ return -EINVAL; -+ -+ ret = panthor_fw_wait_acks(&csg_iface->input->req, -+ &csg_iface->output->ack, -+ &ptdev->fw->req_waitqueue, -+ req_mask, acked, timeout_ms); -+ -+ /* -+ * Check that all bits in the state field were updated, if any mismatch -+ * then clear all bits in the state field. This allows code to do -+ * (acked & CSG_STATE_MASK) and get the right value. -+ */ -+ -+ if ((*acked & CSG_STATE_MASK) != CSG_STATE_MASK) -+ *acked &= ~CSG_STATE_MASK; -+ -+ return ret; -+} -+ -+/** -+ * panthor_fw_ring_csg_doorbells() - Ring command stream group doorbells. -+ * @ptdev: Device. -+ * @csg_mask: Bitmask encoding the command stream group doorbells to ring. -+ * -+ * This function is toggling bits in the doorbell_req and ringing the -+ * global doorbell. It doesn't require a user doorbell to be attached to -+ * the group. -+ */ -+void panthor_fw_ring_csg_doorbells(struct panthor_device *ptdev, u32 csg_mask) -+{ -+ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); -+ -+ panthor_fw_toggle_reqs(glb_iface, doorbell_req, doorbell_ack, csg_mask); -+ gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1); -+} -+ -+static void panthor_fw_ping_work(struct work_struct *work) -+{ -+ struct panthor_fw *fw = container_of(work, struct panthor_fw, watchdog.ping_work.work); -+ struct panthor_device *ptdev = fw->irq.ptdev; -+ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); -+ u32 acked; -+ int ret; -+ -+ if (panthor_device_reset_is_pending(ptdev)) -+ return; -+ -+ panthor_fw_toggle_reqs(glb_iface, req, ack, GLB_PING); -+ gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1); -+ -+ ret = panthor_fw_glb_wait_acks(ptdev, GLB_PING, &acked, 100); -+ if (ret) { -+ panthor_device_schedule_reset(ptdev); -+ drm_err(&ptdev->base, "FW ping timeout, scheduling a reset"); -+ } else { -+ mod_delayed_work(ptdev->reset.wq, &fw->watchdog.ping_work, -+ msecs_to_jiffies(PING_INTERVAL_MS)); -+ } -+} -+ -+/** -+ * panthor_fw_init() - Initialize FW related data. -+ * @ptdev: Device. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+int panthor_fw_init(struct panthor_device *ptdev) -+{ -+ struct panthor_fw *fw; -+ int ret, irq; -+ -+ fw = drmm_kzalloc(&ptdev->base, sizeof(*fw), GFP_KERNEL); -+ if (!fw) -+ return -ENOMEM; -+ -+ ptdev->fw = fw; -+ init_waitqueue_head(&fw->req_waitqueue); -+ INIT_LIST_HEAD(&fw->sections); -+ INIT_DELAYED_WORK(&fw->watchdog.ping_work, panthor_fw_ping_work); -+ -+ irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "job"); -+ if (irq <= 0) -+ return -ENODEV; -+ -+ ret = panthor_request_job_irq(ptdev, &fw->irq, irq, 0); -+ if (ret) { -+ drm_err(&ptdev->base, "failed to request job irq"); -+ return ret; -+ } -+ -+ ret = panthor_gpu_l2_power_on(ptdev); -+ if (ret) -+ return ret; -+ -+ fw->vm = panthor_vm_create(ptdev, true, -+ 0, SZ_4G, -+ CSF_MCU_SHARED_REGION_START, -+ CSF_MCU_SHARED_REGION_SIZE); -+ if (IS_ERR(fw->vm)) { -+ ret = PTR_ERR(fw->vm); -+ fw->vm = NULL; -+ goto err_unplug_fw; -+ } -+ -+ ret = panthor_fw_load(ptdev); -+ if (ret) -+ goto err_unplug_fw; -+ -+ ret = panthor_vm_active(fw->vm); -+ if (ret) -+ goto err_unplug_fw; -+ -+ ret = panthor_fw_start(ptdev); -+ if (ret) -+ goto err_unplug_fw; -+ -+ ret = panthor_fw_init_ifaces(ptdev); -+ if (ret) -+ goto err_unplug_fw; -+ -+ panthor_fw_init_global_iface(ptdev); -+ return 0; -+ -+err_unplug_fw: -+ panthor_fw_unplug(ptdev); -+ return ret; -+} -+ -+MODULE_FIRMWARE("arm/mali/arch10.8/mali_csffw.bin"); -diff --git a/drivers/gpu/drm/panthor/panthor_fw.h b/drivers/gpu/drm/panthor/panthor_fw.h -new file mode 100644 -index 000000000000..22448abde992 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_fw.h -@@ -0,0 +1,503 @@ -+/* SPDX-License-Identifier: GPL-2.0 or MIT */ -+/* Copyright 2023 Collabora ltd. */ -+ -+#ifndef __PANTHOR_MCU_H__ -+#define __PANTHOR_MCU_H__ -+ -+#include -+ -+struct panthor_device; -+struct panthor_kernel_bo; -+ -+#define MAX_CSGS 31 -+#define MAX_CS_PER_CSG 32 -+ -+struct panthor_fw_ringbuf_input_iface { -+ u64 insert; -+ u64 extract; -+}; -+ -+struct panthor_fw_ringbuf_output_iface { -+ u64 extract; -+ u32 active; -+}; -+ -+struct panthor_fw_cs_control_iface { -+#define CS_FEATURES_WORK_REGS(x) (((x) & GENMASK(7, 0)) + 1) -+#define CS_FEATURES_SCOREBOARDS(x) (((x) & GENMASK(15, 8)) >> 8) -+#define CS_FEATURES_COMPUTE BIT(16) -+#define CS_FEATURES_FRAGMENT BIT(17) -+#define CS_FEATURES_TILER BIT(18) -+ u32 features; -+ u32 input_va; -+ u32 output_va; -+}; -+ -+struct panthor_fw_cs_input_iface { -+#define CS_STATE_MASK GENMASK(2, 0) -+#define CS_STATE_STOP 0 -+#define CS_STATE_START 1 -+#define CS_EXTRACT_EVENT BIT(4) -+#define CS_IDLE_SYNC_WAIT BIT(8) -+#define CS_IDLE_PROTM_PENDING BIT(9) -+#define CS_IDLE_EMPTY BIT(10) -+#define CS_IDLE_RESOURCE_REQ BIT(11) -+#define CS_TILER_OOM BIT(26) -+#define CS_PROTM_PENDING BIT(27) -+#define CS_FATAL BIT(30) -+#define CS_FAULT BIT(31) -+#define CS_REQ_MASK (CS_STATE_MASK | \ -+ CS_EXTRACT_EVENT | \ -+ CS_IDLE_SYNC_WAIT | \ -+ CS_IDLE_PROTM_PENDING | \ -+ CS_IDLE_EMPTY | \ -+ CS_IDLE_RESOURCE_REQ) -+#define CS_EVT_MASK (CS_TILER_OOM | \ -+ CS_PROTM_PENDING | \ -+ CS_FATAL | \ -+ CS_FAULT) -+ u32 req; -+ -+#define CS_CONFIG_PRIORITY(x) ((x) & GENMASK(3, 0)) -+#define CS_CONFIG_DOORBELL(x) (((x) << 8) & GENMASK(15, 8)) -+ u32 config; -+ u32 reserved1; -+ u32 ack_irq_mask; -+ u64 ringbuf_base; -+ u32 ringbuf_size; -+ u32 reserved2; -+ u64 heap_start; -+ u64 heap_end; -+ u64 ringbuf_input; -+ u64 ringbuf_output; -+ u32 instr_config; -+ u32 instrbuf_size; -+ u64 instrbuf_base; -+ u64 instrbuf_offset_ptr; -+}; -+ -+struct panthor_fw_cs_output_iface { -+ u32 ack; -+ u32 reserved1[15]; -+ u64 status_cmd_ptr; -+ -+#define CS_STATUS_WAIT_SB_MASK GENMASK(15, 0) -+#define CS_STATUS_WAIT_SB_SRC_MASK GENMASK(19, 16) -+#define CS_STATUS_WAIT_SB_SRC_NONE (0 << 16) -+#define CS_STATUS_WAIT_SB_SRC_WAIT (8 << 16) -+#define CS_STATUS_WAIT_SYNC_COND_LE (0 << 24) -+#define CS_STATUS_WAIT_SYNC_COND_GT (1 << 24) -+#define CS_STATUS_WAIT_SYNC_COND_MASK GENMASK(27, 24) -+#define CS_STATUS_WAIT_PROGRESS BIT(28) -+#define CS_STATUS_WAIT_PROTM BIT(29) -+#define CS_STATUS_WAIT_SYNC_64B BIT(30) -+#define CS_STATUS_WAIT_SYNC BIT(31) -+ u32 status_wait; -+ u32 status_req_resource; -+ u64 status_wait_sync_ptr; -+ u32 status_wait_sync_value; -+ u32 status_scoreboards; -+ -+#define CS_STATUS_BLOCKED_REASON_UNBLOCKED 0 -+#define CS_STATUS_BLOCKED_REASON_SB_WAIT 1 -+#define CS_STATUS_BLOCKED_REASON_PROGRESS_WAIT 2 -+#define CS_STATUS_BLOCKED_REASON_SYNC_WAIT 3 -+#define CS_STATUS_BLOCKED_REASON_DEFERRED 5 -+#define CS_STATUS_BLOCKED_REASON_RES 6 -+#define CS_STATUS_BLOCKED_REASON_FLUSH 7 -+#define CS_STATUS_BLOCKED_REASON_MASK GENMASK(3, 0) -+ u32 status_blocked_reason; -+ u32 status_wait_sync_value_hi; -+ u32 reserved2[6]; -+ -+#define CS_EXCEPTION_TYPE(x) ((x) & GENMASK(7, 0)) -+#define CS_EXCEPTION_DATA(x) (((x) >> 8) & GENMASK(23, 0)) -+ u32 fault; -+ u32 fatal; -+ u64 fault_info; -+ u64 fatal_info; -+ u32 reserved3[10]; -+ u32 heap_vt_start; -+ u32 heap_vt_end; -+ u32 reserved4; -+ u32 heap_frag_end; -+ u64 heap_address; -+}; -+ -+struct panthor_fw_csg_control_iface { -+ u32 features; -+ u32 input_va; -+ u32 output_va; -+ u32 suspend_size; -+ u32 protm_suspend_size; -+ u32 stream_num; -+ u32 stream_stride; -+}; -+ -+struct panthor_fw_csg_input_iface { -+#define CSG_STATE_MASK GENMASK(2, 0) -+#define CSG_STATE_TERMINATE 0 -+#define CSG_STATE_START 1 -+#define CSG_STATE_SUSPEND 2 -+#define CSG_STATE_RESUME 3 -+#define CSG_ENDPOINT_CONFIG BIT(4) -+#define CSG_STATUS_UPDATE BIT(5) -+#define CSG_SYNC_UPDATE BIT(28) -+#define CSG_IDLE BIT(29) -+#define CSG_DOORBELL BIT(30) -+#define CSG_PROGRESS_TIMER_EVENT BIT(31) -+#define CSG_REQ_MASK (CSG_STATE_MASK | \ -+ CSG_ENDPOINT_CONFIG | \ -+ CSG_STATUS_UPDATE) -+#define CSG_EVT_MASK (CSG_SYNC_UPDATE | \ -+ CSG_IDLE | \ -+ CSG_PROGRESS_TIMER_EVENT) -+ u32 req; -+ u32 ack_irq_mask; -+ -+ u32 doorbell_req; -+ u32 cs_irq_ack; -+ u32 reserved1[4]; -+ u64 allow_compute; -+ u64 allow_fragment; -+ u32 allow_other; -+ -+#define CSG_EP_REQ_COMPUTE(x) ((x) & GENMASK(7, 0)) -+#define CSG_EP_REQ_FRAGMENT(x) (((x) << 8) & GENMASK(15, 8)) -+#define CSG_EP_REQ_TILER(x) (((x) << 16) & GENMASK(19, 16)) -+#define CSG_EP_REQ_EXCL_COMPUTE BIT(20) -+#define CSG_EP_REQ_EXCL_FRAGMENT BIT(21) -+#define CSG_EP_REQ_PRIORITY(x) (((x) << 28) & GENMASK(31, 28)) -+#define CSG_EP_REQ_PRIORITY_MASK GENMASK(31, 28) -+ u32 endpoint_req; -+ u32 reserved2[2]; -+ u64 suspend_buf; -+ u64 protm_suspend_buf; -+ u32 config; -+ u32 iter_trace_config; -+}; -+ -+struct panthor_fw_csg_output_iface { -+ u32 ack; -+ u32 reserved1; -+ u32 doorbell_ack; -+ u32 cs_irq_req; -+ u32 status_endpoint_current; -+ u32 status_endpoint_req; -+ -+#define CSG_STATUS_STATE_IS_IDLE BIT(0) -+ u32 status_state; -+ u32 resource_dep; -+}; -+ -+struct panthor_fw_global_control_iface { -+ u32 version; -+ u32 features; -+ u32 input_va; -+ u32 output_va; -+ u32 group_num; -+ u32 group_stride; -+ u32 perfcnt_size; -+ u32 instr_features; -+}; -+ -+struct panthor_fw_global_input_iface { -+#define GLB_HALT BIT(0) -+#define GLB_CFG_PROGRESS_TIMER BIT(1) -+#define GLB_CFG_ALLOC_EN BIT(2) -+#define GLB_CFG_POWEROFF_TIMER BIT(3) -+#define GLB_PROTM_ENTER BIT(4) -+#define GLB_PERFCNT_EN BIT(5) -+#define GLB_PERFCNT_SAMPLE BIT(6) -+#define GLB_COUNTER_EN BIT(7) -+#define GLB_PING BIT(8) -+#define GLB_FWCFG_UPDATE BIT(9) -+#define GLB_IDLE_EN BIT(10) -+#define GLB_SLEEP BIT(12) -+#define GLB_INACTIVE_COMPUTE BIT(20) -+#define GLB_INACTIVE_FRAGMENT BIT(21) -+#define GLB_INACTIVE_TILER BIT(22) -+#define GLB_PROTM_EXIT BIT(23) -+#define GLB_PERFCNT_THRESHOLD BIT(24) -+#define GLB_PERFCNT_OVERFLOW BIT(25) -+#define GLB_IDLE BIT(26) -+#define GLB_DBG_CSF BIT(30) -+#define GLB_DBG_HOST BIT(31) -+#define GLB_REQ_MASK GENMASK(10, 0) -+#define GLB_EVT_MASK GENMASK(26, 20) -+ u32 req; -+ u32 ack_irq_mask; -+ u32 doorbell_req; -+ u32 reserved1; -+ u32 progress_timer; -+ -+#define GLB_TIMER_VAL(x) ((x) & GENMASK(30, 0)) -+#define GLB_TIMER_SOURCE_GPU_COUNTER BIT(31) -+ u32 poweroff_timer; -+ u64 core_en_mask; -+ u32 reserved2; -+ u32 perfcnt_as; -+ u64 perfcnt_base; -+ u32 perfcnt_extract; -+ u32 reserved3[3]; -+ u32 perfcnt_config; -+ u32 perfcnt_csg_select; -+ u32 perfcnt_fw_enable; -+ u32 perfcnt_csg_enable; -+ u32 perfcnt_csf_enable; -+ u32 perfcnt_shader_enable; -+ u32 perfcnt_tiler_enable; -+ u32 perfcnt_mmu_l2_enable; -+ u32 reserved4[8]; -+ u32 idle_timer; -+}; -+ -+enum panthor_fw_halt_status { -+ PANTHOR_FW_HALT_OK = 0, -+ PANTHOR_FW_HALT_ON_PANIC = 0x4e, -+ PANTHOR_FW_HALT_ON_WATCHDOG_EXPIRATION = 0x4f, -+}; -+ -+struct panthor_fw_global_output_iface { -+ u32 ack; -+ u32 reserved1; -+ u32 doorbell_ack; -+ u32 reserved2; -+ u32 halt_status; -+ u32 perfcnt_status; -+ u32 perfcnt_insert; -+}; -+ -+/** -+ * struct panthor_fw_cs_iface - Firmware command stream slot interface -+ */ -+struct panthor_fw_cs_iface { -+ /** -+ * @lock: Lock protecting access to the panthor_fw_cs_input_iface::req -+ * field. -+ * -+ * Needed so we can update the req field concurrently from the interrupt -+ * handler and the scheduler logic. -+ * -+ * TODO: Ideally we'd want to use a cmpxchg() to update the req, but FW -+ * interface sections are mapped uncached/write-combined right now, and -+ * using cmpxchg() on such mappings leads to SError faults. Revisit when -+ * we have 'SHARED' GPU mappings hooked up. -+ */ -+ spinlock_t lock; -+ -+ /** -+ * @control: Command stream slot control interface. -+ * -+ * Used to expose command stream slot properties. -+ * -+ * This interface is read-only. -+ */ -+ struct panthor_fw_cs_control_iface *control; -+ -+ /** -+ * @input: Command stream slot input interface. -+ * -+ * Used for host updates/events. -+ */ -+ struct panthor_fw_cs_input_iface *input; -+ -+ /** -+ * @output: Command stream slot output interface. -+ * -+ * Used for FW updates/events. -+ * -+ * This interface is read-only. -+ */ -+ const struct panthor_fw_cs_output_iface *output; -+}; -+ -+/** -+ * struct panthor_fw_csg_iface - Firmware command stream group slot interface -+ */ -+struct panthor_fw_csg_iface { -+ /** -+ * @lock: Lock protecting access to the panthor_fw_csg_input_iface::req -+ * field. -+ * -+ * Needed so we can update the req field concurrently from the interrupt -+ * handler and the scheduler logic. -+ * -+ * TODO: Ideally we'd want to use a cmpxchg() to update the req, but FW -+ * interface sections are mapped uncached/write-combined right now, and -+ * using cmpxchg() on such mappings leads to SError faults. Revisit when -+ * we have 'SHARED' GPU mappings hooked up. -+ */ -+ spinlock_t lock; -+ -+ /** -+ * @control: Command stream group slot control interface. -+ * -+ * Used to expose command stream group slot properties. -+ * -+ * This interface is read-only. -+ */ -+ const struct panthor_fw_csg_control_iface *control; -+ -+ /** -+ * @input: Command stream slot input interface. -+ * -+ * Used for host updates/events. -+ */ -+ struct panthor_fw_csg_input_iface *input; -+ -+ /** -+ * @output: Command stream group slot output interface. -+ * -+ * Used for FW updates/events. -+ * -+ * This interface is read-only. -+ */ -+ const struct panthor_fw_csg_output_iface *output; -+}; -+ -+/** -+ * struct panthor_fw_global_iface - Firmware global interface -+ */ -+struct panthor_fw_global_iface { -+ /** -+ * @lock: Lock protecting access to the panthor_fw_global_input_iface::req -+ * field. -+ * -+ * Needed so we can update the req field concurrently from the interrupt -+ * handler and the scheduler/FW management logic. -+ * -+ * TODO: Ideally we'd want to use a cmpxchg() to update the req, but FW -+ * interface sections are mapped uncached/write-combined right now, and -+ * using cmpxchg() on such mappings leads to SError faults. Revisit when -+ * we have 'SHARED' GPU mappings hooked up. -+ */ -+ spinlock_t lock; -+ -+ /** -+ * @control: Command stream group slot control interface. -+ * -+ * Used to expose global FW properties. -+ * -+ * This interface is read-only. -+ */ -+ const struct panthor_fw_global_control_iface *control; -+ -+ /** -+ * @input: Global input interface. -+ * -+ * Used for host updates/events. -+ */ -+ struct panthor_fw_global_input_iface *input; -+ -+ /** -+ * @output: Global output interface. -+ * -+ * Used for FW updates/events. -+ * -+ * This interface is read-only. -+ */ -+ const struct panthor_fw_global_output_iface *output; -+}; -+ -+/** -+ * panthor_fw_toggle_reqs() - Toggle acknowledge bits to send an event to the FW -+ * @__iface: The interface to operate on. -+ * @__in_reg: Name of the register to update in the input section of the interface. -+ * @__out_reg: Name of the register to take as a reference in the output section of the -+ * interface. -+ * @__mask: Mask to apply to the update. -+ * -+ * The Host -> FW event/message passing was designed to be lockless, with each side of -+ * the channel having its writeable section. Events are signaled as a difference between -+ * the host and FW side in the req/ack registers (when a bit differs, there's an event -+ * pending, when they are the same, nothing needs attention). -+ * -+ * This helper allows one to update the req register based on the current value of the -+ * ack register managed by the FW. Toggling a specific bit will flag an event. In order -+ * for events to be re-evaluated, the interface doorbell needs to be rung. -+ * -+ * Concurrent accesses to the same req register is covered. -+ * -+ * Anything requiring atomic updates to multiple registers requires a dedicated lock. -+ */ -+#define panthor_fw_toggle_reqs(__iface, __in_reg, __out_reg, __mask) \ -+ do { \ -+ u32 __cur_val, __new_val, __out_val; \ -+ spin_lock(&(__iface)->lock); \ -+ __cur_val = READ_ONCE((__iface)->input->__in_reg); \ -+ __out_val = READ_ONCE((__iface)->output->__out_reg); \ -+ __new_val = ((__out_val ^ (__mask)) & (__mask)) | (__cur_val & ~(__mask)); \ -+ WRITE_ONCE((__iface)->input->__in_reg, __new_val); \ -+ spin_unlock(&(__iface)->lock); \ -+ } while (0) -+ -+/** -+ * panthor_fw_update_reqs() - Update bits to reflect a configuration change -+ * @__iface: The interface to operate on. -+ * @__in_reg: Name of the register to update in the input section of the interface. -+ * @__val: Value to set. -+ * @__mask: Mask to apply to the update. -+ * -+ * Some configuration get passed through req registers that are also used to -+ * send events to the FW. Those req registers being updated from the interrupt -+ * handler, they require special helpers to update the configuration part as well. -+ * -+ * Concurrent accesses to the same req register is covered. -+ * -+ * Anything requiring atomic updates to multiple registers requires a dedicated lock. -+ */ -+#define panthor_fw_update_reqs(__iface, __in_reg, __val, __mask) \ -+ do { \ -+ u32 __cur_val, __new_val; \ -+ spin_lock(&(__iface)->lock); \ -+ __cur_val = READ_ONCE((__iface)->input->__in_reg); \ -+ __new_val = (__cur_val & ~(__mask)) | ((__val) & (__mask)); \ -+ WRITE_ONCE((__iface)->input->__in_reg, __new_val); \ -+ spin_unlock(&(__iface)->lock); \ -+ } while (0) -+ -+struct panthor_fw_global_iface * -+panthor_fw_get_glb_iface(struct panthor_device *ptdev); -+ -+struct panthor_fw_csg_iface * -+panthor_fw_get_csg_iface(struct panthor_device *ptdev, u32 csg_slot); -+ -+struct panthor_fw_cs_iface * -+panthor_fw_get_cs_iface(struct panthor_device *ptdev, u32 csg_slot, u32 cs_slot); -+ -+int panthor_fw_csg_wait_acks(struct panthor_device *ptdev, u32 csg_id, u32 req_mask, -+ u32 *acked, u32 timeout_ms); -+ -+int panthor_fw_glb_wait_acks(struct panthor_device *ptdev, u32 req_mask, u32 *acked, -+ u32 timeout_ms); -+ -+void panthor_fw_ring_csg_doorbells(struct panthor_device *ptdev, u32 csg_slot); -+ -+struct panthor_kernel_bo * -+panthor_fw_alloc_queue_iface_mem(struct panthor_device *ptdev, -+ struct panthor_fw_ringbuf_input_iface **input, -+ const struct panthor_fw_ringbuf_output_iface **output, -+ u32 *input_fw_va, u32 *output_fw_va); -+struct panthor_kernel_bo * -+panthor_fw_alloc_suspend_buf_mem(struct panthor_device *ptdev, size_t size); -+ -+struct panthor_vm *panthor_fw_vm(struct panthor_device *ptdev); -+ -+void panthor_fw_pre_reset(struct panthor_device *ptdev, bool on_hang); -+int panthor_fw_post_reset(struct panthor_device *ptdev); -+ -+static inline void panthor_fw_suspend(struct panthor_device *ptdev) -+{ -+ panthor_fw_pre_reset(ptdev, false); -+} -+ -+static inline int panthor_fw_resume(struct panthor_device *ptdev) -+{ -+ return panthor_fw_post_reset(ptdev); -+} -+ -+int panthor_fw_init(struct panthor_device *ptdev); -+void panthor_fw_unplug(struct panthor_device *ptdev); -+ -+#endif --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:23 +0100 -Subject: drm/panthor: Add the heap logical block - -Tiler heap growing requires some kernel driver involvement: when the -tiler runs out of heap memory, it will raise an exception which is -either directly handled by the firmware if some free heap chunks are -available in the heap context, or passed back to the kernel otherwise. -The heap helpers will be used by the scheduler logic to allocate more -heap chunks to a heap context, when such a situation happens. - -Heap context creation is explicitly requested by userspace (using -the TILER_HEAP_CREATE ioctl), and the returned context is attached to a -queue through some command stream instruction. - -All the kernel does is keep the list of heap chunks allocated to a -context, so they can be freed when TILER_HEAP_DESTROY is called, or -extended when the FW requests a new chunk. - -v6: -- Add Maxime's and Heiko's acks - -v5: -- Fix FIXME comment -- Add Steve's R-b - -v4: -- Rework locking to allow concurrent calls to panthor_heap_grow() -- Add a helper to return a heap chunk if we couldn't pass it to the - FW because the group was scheduled out - -v3: -- Add a FIXME for the heap OOM deadlock -- Use the panthor_kernel_bo abstraction for the heap context and heap - chunks -- Drop the panthor_heap_gpu_ctx struct as it is opaque to the driver -- Ensure that the heap context is aligned to the GPU cache line size -- Minor code tidy ups - -Co-developed-by: Steven Price -Signed-off-by: Steven Price -Signed-off-by: Boris Brezillon -Reviewed-by: Steven Price -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - drivers/gpu/drm/panthor/panthor_heap.c | 597 ++++++++++ - drivers/gpu/drm/panthor/panthor_heap.h | 39 + - 2 files changed, 636 insertions(+) - -diff --git a/drivers/gpu/drm/panthor/panthor_heap.c b/drivers/gpu/drm/panthor/panthor_heap.c -new file mode 100644 -index 000000000000..143fa35f2e74 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_heap.c -@@ -0,0 +1,597 @@ -+// SPDX-License-Identifier: GPL-2.0 or MIT -+/* Copyright 2023 Collabora ltd. */ -+ -+#include -+#include -+ -+#include -+ -+#include "panthor_device.h" -+#include "panthor_gem.h" -+#include "panthor_heap.h" -+#include "panthor_mmu.h" -+#include "panthor_regs.h" -+ -+/* -+ * The GPU heap context is an opaque structure used by the GPU to track the -+ * heap allocations. The driver should only touch it to initialize it (zero all -+ * fields). Because the CPU and GPU can both access this structure it is -+ * required to be GPU cache line aligned. -+ */ -+#define HEAP_CONTEXT_SIZE 32 -+ -+/** -+ * struct panthor_heap_chunk_header - Heap chunk header -+ */ -+struct panthor_heap_chunk_header { -+ /** -+ * @next: Next heap chunk in the list. -+ * -+ * This is a GPU VA. -+ */ -+ u64 next; -+ -+ /** @unknown: MBZ. */ -+ u32 unknown[14]; -+}; -+ -+/** -+ * struct panthor_heap_chunk - Structure used to keep track of allocated heap chunks. -+ */ -+struct panthor_heap_chunk { -+ /** @node: Used to insert the heap chunk in panthor_heap::chunks. */ -+ struct list_head node; -+ -+ /** @bo: Buffer object backing the heap chunk. */ -+ struct panthor_kernel_bo *bo; -+}; -+ -+/** -+ * struct panthor_heap - Structure used to manage tiler heap contexts. -+ */ -+struct panthor_heap { -+ /** @chunks: List containing all heap chunks allocated so far. */ -+ struct list_head chunks; -+ -+ /** @lock: Lock protecting insertion in the chunks list. */ -+ struct mutex lock; -+ -+ /** @chunk_size: Size of each chunk. */ -+ u32 chunk_size; -+ -+ /** @max_chunks: Maximum number of chunks. */ -+ u32 max_chunks; -+ -+ /** -+ * @target_in_flight: Number of in-flight render passes after which -+ * we'd let the FW wait for fragment job to finish instead of allocating new chunks. -+ */ -+ u32 target_in_flight; -+ -+ /** @chunk_count: Number of heap chunks currently allocated. */ -+ u32 chunk_count; -+}; -+ -+#define MAX_HEAPS_PER_POOL 128 -+ -+/** -+ * struct panthor_heap_pool - Pool of heap contexts -+ * -+ * The pool is attached to a panthor_file and can't be shared across processes. -+ */ -+struct panthor_heap_pool { -+ /** @refcount: Reference count. */ -+ struct kref refcount; -+ -+ /** @ptdev: Device. */ -+ struct panthor_device *ptdev; -+ -+ /** @vm: VM this pool is bound to. */ -+ struct panthor_vm *vm; -+ -+ /** @lock: Lock protecting access to @xa. */ -+ struct rw_semaphore lock; -+ -+ /** @xa: Array storing panthor_heap objects. */ -+ struct xarray xa; -+ -+ /** @gpu_contexts: Buffer object containing the GPU heap contexts. */ -+ struct panthor_kernel_bo *gpu_contexts; -+}; -+ -+static int panthor_heap_ctx_stride(struct panthor_device *ptdev) -+{ -+ u32 l2_features = ptdev->gpu_info.l2_features; -+ u32 gpu_cache_line_size = GPU_L2_FEATURES_LINE_SIZE(l2_features); -+ -+ return ALIGN(HEAP_CONTEXT_SIZE, gpu_cache_line_size); -+} -+ -+static int panthor_get_heap_ctx_offset(struct panthor_heap_pool *pool, int id) -+{ -+ return panthor_heap_ctx_stride(pool->ptdev) * id; -+} -+ -+static void *panthor_get_heap_ctx(struct panthor_heap_pool *pool, int id) -+{ -+ return pool->gpu_contexts->kmap + -+ panthor_get_heap_ctx_offset(pool, id); -+} -+ -+static void panthor_free_heap_chunk(struct panthor_vm *vm, -+ struct panthor_heap *heap, -+ struct panthor_heap_chunk *chunk) -+{ -+ mutex_lock(&heap->lock); -+ list_del(&chunk->node); -+ heap->chunk_count--; -+ mutex_unlock(&heap->lock); -+ -+ panthor_kernel_bo_destroy(vm, chunk->bo); -+ kfree(chunk); -+} -+ -+static int panthor_alloc_heap_chunk(struct panthor_device *ptdev, -+ struct panthor_vm *vm, -+ struct panthor_heap *heap, -+ bool initial_chunk) -+{ -+ struct panthor_heap_chunk *chunk; -+ struct panthor_heap_chunk_header *hdr; -+ int ret; -+ -+ chunk = kmalloc(sizeof(*chunk), GFP_KERNEL); -+ if (!chunk) -+ return -ENOMEM; -+ -+ chunk->bo = panthor_kernel_bo_create(ptdev, vm, heap->chunk_size, -+ DRM_PANTHOR_BO_NO_MMAP, -+ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC, -+ PANTHOR_VM_KERNEL_AUTO_VA); -+ if (IS_ERR(chunk->bo)) { -+ ret = PTR_ERR(chunk->bo); -+ goto err_free_chunk; -+ } -+ -+ ret = panthor_kernel_bo_vmap(chunk->bo); -+ if (ret) -+ goto err_destroy_bo; -+ -+ hdr = chunk->bo->kmap; -+ memset(hdr, 0, sizeof(*hdr)); -+ -+ if (initial_chunk && !list_empty(&heap->chunks)) { -+ struct panthor_heap_chunk *prev_chunk; -+ u64 prev_gpuva; -+ -+ prev_chunk = list_first_entry(&heap->chunks, -+ struct panthor_heap_chunk, -+ node); -+ -+ prev_gpuva = panthor_kernel_bo_gpuva(prev_chunk->bo); -+ hdr->next = (prev_gpuva & GENMASK_ULL(63, 12)) | -+ (heap->chunk_size >> 12); -+ } -+ -+ panthor_kernel_bo_vunmap(chunk->bo); -+ -+ mutex_lock(&heap->lock); -+ list_add(&chunk->node, &heap->chunks); -+ heap->chunk_count++; -+ mutex_unlock(&heap->lock); -+ -+ return 0; -+ -+err_destroy_bo: -+ panthor_kernel_bo_destroy(vm, chunk->bo); -+ -+err_free_chunk: -+ kfree(chunk); -+ -+ return ret; -+} -+ -+static void panthor_free_heap_chunks(struct panthor_vm *vm, -+ struct panthor_heap *heap) -+{ -+ struct panthor_heap_chunk *chunk, *tmp; -+ -+ list_for_each_entry_safe(chunk, tmp, &heap->chunks, node) -+ panthor_free_heap_chunk(vm, heap, chunk); -+} -+ -+static int panthor_alloc_heap_chunks(struct panthor_device *ptdev, -+ struct panthor_vm *vm, -+ struct panthor_heap *heap, -+ u32 chunk_count) -+{ -+ int ret; -+ u32 i; -+ -+ for (i = 0; i < chunk_count; i++) { -+ ret = panthor_alloc_heap_chunk(ptdev, vm, heap, true); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int -+panthor_heap_destroy_locked(struct panthor_heap_pool *pool, u32 handle) -+{ -+ struct panthor_heap *heap; -+ -+ heap = xa_erase(&pool->xa, handle); -+ if (!heap) -+ return -EINVAL; -+ -+ panthor_free_heap_chunks(pool->vm, heap); -+ mutex_destroy(&heap->lock); -+ kfree(heap); -+ return 0; -+} -+ -+/** -+ * panthor_heap_destroy() - Destroy a heap context -+ * @pool: Pool this context belongs to. -+ * @handle: Handle returned by panthor_heap_create(). -+ */ -+int panthor_heap_destroy(struct panthor_heap_pool *pool, u32 handle) -+{ -+ int ret; -+ -+ down_write(&pool->lock); -+ ret = panthor_heap_destroy_locked(pool, handle); -+ up_write(&pool->lock); -+ -+ return ret; -+} -+ -+/** -+ * panthor_heap_create() - Create a heap context -+ * @pool: Pool to instantiate the heap context from. -+ * @initial_chunk_count: Number of chunk allocated at initialization time. -+ * Must be at least 1. -+ * @chunk_size: The size of each chunk. Must be a power of two between 256k -+ * and 2M. -+ * @max_chunks: Maximum number of chunks that can be allocated. -+ * @target_in_flight: Maximum number of in-flight render passes. -+ * @heap_ctx_gpu_va: Pointer holding the GPU address of the allocated heap -+ * context. -+ * @first_chunk_gpu_va: Pointer holding the GPU address of the first chunk -+ * assigned to the heap context. -+ * -+ * Return: a positive handle on success, a negative error otherwise. -+ */ -+int panthor_heap_create(struct panthor_heap_pool *pool, -+ u32 initial_chunk_count, -+ u32 chunk_size, -+ u32 max_chunks, -+ u32 target_in_flight, -+ u64 *heap_ctx_gpu_va, -+ u64 *first_chunk_gpu_va) -+{ -+ struct panthor_heap *heap; -+ struct panthor_heap_chunk *first_chunk; -+ struct panthor_vm *vm; -+ int ret = 0; -+ u32 id; -+ -+ if (initial_chunk_count == 0) -+ return -EINVAL; -+ -+ if (hweight32(chunk_size) != 1 || -+ chunk_size < SZ_256K || chunk_size > SZ_2M) -+ return -EINVAL; -+ -+ down_read(&pool->lock); -+ vm = panthor_vm_get(pool->vm); -+ up_read(&pool->lock); -+ -+ /* The pool has been destroyed, we can't create a new heap. */ -+ if (!vm) -+ return -EINVAL; -+ -+ heap = kzalloc(sizeof(*heap), GFP_KERNEL); -+ if (!heap) { -+ ret = -ENOMEM; -+ goto err_put_vm; -+ } -+ -+ mutex_init(&heap->lock); -+ INIT_LIST_HEAD(&heap->chunks); -+ heap->chunk_size = chunk_size; -+ heap->max_chunks = max_chunks; -+ heap->target_in_flight = target_in_flight; -+ -+ ret = panthor_alloc_heap_chunks(pool->ptdev, vm, heap, -+ initial_chunk_count); -+ if (ret) -+ goto err_free_heap; -+ -+ first_chunk = list_first_entry(&heap->chunks, -+ struct panthor_heap_chunk, -+ node); -+ *first_chunk_gpu_va = panthor_kernel_bo_gpuva(first_chunk->bo); -+ -+ down_write(&pool->lock); -+ /* The pool has been destroyed, we can't create a new heap. */ -+ if (!pool->vm) { -+ ret = -EINVAL; -+ } else { -+ ret = xa_alloc(&pool->xa, &id, heap, XA_LIMIT(1, MAX_HEAPS_PER_POOL), GFP_KERNEL); -+ if (!ret) { -+ void *gpu_ctx = panthor_get_heap_ctx(pool, id); -+ -+ memset(gpu_ctx, 0, panthor_heap_ctx_stride(pool->ptdev)); -+ *heap_ctx_gpu_va = panthor_kernel_bo_gpuva(pool->gpu_contexts) + -+ panthor_get_heap_ctx_offset(pool, id); -+ } -+ } -+ up_write(&pool->lock); -+ -+ if (ret) -+ goto err_free_heap; -+ -+ panthor_vm_put(vm); -+ return id; -+ -+err_free_heap: -+ panthor_free_heap_chunks(pool->vm, heap); -+ mutex_destroy(&heap->lock); -+ kfree(heap); -+ -+err_put_vm: -+ panthor_vm_put(vm); -+ return ret; -+} -+ -+/** -+ * panthor_heap_return_chunk() - Return an unused heap chunk -+ * @pool: The pool this heap belongs to. -+ * @heap_gpu_va: The GPU address of the heap context. -+ * @chunk_gpu_va: The chunk VA to return. -+ * -+ * This function is used when a chunk allocated with panthor_heap_grow() -+ * couldn't be linked to the heap context through the FW interface because -+ * the group requesting the allocation was scheduled out in the meantime. -+ */ -+int panthor_heap_return_chunk(struct panthor_heap_pool *pool, -+ u64 heap_gpu_va, -+ u64 chunk_gpu_va) -+{ -+ u64 offset = heap_gpu_va - panthor_kernel_bo_gpuva(pool->gpu_contexts); -+ u32 heap_id = (u32)offset / panthor_heap_ctx_stride(pool->ptdev); -+ struct panthor_heap_chunk *chunk, *tmp, *removed = NULL; -+ struct panthor_heap *heap; -+ int ret; -+ -+ if (offset > U32_MAX || heap_id >= MAX_HEAPS_PER_POOL) -+ return -EINVAL; -+ -+ down_read(&pool->lock); -+ heap = xa_load(&pool->xa, heap_id); -+ if (!heap) { -+ ret = -EINVAL; -+ goto out_unlock; -+ } -+ -+ chunk_gpu_va &= GENMASK_ULL(63, 12); -+ -+ mutex_lock(&heap->lock); -+ list_for_each_entry_safe(chunk, tmp, &heap->chunks, node) { -+ if (panthor_kernel_bo_gpuva(chunk->bo) == chunk_gpu_va) { -+ removed = chunk; -+ list_del(&chunk->node); -+ heap->chunk_count--; -+ break; -+ } -+ } -+ mutex_unlock(&heap->lock); -+ -+ if (removed) { -+ panthor_kernel_bo_destroy(pool->vm, chunk->bo); -+ kfree(chunk); -+ ret = 0; -+ } else { -+ ret = -EINVAL; -+ } -+ -+out_unlock: -+ up_read(&pool->lock); -+ return ret; -+} -+ -+/** -+ * panthor_heap_grow() - Make a heap context grow. -+ * @pool: The pool this heap belongs to. -+ * @heap_gpu_va: The GPU address of the heap context. -+ * @renderpasses_in_flight: Number of render passes currently in-flight. -+ * @pending_frag_count: Number of fragment jobs waiting for execution/completion. -+ * @new_chunk_gpu_va: Pointer used to return the chunk VA. -+ */ -+int panthor_heap_grow(struct panthor_heap_pool *pool, -+ u64 heap_gpu_va, -+ u32 renderpasses_in_flight, -+ u32 pending_frag_count, -+ u64 *new_chunk_gpu_va) -+{ -+ u64 offset = heap_gpu_va - panthor_kernel_bo_gpuva(pool->gpu_contexts); -+ u32 heap_id = (u32)offset / panthor_heap_ctx_stride(pool->ptdev); -+ struct panthor_heap_chunk *chunk; -+ struct panthor_heap *heap; -+ int ret; -+ -+ if (offset > U32_MAX || heap_id >= MAX_HEAPS_PER_POOL) -+ return -EINVAL; -+ -+ down_read(&pool->lock); -+ heap = xa_load(&pool->xa, heap_id); -+ if (!heap) { -+ ret = -EINVAL; -+ goto out_unlock; -+ } -+ -+ /* If we reached the target in-flight render passes, or if we -+ * reached the maximum number of chunks, let the FW figure another way to -+ * find some memory (wait for render passes to finish, or call the exception -+ * handler provided by the userspace driver, if any). -+ */ -+ if (renderpasses_in_flight > heap->target_in_flight || -+ (pending_frag_count > 0 && heap->chunk_count >= heap->max_chunks)) { -+ ret = -EBUSY; -+ goto out_unlock; -+ } else if (heap->chunk_count >= heap->max_chunks) { -+ ret = -ENOMEM; -+ goto out_unlock; -+ } -+ -+ /* FIXME: panthor_alloc_heap_chunk() triggers a kernel BO creation, -+ * which goes through the blocking allocation path. Ultimately, we -+ * want a non-blocking allocation, so we can immediately report to the -+ * FW when the system is running out of memory. In that case, the FW -+ * can call a user-provided exception handler, which might try to free -+ * some tiler memory by issuing an intermediate fragment job. If the -+ * exception handler can't do anything, it will flag the queue as -+ * faulty so the job that triggered this tiler chunk allocation and all -+ * further jobs in this queue fail immediately instead of having to -+ * wait for the job timeout. -+ */ -+ ret = panthor_alloc_heap_chunk(pool->ptdev, pool->vm, heap, false); -+ if (ret) -+ goto out_unlock; -+ -+ chunk = list_first_entry(&heap->chunks, -+ struct panthor_heap_chunk, -+ node); -+ *new_chunk_gpu_va = (panthor_kernel_bo_gpuva(chunk->bo) & GENMASK_ULL(63, 12)) | -+ (heap->chunk_size >> 12); -+ ret = 0; -+ -+out_unlock: -+ up_read(&pool->lock); -+ return ret; -+} -+ -+static void panthor_heap_pool_release(struct kref *refcount) -+{ -+ struct panthor_heap_pool *pool = -+ container_of(refcount, struct panthor_heap_pool, refcount); -+ -+ xa_destroy(&pool->xa); -+ kfree(pool); -+} -+ -+/** -+ * panthor_heap_pool_put() - Release a heap pool reference -+ * @pool: Pool to release the reference on. Can be NULL. -+ */ -+void panthor_heap_pool_put(struct panthor_heap_pool *pool) -+{ -+ if (pool) -+ kref_put(&pool->refcount, panthor_heap_pool_release); -+} -+ -+/** -+ * panthor_heap_pool_get() - Get a heap pool reference -+ * @pool: Pool to get the reference on. Can be NULL. -+ * -+ * Return: @pool. -+ */ -+struct panthor_heap_pool * -+panthor_heap_pool_get(struct panthor_heap_pool *pool) -+{ -+ if (pool) -+ kref_get(&pool->refcount); -+ -+ return pool; -+} -+ -+/** -+ * panthor_heap_pool_create() - Create a heap pool -+ * @ptdev: Device. -+ * @vm: The VM this heap pool will be attached to. -+ * -+ * Heap pools might contain up to 128 heap contexts, and are per-VM. -+ * -+ * Return: A valid pointer on success, a negative error code otherwise. -+ */ -+struct panthor_heap_pool * -+panthor_heap_pool_create(struct panthor_device *ptdev, struct panthor_vm *vm) -+{ -+ size_t bosize = ALIGN(MAX_HEAPS_PER_POOL * -+ panthor_heap_ctx_stride(ptdev), -+ 4096); -+ struct panthor_heap_pool *pool; -+ int ret = 0; -+ -+ pool = kzalloc(sizeof(*pool), GFP_KERNEL); -+ if (!pool) -+ return ERR_PTR(-ENOMEM); -+ -+ /* We want a weak ref here: the heap pool belongs to the VM, so we're -+ * sure that, as long as the heap pool exists, the VM exists too. -+ */ -+ pool->vm = vm; -+ pool->ptdev = ptdev; -+ init_rwsem(&pool->lock); -+ xa_init_flags(&pool->xa, XA_FLAGS_ALLOC1); -+ kref_init(&pool->refcount); -+ -+ pool->gpu_contexts = panthor_kernel_bo_create(ptdev, vm, bosize, -+ DRM_PANTHOR_BO_NO_MMAP, -+ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC, -+ PANTHOR_VM_KERNEL_AUTO_VA); -+ if (IS_ERR(pool->gpu_contexts)) { -+ ret = PTR_ERR(pool->gpu_contexts); -+ goto err_destroy_pool; -+ } -+ -+ ret = panthor_kernel_bo_vmap(pool->gpu_contexts); -+ if (ret) -+ goto err_destroy_pool; -+ -+ return pool; -+ -+err_destroy_pool: -+ panthor_heap_pool_destroy(pool); -+ return ERR_PTR(ret); -+} -+ -+/** -+ * panthor_heap_pool_destroy() - Destroy a heap pool. -+ * @pool: Pool to destroy. -+ * -+ * This function destroys all heap contexts and their resources. Thus -+ * preventing any use of the heap context or the chunk attached to them -+ * after that point. -+ * -+ * If the GPU still has access to some heap contexts, a fault should be -+ * triggered, which should flag the command stream groups using these -+ * context as faulty. -+ * -+ * The heap pool object is only released when all references to this pool -+ * are released. -+ */ -+void panthor_heap_pool_destroy(struct panthor_heap_pool *pool) -+{ -+ struct panthor_heap *heap; -+ unsigned long i; -+ -+ if (!pool) -+ return; -+ -+ down_write(&pool->lock); -+ xa_for_each(&pool->xa, i, heap) -+ drm_WARN_ON(&pool->ptdev->base, panthor_heap_destroy_locked(pool, i)); -+ -+ if (!IS_ERR_OR_NULL(pool->gpu_contexts)) -+ panthor_kernel_bo_destroy(pool->vm, pool->gpu_contexts); -+ -+ /* Reflects the fact the pool has been destroyed. */ -+ pool->vm = NULL; -+ up_write(&pool->lock); -+ -+ panthor_heap_pool_put(pool); -+} -diff --git a/drivers/gpu/drm/panthor/panthor_heap.h b/drivers/gpu/drm/panthor/panthor_heap.h -new file mode 100644 -index 000000000000..25a5f2bba445 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_heap.h -@@ -0,0 +1,39 @@ -+/* SPDX-License-Identifier: GPL-2.0 or MIT */ -+/* Copyright 2023 Collabora ltd. */ -+ -+#ifndef __PANTHOR_HEAP_H__ -+#define __PANTHOR_HEAP_H__ -+ -+#include -+ -+struct panthor_device; -+struct panthor_heap_pool; -+struct panthor_vm; -+ -+int panthor_heap_create(struct panthor_heap_pool *pool, -+ u32 initial_chunk_count, -+ u32 chunk_size, -+ u32 max_chunks, -+ u32 target_in_flight, -+ u64 *heap_ctx_gpu_va, -+ u64 *first_chunk_gpu_va); -+int panthor_heap_destroy(struct panthor_heap_pool *pool, u32 handle); -+ -+struct panthor_heap_pool * -+panthor_heap_pool_create(struct panthor_device *ptdev, struct panthor_vm *vm); -+void panthor_heap_pool_destroy(struct panthor_heap_pool *pool); -+ -+struct panthor_heap_pool * -+panthor_heap_pool_get(struct panthor_heap_pool *pool); -+void panthor_heap_pool_put(struct panthor_heap_pool *pool); -+ -+int panthor_heap_grow(struct panthor_heap_pool *pool, -+ u64 heap_gpu_va, -+ u32 renderpasses_in_flight, -+ u32 pending_frag_count, -+ u64 *new_chunk_gpu_va); -+int panthor_heap_return_chunk(struct panthor_heap_pool *pool, -+ u64 heap_gpu_va, -+ u64 chunk_gpu_va); -+ -+#endif --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:24 +0100 -Subject: drm/panthor: Add the scheduler logical block - -This is the piece of software interacting with the FW scheduler, and -taking care of some scheduling aspects when the FW comes short of slots -scheduling slots. Indeed, the FW only expose a few slots, and the kernel -has to give all submission contexts, a chance to execute their jobs. - -The kernel-side scheduler is timeslice-based, with a round-robin queue -per priority level. - -Job submission is handled with a 1:1 drm_sched_entity:drm_gpu_scheduler, -allowing us to delegate the dependency tracking to the core. - -All the gory details should be documented inline. - -v6: -- Add Maxime's and Heiko's acks -- Make sure the scheduler is initialized before queueing the tick work - in the MMU fault handler -- Keep header inclusion alphabetically ordered - -v5: -- Fix typos -- Call panthor_kernel_bo_destroy(group->syncobjs) unconditionally -- Don't move the group to the waiting list tail when it was already - waiting for a different syncobj -- Fix fatal_queues flagging in the tiler OOM path -- Don't warn when more than one job timesout on a group -- Add a warning message when we fail to allocate a heap chunk -- Add Steve's R-b - -v4: -- Check drmm_mutex_init() return code -- s/drm_gem_vmap_unlocked/drm_gem_vunmap_unlocked/ in - panthor_queue_put_syncwait_obj() -- Drop unneeded WARN_ON() in cs_slot_sync_queue_state_locked() -- Use atomic_xchg() instead of atomic_fetch_and(0) -- Fix typos -- Let panthor_kernel_bo_destroy() check for IS_ERR_OR_NULL() BOs -- Defer TILER_OOM event handling to a separate workqueue to prevent - deadlocks when the heap chunk allocation is blocked on mem-reclaim. - This is just a temporary solution, until we add support for - non-blocking/failable allocations -- Pass the scheduler workqueue to drm_sched instead of instantiating - a separate one (no longer needed now that heap chunk allocation - happens on a dedicated wq) -- Set WQ_MEM_RECLAIM on the scheduler workqueue, so we can handle - job timeouts when the system is under mem pressure, and hopefully - free up some memory retained by these jobs - -v3: -- Rework the FW event handling logic to avoid races -- Make sure MMU faults kill the group immediately -- Use the panthor_kernel_bo abstraction for group/queue buffers -- Make in_progress an atomic_t, so we can check it without the reset lock - held -- Don't limit the number of groups per context to the FW scheduler - capacity. Fix the limit to 128 for now. -- Add a panthor_job_vm() helper -- Account for panthor_vm changes -- Add our job fence as DMA_RESV_USAGE_WRITE to all external objects - (was previously DMA_RESV_USAGE_BOOKKEEP). I don't get why, given - we're supposed to be fully-explicit, but other drivers do that, so - there must be a good reason -- Account for drm_sched changes -- Provide a panthor_queue_put_syncwait_obj() -- Unconditionally return groups to their idle list in - panthor_sched_suspend() -- Condition of sched_queue_{,delayed_}work fixed to be only when a reset - isn't pending or in progress. -- Several typos in comments fixed. - -Co-developed-by: Steven Price -Signed-off-by: Steven Price -Signed-off-by: Boris Brezillon -Reviewed-by: Steven Price -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - drivers/gpu/drm/panthor/panthor_sched.c | 3502 ++++++++++ - drivers/gpu/drm/panthor/panthor_sched.h | 50 + - 2 files changed, 3552 insertions(+) - -diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c -new file mode 100644 -index 000000000000..5f7803b6fc48 ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_sched.c -@@ -0,0 +1,3502 @@ -+// SPDX-License-Identifier: GPL-2.0 or MIT -+/* Copyright 2023 Collabora ltd. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "panthor_devfreq.h" -+#include "panthor_device.h" -+#include "panthor_fw.h" -+#include "panthor_gem.h" -+#include "panthor_gpu.h" -+#include "panthor_heap.h" -+#include "panthor_mmu.h" -+#include "panthor_regs.h" -+#include "panthor_sched.h" -+ -+/** -+ * DOC: Scheduler -+ * -+ * Mali CSF hardware adopts a firmware-assisted scheduling model, where -+ * the firmware takes care of scheduling aspects, to some extent. -+ * -+ * The scheduling happens at the scheduling group level, each group -+ * contains 1 to N queues (N is FW/hardware dependent, and exposed -+ * through the firmware interface). Each queue is assigned a command -+ * stream ring buffer, which serves as a way to get jobs submitted to -+ * the GPU, among other things. -+ * -+ * The firmware can schedule a maximum of M groups (M is FW/hardware -+ * dependent, and exposed through the firmware interface). Passed -+ * this maximum number of groups, the kernel must take care of -+ * rotating the groups passed to the firmware so every group gets -+ * a chance to have his queues scheduled for execution. -+ * -+ * The current implementation only supports with kernel-mode queues. -+ * In other terms, userspace doesn't have access to the ring-buffer. -+ * Instead, userspace passes indirect command stream buffers that are -+ * called from the queue ring-buffer by the kernel using a pre-defined -+ * sequence of command stream instructions to ensure the userspace driver -+ * always gets consistent results (cache maintenance, -+ * synchronization, ...). -+ * -+ * We rely on the drm_gpu_scheduler framework to deal with job -+ * dependencies and submission. As any other driver dealing with a -+ * FW-scheduler, we use the 1:1 entity:scheduler mode, such that each -+ * entity has its own job scheduler. When a job is ready to be executed -+ * (all its dependencies are met), it is pushed to the appropriate -+ * queue ring-buffer, and the group is scheduled for execution if it -+ * wasn't already active. -+ * -+ * Kernel-side group scheduling is timeslice-based. When we have less -+ * groups than there are slots, the periodic tick is disabled and we -+ * just let the FW schedule the active groups. When there are more -+ * groups than slots, we let each group a chance to execute stuff for -+ * a given amount of time, and then re-evaluate and pick new groups -+ * to schedule. The group selection algorithm is based on -+ * priority+round-robin. -+ * -+ * Even though user-mode queues is out of the scope right now, the -+ * current design takes them into account by avoiding any guess on the -+ * group/queue state that would be based on information we wouldn't have -+ * if userspace was in charge of the ring-buffer. That's also one of the -+ * reason we don't do 'cooperative' scheduling (encoding FW group slot -+ * reservation as dma_fence that would be returned from the -+ * drm_gpu_scheduler::prepare_job() hook, and treating group rotation as -+ * a queue of waiters, ordered by job submission order). This approach -+ * would work for kernel-mode queues, but would make user-mode queues a -+ * lot more complicated to retrofit. -+ */ -+ -+#define JOB_TIMEOUT_MS 5000 -+ -+#define MIN_CS_PER_CSG 8 -+ -+#define MIN_CSGS 3 -+#define MAX_CSG_PRIO 0xf -+ -+struct panthor_group; -+ -+/** -+ * struct panthor_csg_slot - Command stream group slot -+ * -+ * This represents a FW slot for a scheduling group. -+ */ -+struct panthor_csg_slot { -+ /** @group: Scheduling group bound to this slot. */ -+ struct panthor_group *group; -+ -+ /** @priority: Group priority. */ -+ u8 priority; -+ -+ /** -+ * @idle: True if the group bound to this slot is idle. -+ * -+ * A group is idle when it has nothing waiting for execution on -+ * all its queues, or when queues are blocked waiting for something -+ * to happen (synchronization object). -+ */ -+ bool idle; -+}; -+ -+/** -+ * enum panthor_csg_priority - Group priority -+ */ -+enum panthor_csg_priority { -+ /** @PANTHOR_CSG_PRIORITY_LOW: Low priority group. */ -+ PANTHOR_CSG_PRIORITY_LOW = 0, -+ -+ /** @PANTHOR_CSG_PRIORITY_MEDIUM: Medium priority group. */ -+ PANTHOR_CSG_PRIORITY_MEDIUM, -+ -+ /** @PANTHOR_CSG_PRIORITY_HIGH: High priority group. */ -+ PANTHOR_CSG_PRIORITY_HIGH, -+ -+ /** -+ * @PANTHOR_CSG_PRIORITY_RT: Real-time priority group. -+ * -+ * Real-time priority allows one to preempt scheduling of other -+ * non-real-time groups. When such a group becomes executable, -+ * it will evict the group with the lowest non-rt priority if -+ * there's no free group slot available. -+ * -+ * Currently not exposed to userspace. -+ */ -+ PANTHOR_CSG_PRIORITY_RT, -+ -+ /** @PANTHOR_CSG_PRIORITY_COUNT: Number of priority levels. */ -+ PANTHOR_CSG_PRIORITY_COUNT, -+}; -+ -+/** -+ * struct panthor_scheduler - Object used to manage the scheduler -+ */ -+struct panthor_scheduler { -+ /** @ptdev: Device. */ -+ struct panthor_device *ptdev; -+ -+ /** -+ * @wq: Workqueue used by our internal scheduler logic and -+ * drm_gpu_scheduler. -+ * -+ * Used for the scheduler tick, group update or other kind of FW -+ * event processing that can't be handled in the threaded interrupt -+ * path. Also passed to the drm_gpu_scheduler instances embedded -+ * in panthor_queue. -+ */ -+ struct workqueue_struct *wq; -+ -+ /** -+ * @heap_alloc_wq: Workqueue used to schedule tiler_oom works. -+ * -+ * We have a queue dedicated to heap chunk allocation works to avoid -+ * blocking the rest of the scheduler if the allocation tries to -+ * reclaim memory. -+ */ -+ struct workqueue_struct *heap_alloc_wq; -+ -+ /** @tick_work: Work executed on a scheduling tick. */ -+ struct delayed_work tick_work; -+ -+ /** -+ * @sync_upd_work: Work used to process synchronization object updates. -+ * -+ * We use this work to unblock queues/groups that were waiting on a -+ * synchronization object. -+ */ -+ struct work_struct sync_upd_work; -+ -+ /** -+ * @fw_events_work: Work used to process FW events outside the interrupt path. -+ * -+ * Even if the interrupt is threaded, we need any event processing -+ * that require taking the panthor_scheduler::lock to be processed -+ * outside the interrupt path so we don't block the tick logic when -+ * it calls panthor_fw_{csg,wait}_wait_acks(). Since most of the -+ * event processing requires taking this lock, we just delegate all -+ * FW event processing to the scheduler workqueue. -+ */ -+ struct work_struct fw_events_work; -+ -+ /** -+ * @fw_events: Bitmask encoding pending FW events. -+ */ -+ atomic_t fw_events; -+ -+ /** -+ * @resched_target: When the next tick should occur. -+ * -+ * Expressed in jiffies. -+ */ -+ u64 resched_target; -+ -+ /** -+ * @last_tick: When the last tick occurred. -+ * -+ * Expressed in jiffies. -+ */ -+ u64 last_tick; -+ -+ /** @tick_period: Tick period in jiffies. */ -+ u64 tick_period; -+ -+ /** -+ * @lock: Lock protecting access to all the scheduler fields. -+ * -+ * Should be taken in the tick work, the irq handler, and anywhere the @groups -+ * fields are touched. -+ */ -+ struct mutex lock; -+ -+ /** @groups: Various lists used to classify groups. */ -+ struct { -+ /** -+ * @runnable: Runnable group lists. -+ * -+ * When a group has queues that want to execute something, -+ * its panthor_group::run_node should be inserted here. -+ * -+ * One list per-priority. -+ */ -+ struct list_head runnable[PANTHOR_CSG_PRIORITY_COUNT]; -+ -+ /** -+ * @idle: Idle group lists. -+ * -+ * When all queues of a group are idle (either because they -+ * have nothing to execute, or because they are blocked), the -+ * panthor_group::run_node field should be inserted here. -+ * -+ * One list per-priority. -+ */ -+ struct list_head idle[PANTHOR_CSG_PRIORITY_COUNT]; -+ -+ /** -+ * @waiting: List of groups whose queues are blocked on a -+ * synchronization object. -+ * -+ * Insert panthor_group::wait_node here when a group is waiting -+ * for synchronization objects to be signaled. -+ * -+ * This list is evaluated in the @sync_upd_work work. -+ */ -+ struct list_head waiting; -+ } groups; -+ -+ /** -+ * @csg_slots: FW command stream group slots. -+ */ -+ struct panthor_csg_slot csg_slots[MAX_CSGS]; -+ -+ /** @csg_slot_count: Number of command stream group slots exposed by the FW. */ -+ u32 csg_slot_count; -+ -+ /** @cs_slot_count: Number of command stream slot per group slot exposed by the FW. */ -+ u32 cs_slot_count; -+ -+ /** @as_slot_count: Number of address space slots supported by the MMU. */ -+ u32 as_slot_count; -+ -+ /** @used_csg_slot_count: Number of command stream group slot currently used. */ -+ u32 used_csg_slot_count; -+ -+ /** @sb_slot_count: Number of scoreboard slots. */ -+ u32 sb_slot_count; -+ -+ /** -+ * @might_have_idle_groups: True if an active group might have become idle. -+ * -+ * This will force a tick, so other runnable groups can be scheduled if one -+ * or more active groups became idle. -+ */ -+ bool might_have_idle_groups; -+ -+ /** @pm: Power management related fields. */ -+ struct { -+ /** @has_ref: True if the scheduler owns a runtime PM reference. */ -+ bool has_ref; -+ } pm; -+ -+ /** @reset: Reset related fields. */ -+ struct { -+ /** @lock: Lock protecting the other reset fields. */ -+ struct mutex lock; -+ -+ /** -+ * @in_progress: True if a reset is in progress. -+ * -+ * Set to true in panthor_sched_pre_reset() and back to false in -+ * panthor_sched_post_reset(). -+ */ -+ atomic_t in_progress; -+ -+ /** -+ * @stopped_groups: List containing all groups that were stopped -+ * before a reset. -+ * -+ * Insert panthor_group::run_node in the pre_reset path. -+ */ -+ struct list_head stopped_groups; -+ } reset; -+}; -+ -+/** -+ * struct panthor_syncobj_32b - 32-bit FW synchronization object -+ */ -+struct panthor_syncobj_32b { -+ /** @seqno: Sequence number. */ -+ u32 seqno; -+ -+ /** -+ * @status: Status. -+ * -+ * Not zero on failure. -+ */ -+ u32 status; -+}; -+ -+/** -+ * struct panthor_syncobj_64b - 64-bit FW synchronization object -+ */ -+struct panthor_syncobj_64b { -+ /** @seqno: Sequence number. */ -+ u64 seqno; -+ -+ /** -+ * @status: Status. -+ * -+ * Not zero on failure. -+ */ -+ u32 status; -+ -+ /** @pad: MBZ. */ -+ u32 pad; -+}; -+ -+/** -+ * struct panthor_queue - Execution queue -+ */ -+struct panthor_queue { -+ /** @scheduler: DRM scheduler used for this queue. */ -+ struct drm_gpu_scheduler scheduler; -+ -+ /** @entity: DRM scheduling entity used for this queue. */ -+ struct drm_sched_entity entity; -+ -+ /** -+ * @remaining_time: Time remaining before the job timeout expires. -+ * -+ * The job timeout is suspended when the queue is not scheduled by the -+ * FW. Every time we suspend the timer, we need to save the remaining -+ * time so we can restore it later on. -+ */ -+ unsigned long remaining_time; -+ -+ /** @timeout_suspended: True if the job timeout was suspended. */ -+ bool timeout_suspended; -+ -+ /** -+ * @doorbell_id: Doorbell assigned to this queue. -+ * -+ * Right now, all groups share the same doorbell, and the doorbell ID -+ * is assigned to group_slot + 1 when the group is assigned a slot. But -+ * we might decide to provide fine grained doorbell assignment at some -+ * point, so don't have to wake up all queues in a group every time one -+ * of them is updated. -+ */ -+ u8 doorbell_id; -+ -+ /** -+ * @priority: Priority of the queue inside the group. -+ * -+ * Must be less than 16 (Only 4 bits available). -+ */ -+ u8 priority; -+#define CSF_MAX_QUEUE_PRIO GENMASK(3, 0) -+ -+ /** @ringbuf: Command stream ring-buffer. */ -+ struct panthor_kernel_bo *ringbuf; -+ -+ /** @iface: Firmware interface. */ -+ struct { -+ /** @mem: FW memory allocated for this interface. */ -+ struct panthor_kernel_bo *mem; -+ -+ /** @input: Input interface. */ -+ struct panthor_fw_ringbuf_input_iface *input; -+ -+ /** @output: Output interface. */ -+ const struct panthor_fw_ringbuf_output_iface *output; -+ -+ /** @input_fw_va: FW virtual address of the input interface buffer. */ -+ u32 input_fw_va; -+ -+ /** @output_fw_va: FW virtual address of the output interface buffer. */ -+ u32 output_fw_va; -+ } iface; -+ -+ /** -+ * @syncwait: Stores information about the synchronization object this -+ * queue is waiting on. -+ */ -+ struct { -+ /** @gpu_va: GPU address of the synchronization object. */ -+ u64 gpu_va; -+ -+ /** @ref: Reference value to compare against. */ -+ u64 ref; -+ -+ /** @gt: True if this is a greater-than test. */ -+ bool gt; -+ -+ /** @sync64: True if this is a 64-bit sync object. */ -+ bool sync64; -+ -+ /** @bo: Buffer object holding the synchronization object. */ -+ struct drm_gem_object *obj; -+ -+ /** @offset: Offset of the synchronization object inside @bo. */ -+ u64 offset; -+ -+ /** -+ * @kmap: Kernel mapping of the buffer object holding the -+ * synchronization object. -+ */ -+ void *kmap; -+ } syncwait; -+ -+ /** @fence_ctx: Fence context fields. */ -+ struct { -+ /** @lock: Used to protect access to all fences allocated by this context. */ -+ spinlock_t lock; -+ -+ /** -+ * @id: Fence context ID. -+ * -+ * Allocated with dma_fence_context_alloc(). -+ */ -+ u64 id; -+ -+ /** @seqno: Sequence number of the last initialized fence. */ -+ atomic64_t seqno; -+ -+ /** -+ * @in_flight_jobs: List containing all in-flight jobs. -+ * -+ * Used to keep track and signal panthor_job::done_fence when the -+ * synchronization object attached to the queue is signaled. -+ */ -+ struct list_head in_flight_jobs; -+ } fence_ctx; -+}; -+ -+/** -+ * enum panthor_group_state - Scheduling group state. -+ */ -+enum panthor_group_state { -+ /** @PANTHOR_CS_GROUP_CREATED: Group was created, but not scheduled yet. */ -+ PANTHOR_CS_GROUP_CREATED, -+ -+ /** @PANTHOR_CS_GROUP_ACTIVE: Group is currently scheduled. */ -+ PANTHOR_CS_GROUP_ACTIVE, -+ -+ /** -+ * @PANTHOR_CS_GROUP_SUSPENDED: Group was scheduled at least once, but is -+ * inactive/suspended right now. -+ */ -+ PANTHOR_CS_GROUP_SUSPENDED, -+ -+ /** -+ * @PANTHOR_CS_GROUP_TERMINATED: Group was terminated. -+ * -+ * Can no longer be scheduled. The only allowed action is a destruction. -+ */ -+ PANTHOR_CS_GROUP_TERMINATED, -+}; -+ -+/** -+ * struct panthor_group - Scheduling group object -+ */ -+struct panthor_group { -+ /** @refcount: Reference count */ -+ struct kref refcount; -+ -+ /** @ptdev: Device. */ -+ struct panthor_device *ptdev; -+ -+ /** @vm: VM bound to the group. */ -+ struct panthor_vm *vm; -+ -+ /** @compute_core_mask: Mask of shader cores that can be used for compute jobs. */ -+ u64 compute_core_mask; -+ -+ /** @fragment_core_mask: Mask of shader cores that can be used for fragment jobs. */ -+ u64 fragment_core_mask; -+ -+ /** @tiler_core_mask: Mask of tiler cores that can be used for tiler jobs. */ -+ u64 tiler_core_mask; -+ -+ /** @max_compute_cores: Maximum number of shader cores used for compute jobs. */ -+ u8 max_compute_cores; -+ -+ /** @max_compute_cores: Maximum number of shader cores used for fragment jobs. */ -+ u8 max_fragment_cores; -+ -+ /** @max_tiler_cores: Maximum number of tiler cores used for tiler jobs. */ -+ u8 max_tiler_cores; -+ -+ /** @priority: Group priority (check panthor_csg_priority). */ -+ u8 priority; -+ -+ /** @blocked_queues: Bitmask reflecting the blocked queues. */ -+ u32 blocked_queues; -+ -+ /** @idle_queues: Bitmask reflecting the idle queues. */ -+ u32 idle_queues; -+ -+ /** @fatal_lock: Lock used to protect access to fatal fields. */ -+ spinlock_t fatal_lock; -+ -+ /** @fatal_queues: Bitmask reflecting the queues that hit a fatal exception. */ -+ u32 fatal_queues; -+ -+ /** @tiler_oom: Mask of queues that have a tiler OOM event to process. */ -+ atomic_t tiler_oom; -+ -+ /** @queue_count: Number of queues in this group. */ -+ u32 queue_count; -+ -+ /** @queues: Queues owned by this group. */ -+ struct panthor_queue *queues[MAX_CS_PER_CSG]; -+ -+ /** -+ * @csg_id: ID of the FW group slot. -+ * -+ * -1 when the group is not scheduled/active. -+ */ -+ int csg_id; -+ -+ /** -+ * @destroyed: True when the group has been destroyed. -+ * -+ * If a group is destroyed it becomes useless: no further jobs can be submitted -+ * to its queues. We simply wait for all references to be dropped so we can -+ * release the group object. -+ */ -+ bool destroyed; -+ -+ /** -+ * @timedout: True when a timeout occurred on any of the queues owned by -+ * this group. -+ * -+ * Timeouts can be reported by drm_sched or by the FW. In any case, any -+ * timeout situation is unrecoverable, and the group becomes useless. -+ * We simply wait for all references to be dropped so we can release the -+ * group object. -+ */ -+ bool timedout; -+ -+ /** -+ * @syncobjs: Pool of per-queue synchronization objects. -+ * -+ * One sync object per queue. The position of the sync object is -+ * determined by the queue index. -+ */ -+ struct panthor_kernel_bo *syncobjs; -+ -+ /** @state: Group state. */ -+ enum panthor_group_state state; -+ -+ /** -+ * @suspend_buf: Suspend buffer. -+ * -+ * Stores the state of the group and its queues when a group is suspended. -+ * Used at resume time to restore the group in its previous state. -+ * -+ * The size of the suspend buffer is exposed through the FW interface. -+ */ -+ struct panthor_kernel_bo *suspend_buf; -+ -+ /** -+ * @protm_suspend_buf: Protection mode suspend buffer. -+ * -+ * Stores the state of the group and its queues when a group that's in -+ * protection mode is suspended. -+ * -+ * Used at resume time to restore the group in its previous state. -+ * -+ * The size of the protection mode suspend buffer is exposed through the -+ * FW interface. -+ */ -+ struct panthor_kernel_bo *protm_suspend_buf; -+ -+ /** @sync_upd_work: Work used to check/signal job fences. */ -+ struct work_struct sync_upd_work; -+ -+ /** @tiler_oom_work: Work used to process tiler OOM events happening on this group. */ -+ struct work_struct tiler_oom_work; -+ -+ /** @term_work: Work used to finish the group termination procedure. */ -+ struct work_struct term_work; -+ -+ /** -+ * @release_work: Work used to release group resources. -+ * -+ * We need to postpone the group release to avoid a deadlock when -+ * the last ref is released in the tick work. -+ */ -+ struct work_struct release_work; -+ -+ /** -+ * @run_node: Node used to insert the group in the -+ * panthor_group::groups::{runnable,idle} and -+ * panthor_group::reset.stopped_groups lists. -+ */ -+ struct list_head run_node; -+ -+ /** -+ * @wait_node: Node used to insert the group in the -+ * panthor_group::groups::waiting list. -+ */ -+ struct list_head wait_node; -+}; -+ -+/** -+ * group_queue_work() - Queue a group work -+ * @group: Group to queue the work for. -+ * @wname: Work name. -+ * -+ * Grabs a ref and queue a work item to the scheduler workqueue. If -+ * the work was already queued, we release the reference we grabbed. -+ * -+ * Work callbacks must release the reference we grabbed here. -+ */ -+#define group_queue_work(group, wname) \ -+ do { \ -+ group_get(group); \ -+ if (!queue_work((group)->ptdev->scheduler->wq, &(group)->wname ## _work)) \ -+ group_put(group); \ -+ } while (0) -+ -+/** -+ * sched_queue_work() - Queue a scheduler work. -+ * @sched: Scheduler object. -+ * @wname: Work name. -+ * -+ * Conditionally queues a scheduler work if no reset is pending/in-progress. -+ */ -+#define sched_queue_work(sched, wname) \ -+ do { \ -+ if (!atomic_read(&(sched)->reset.in_progress) && \ -+ !panthor_device_reset_is_pending((sched)->ptdev)) \ -+ queue_work((sched)->wq, &(sched)->wname ## _work); \ -+ } while (0) -+ -+/** -+ * sched_queue_delayed_work() - Queue a scheduler delayed work. -+ * @sched: Scheduler object. -+ * @wname: Work name. -+ * @delay: Work delay in jiffies. -+ * -+ * Conditionally queues a scheduler delayed work if no reset is -+ * pending/in-progress. -+ */ -+#define sched_queue_delayed_work(sched, wname, delay) \ -+ do { \ -+ if (!atomic_read(&sched->reset.in_progress) && \ -+ !panthor_device_reset_is_pending((sched)->ptdev)) \ -+ mod_delayed_work((sched)->wq, &(sched)->wname ## _work, delay); \ -+ } while (0) -+ -+/* -+ * We currently set the maximum of groups per file to an arbitrary low value. -+ * But this can be updated if we need more. -+ */ -+#define MAX_GROUPS_PER_POOL 128 -+ -+/** -+ * struct panthor_group_pool - Group pool -+ * -+ * Each file get assigned a group pool. -+ */ -+struct panthor_group_pool { -+ /** @xa: Xarray used to manage group handles. */ -+ struct xarray xa; -+}; -+ -+/** -+ * struct panthor_job - Used to manage GPU job -+ */ -+struct panthor_job { -+ /** @base: Inherit from drm_sched_job. */ -+ struct drm_sched_job base; -+ -+ /** @refcount: Reference count. */ -+ struct kref refcount; -+ -+ /** @group: Group of the queue this job will be pushed to. */ -+ struct panthor_group *group; -+ -+ /** @queue_idx: Index of the queue inside @group. */ -+ u32 queue_idx; -+ -+ /** @call_info: Information about the userspace command stream call. */ -+ struct { -+ /** @start: GPU address of the userspace command stream. */ -+ u64 start; -+ -+ /** @size: Size of the userspace command stream. */ -+ u32 size; -+ -+ /** -+ * @latest_flush: Flush ID at the time the userspace command -+ * stream was built. -+ * -+ * Needed for the flush reduction mechanism. -+ */ -+ u32 latest_flush; -+ } call_info; -+ -+ /** @ringbuf: Position of this job is in the ring buffer. */ -+ struct { -+ /** @start: Start offset. */ -+ u64 start; -+ -+ /** @end: End offset. */ -+ u64 end; -+ } ringbuf; -+ -+ /** -+ * @node: Used to insert the job in the panthor_queue::fence_ctx::in_flight_jobs -+ * list. -+ */ -+ struct list_head node; -+ -+ /** @done_fence: Fence signaled when the job is finished or cancelled. */ -+ struct dma_fence *done_fence; -+}; -+ -+static void -+panthor_queue_put_syncwait_obj(struct panthor_queue *queue) -+{ -+ if (queue->syncwait.kmap) { -+ struct iosys_map map = IOSYS_MAP_INIT_VADDR(queue->syncwait.kmap); -+ -+ drm_gem_vunmap_unlocked(queue->syncwait.obj, &map); -+ queue->syncwait.kmap = NULL; -+ } -+ -+ drm_gem_object_put(queue->syncwait.obj); -+ queue->syncwait.obj = NULL; -+} -+ -+static void * -+panthor_queue_get_syncwait_obj(struct panthor_group *group, struct panthor_queue *queue) -+{ -+ struct panthor_device *ptdev = group->ptdev; -+ struct panthor_gem_object *bo; -+ struct iosys_map map; -+ int ret; -+ -+ if (queue->syncwait.kmap) -+ return queue->syncwait.kmap + queue->syncwait.offset; -+ -+ bo = panthor_vm_get_bo_for_va(group->vm, -+ queue->syncwait.gpu_va, -+ &queue->syncwait.offset); -+ if (drm_WARN_ON(&ptdev->base, IS_ERR_OR_NULL(bo))) -+ goto err_put_syncwait_obj; -+ -+ queue->syncwait.obj = &bo->base.base; -+ ret = drm_gem_vmap_unlocked(queue->syncwait.obj, &map); -+ if (drm_WARN_ON(&ptdev->base, ret)) -+ goto err_put_syncwait_obj; -+ -+ queue->syncwait.kmap = map.vaddr; -+ if (drm_WARN_ON(&ptdev->base, !queue->syncwait.kmap)) -+ goto err_put_syncwait_obj; -+ -+ return queue->syncwait.kmap + queue->syncwait.offset; -+ -+err_put_syncwait_obj: -+ panthor_queue_put_syncwait_obj(queue); -+ return NULL; -+} -+ -+static void group_free_queue(struct panthor_group *group, struct panthor_queue *queue) -+{ -+ if (IS_ERR_OR_NULL(queue)) -+ return; -+ -+ if (queue->entity.fence_context) -+ drm_sched_entity_destroy(&queue->entity); -+ -+ if (queue->scheduler.ops) -+ drm_sched_fini(&queue->scheduler); -+ -+ panthor_queue_put_syncwait_obj(queue); -+ -+ panthor_kernel_bo_destroy(group->vm, queue->ringbuf); -+ panthor_kernel_bo_destroy(panthor_fw_vm(group->ptdev), queue->iface.mem); -+ -+ kfree(queue); -+} -+ -+static void group_release_work(struct work_struct *work) -+{ -+ struct panthor_group *group = container_of(work, -+ struct panthor_group, -+ release_work); -+ struct panthor_device *ptdev = group->ptdev; -+ u32 i; -+ -+ for (i = 0; i < group->queue_count; i++) -+ group_free_queue(group, group->queues[i]); -+ -+ panthor_kernel_bo_destroy(panthor_fw_vm(ptdev), group->suspend_buf); -+ panthor_kernel_bo_destroy(panthor_fw_vm(ptdev), group->protm_suspend_buf); -+ panthor_kernel_bo_destroy(group->vm, group->syncobjs); -+ -+ panthor_vm_put(group->vm); -+ kfree(group); -+} -+ -+static void group_release(struct kref *kref) -+{ -+ struct panthor_group *group = container_of(kref, -+ struct panthor_group, -+ refcount); -+ struct panthor_device *ptdev = group->ptdev; -+ -+ drm_WARN_ON(&ptdev->base, group->csg_id >= 0); -+ drm_WARN_ON(&ptdev->base, !list_empty(&group->run_node)); -+ drm_WARN_ON(&ptdev->base, !list_empty(&group->wait_node)); -+ -+ queue_work(panthor_cleanup_wq, &group->release_work); -+} -+ -+static void group_put(struct panthor_group *group) -+{ -+ if (group) -+ kref_put(&group->refcount, group_release); -+} -+ -+static struct panthor_group * -+group_get(struct panthor_group *group) -+{ -+ if (group) -+ kref_get(&group->refcount); -+ -+ return group; -+} -+ -+/** -+ * group_bind_locked() - Bind a group to a group slot -+ * @group: Group. -+ * @csg_id: Slot. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+static int -+group_bind_locked(struct panthor_group *group, u32 csg_id) -+{ -+ struct panthor_device *ptdev = group->ptdev; -+ struct panthor_csg_slot *csg_slot; -+ int ret; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ if (drm_WARN_ON(&ptdev->base, group->csg_id != -1 || csg_id >= MAX_CSGS || -+ ptdev->scheduler->csg_slots[csg_id].group)) -+ return -EINVAL; -+ -+ ret = panthor_vm_active(group->vm); -+ if (ret) -+ return ret; -+ -+ csg_slot = &ptdev->scheduler->csg_slots[csg_id]; -+ group_get(group); -+ group->csg_id = csg_id; -+ -+ /* Dummy doorbell allocation: doorbell is assigned to the group and -+ * all queues use the same doorbell. -+ * -+ * TODO: Implement LRU-based doorbell assignment, so the most often -+ * updated queues get their own doorbell, thus avoiding useless checks -+ * on queues belonging to the same group that are rarely updated. -+ */ -+ for (u32 i = 0; i < group->queue_count; i++) -+ group->queues[i]->doorbell_id = csg_id + 1; -+ -+ csg_slot->group = group; -+ -+ return 0; -+} -+ -+/** -+ * group_unbind_locked() - Unbind a group from a slot. -+ * @group: Group to unbind. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+static int -+group_unbind_locked(struct panthor_group *group) -+{ -+ struct panthor_device *ptdev = group->ptdev; -+ struct panthor_csg_slot *slot; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ if (drm_WARN_ON(&ptdev->base, group->csg_id < 0 || group->csg_id >= MAX_CSGS)) -+ return -EINVAL; -+ -+ if (drm_WARN_ON(&ptdev->base, group->state == PANTHOR_CS_GROUP_ACTIVE)) -+ return -EINVAL; -+ -+ slot = &ptdev->scheduler->csg_slots[group->csg_id]; -+ panthor_vm_idle(group->vm); -+ group->csg_id = -1; -+ -+ /* Tiler OOM events will be re-issued next time the group is scheduled. */ -+ atomic_set(&group->tiler_oom, 0); -+ cancel_work(&group->tiler_oom_work); -+ -+ for (u32 i = 0; i < group->queue_count; i++) -+ group->queues[i]->doorbell_id = -1; -+ -+ slot->group = NULL; -+ -+ group_put(group); -+ return 0; -+} -+ -+/** -+ * cs_slot_prog_locked() - Program a queue slot -+ * @ptdev: Device. -+ * @csg_id: Group slot ID. -+ * @cs_id: Queue slot ID. -+ * -+ * Program a queue slot with the queue information so things can start being -+ * executed on this queue. -+ * -+ * The group slot must have a group bound to it already (group_bind_locked()). -+ */ -+static void -+cs_slot_prog_locked(struct panthor_device *ptdev, u32 csg_id, u32 cs_id) -+{ -+ struct panthor_queue *queue = ptdev->scheduler->csg_slots[csg_id].group->queues[cs_id]; -+ struct panthor_fw_cs_iface *cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ queue->iface.input->extract = queue->iface.output->extract; -+ drm_WARN_ON(&ptdev->base, queue->iface.input->insert < queue->iface.input->extract); -+ -+ cs_iface->input->ringbuf_base = panthor_kernel_bo_gpuva(queue->ringbuf); -+ cs_iface->input->ringbuf_size = panthor_kernel_bo_size(queue->ringbuf); -+ cs_iface->input->ringbuf_input = queue->iface.input_fw_va; -+ cs_iface->input->ringbuf_output = queue->iface.output_fw_va; -+ cs_iface->input->config = CS_CONFIG_PRIORITY(queue->priority) | -+ CS_CONFIG_DOORBELL(queue->doorbell_id); -+ cs_iface->input->ack_irq_mask = ~0; -+ panthor_fw_update_reqs(cs_iface, req, -+ CS_IDLE_SYNC_WAIT | -+ CS_IDLE_EMPTY | -+ CS_STATE_START | -+ CS_EXTRACT_EVENT, -+ CS_IDLE_SYNC_WAIT | -+ CS_IDLE_EMPTY | -+ CS_STATE_MASK | -+ CS_EXTRACT_EVENT); -+ if (queue->iface.input->insert != queue->iface.input->extract && queue->timeout_suspended) { -+ drm_sched_resume_timeout(&queue->scheduler, queue->remaining_time); -+ queue->timeout_suspended = false; -+ } -+} -+ -+/** -+ * @cs_slot_reset_locked() - Reset a queue slot -+ * @ptdev: Device. -+ * @csg_id: Group slot. -+ * @cs_id: Queue slot. -+ * -+ * Change the queue slot state to STOP and suspend the queue timeout if -+ * the queue is not blocked. -+ * -+ * The group slot must have a group bound to it (group_bind_locked()). -+ */ -+static int -+cs_slot_reset_locked(struct panthor_device *ptdev, u32 csg_id, u32 cs_id) -+{ -+ struct panthor_fw_cs_iface *cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); -+ struct panthor_group *group = ptdev->scheduler->csg_slots[csg_id].group; -+ struct panthor_queue *queue = group->queues[cs_id]; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ panthor_fw_update_reqs(cs_iface, req, -+ CS_STATE_STOP, -+ CS_STATE_MASK); -+ -+ /* If the queue is blocked, we want to keep the timeout running, so -+ * we can detect unbounded waits and kill the group when that happens. -+ */ -+ if (!(group->blocked_queues & BIT(cs_id)) && !queue->timeout_suspended) { -+ queue->remaining_time = drm_sched_suspend_timeout(&queue->scheduler); -+ queue->timeout_suspended = true; -+ WARN_ON(queue->remaining_time > msecs_to_jiffies(JOB_TIMEOUT_MS)); -+ } -+ -+ return 0; -+} -+ -+/** -+ * csg_slot_sync_priority_locked() - Synchronize the group slot priority -+ * @ptdev: Device. -+ * @csg_id: Group slot ID. -+ * -+ * Group slot priority update happens asynchronously. When we receive a -+ * %CSG_ENDPOINT_CONFIG, we know the update is effective, and can -+ * reflect it to our panthor_csg_slot object. -+ */ -+static void -+csg_slot_sync_priority_locked(struct panthor_device *ptdev, u32 csg_id) -+{ -+ struct panthor_csg_slot *csg_slot = &ptdev->scheduler->csg_slots[csg_id]; -+ struct panthor_fw_csg_iface *csg_iface; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); -+ csg_slot->priority = (csg_iface->input->endpoint_req & CSG_EP_REQ_PRIORITY_MASK) >> 28; -+} -+ -+/** -+ * cs_slot_sync_queue_state_locked() - Synchronize the queue slot priority -+ * @ptdev: Device. -+ * @csg_id: Group slot. -+ * @cs_id: Queue slot. -+ * -+ * Queue state is updated on group suspend or STATUS_UPDATE event. -+ */ -+static void -+cs_slot_sync_queue_state_locked(struct panthor_device *ptdev, u32 csg_id, u32 cs_id) -+{ -+ struct panthor_group *group = ptdev->scheduler->csg_slots[csg_id].group; -+ struct panthor_queue *queue = group->queues[cs_id]; -+ struct panthor_fw_cs_iface *cs_iface = -+ panthor_fw_get_cs_iface(group->ptdev, csg_id, cs_id); -+ -+ u32 status_wait_cond; -+ -+ switch (cs_iface->output->status_blocked_reason) { -+ case CS_STATUS_BLOCKED_REASON_UNBLOCKED: -+ if (queue->iface.input->insert == queue->iface.output->extract && -+ cs_iface->output->status_scoreboards == 0) -+ group->idle_queues |= BIT(cs_id); -+ break; -+ -+ case CS_STATUS_BLOCKED_REASON_SYNC_WAIT: -+ if (list_empty(&group->wait_node)) { -+ list_move_tail(&group->wait_node, -+ &group->ptdev->scheduler->groups.waiting); -+ } -+ group->blocked_queues |= BIT(cs_id); -+ queue->syncwait.gpu_va = cs_iface->output->status_wait_sync_ptr; -+ queue->syncwait.ref = cs_iface->output->status_wait_sync_value; -+ status_wait_cond = cs_iface->output->status_wait & CS_STATUS_WAIT_SYNC_COND_MASK; -+ queue->syncwait.gt = status_wait_cond == CS_STATUS_WAIT_SYNC_COND_GT; -+ if (cs_iface->output->status_wait & CS_STATUS_WAIT_SYNC_64B) { -+ u64 sync_val_hi = cs_iface->output->status_wait_sync_value_hi; -+ -+ queue->syncwait.sync64 = true; -+ queue->syncwait.ref |= sync_val_hi << 32; -+ } else { -+ queue->syncwait.sync64 = false; -+ } -+ break; -+ -+ default: -+ /* Other reasons are not blocking. Consider the queue as runnable -+ * in those cases. -+ */ -+ break; -+ } -+} -+ -+static void -+csg_slot_sync_queues_state_locked(struct panthor_device *ptdev, u32 csg_id) -+{ -+ struct panthor_csg_slot *csg_slot = &ptdev->scheduler->csg_slots[csg_id]; -+ struct panthor_group *group = csg_slot->group; -+ u32 i; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ group->idle_queues = 0; -+ group->blocked_queues = 0; -+ -+ for (i = 0; i < group->queue_count; i++) { -+ if (group->queues[i]) -+ cs_slot_sync_queue_state_locked(ptdev, csg_id, i); -+ } -+} -+ -+static void -+csg_slot_sync_state_locked(struct panthor_device *ptdev, u32 csg_id) -+{ -+ struct panthor_csg_slot *csg_slot = &ptdev->scheduler->csg_slots[csg_id]; -+ struct panthor_fw_csg_iface *csg_iface; -+ struct panthor_group *group; -+ enum panthor_group_state new_state, old_state; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); -+ group = csg_slot->group; -+ -+ if (!group) -+ return; -+ -+ old_state = group->state; -+ switch (csg_iface->output->ack & CSG_STATE_MASK) { -+ case CSG_STATE_START: -+ case CSG_STATE_RESUME: -+ new_state = PANTHOR_CS_GROUP_ACTIVE; -+ break; -+ case CSG_STATE_TERMINATE: -+ new_state = PANTHOR_CS_GROUP_TERMINATED; -+ break; -+ case CSG_STATE_SUSPEND: -+ new_state = PANTHOR_CS_GROUP_SUSPENDED; -+ break; -+ } -+ -+ if (old_state == new_state) -+ return; -+ -+ if (new_state == PANTHOR_CS_GROUP_SUSPENDED) -+ csg_slot_sync_queues_state_locked(ptdev, csg_id); -+ -+ if (old_state == PANTHOR_CS_GROUP_ACTIVE) { -+ u32 i; -+ -+ /* Reset the queue slots so we start from a clean -+ * state when starting/resuming a new group on this -+ * CSG slot. No wait needed here, and no ringbell -+ * either, since the CS slot will only be re-used -+ * on the next CSG start operation. -+ */ -+ for (i = 0; i < group->queue_count; i++) { -+ if (group->queues[i]) -+ cs_slot_reset_locked(ptdev, csg_id, i); -+ } -+ } -+ -+ group->state = new_state; -+} -+ -+static int -+csg_slot_prog_locked(struct panthor_device *ptdev, u32 csg_id, u32 priority) -+{ -+ struct panthor_fw_csg_iface *csg_iface; -+ struct panthor_csg_slot *csg_slot; -+ struct panthor_group *group; -+ u32 queue_mask = 0, i; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ if (priority > MAX_CSG_PRIO) -+ return -EINVAL; -+ -+ if (drm_WARN_ON(&ptdev->base, csg_id >= MAX_CSGS)) -+ return -EINVAL; -+ -+ csg_slot = &ptdev->scheduler->csg_slots[csg_id]; -+ group = csg_slot->group; -+ if (!group || group->state == PANTHOR_CS_GROUP_ACTIVE) -+ return 0; -+ -+ csg_iface = panthor_fw_get_csg_iface(group->ptdev, csg_id); -+ -+ for (i = 0; i < group->queue_count; i++) { -+ if (group->queues[i]) { -+ cs_slot_prog_locked(ptdev, csg_id, i); -+ queue_mask |= BIT(i); -+ } -+ } -+ -+ csg_iface->input->allow_compute = group->compute_core_mask; -+ csg_iface->input->allow_fragment = group->fragment_core_mask; -+ csg_iface->input->allow_other = group->tiler_core_mask; -+ csg_iface->input->endpoint_req = CSG_EP_REQ_COMPUTE(group->max_compute_cores) | -+ CSG_EP_REQ_FRAGMENT(group->max_fragment_cores) | -+ CSG_EP_REQ_TILER(group->max_tiler_cores) | -+ CSG_EP_REQ_PRIORITY(priority); -+ csg_iface->input->config = panthor_vm_as(group->vm); -+ -+ if (group->suspend_buf) -+ csg_iface->input->suspend_buf = panthor_kernel_bo_gpuva(group->suspend_buf); -+ else -+ csg_iface->input->suspend_buf = 0; -+ -+ if (group->protm_suspend_buf) { -+ csg_iface->input->protm_suspend_buf = -+ panthor_kernel_bo_gpuva(group->protm_suspend_buf); -+ } else { -+ csg_iface->input->protm_suspend_buf = 0; -+ } -+ -+ csg_iface->input->ack_irq_mask = ~0; -+ panthor_fw_toggle_reqs(csg_iface, doorbell_req, doorbell_ack, queue_mask); -+ return 0; -+} -+ -+static void -+cs_slot_process_fatal_event_locked(struct panthor_device *ptdev, -+ u32 csg_id, u32 cs_id) -+{ -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; -+ struct panthor_group *group = csg_slot->group; -+ struct panthor_fw_cs_iface *cs_iface; -+ u32 fatal; -+ u64 info; -+ -+ lockdep_assert_held(&sched->lock); -+ -+ cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); -+ fatal = cs_iface->output->fatal; -+ info = cs_iface->output->fatal_info; -+ -+ if (group) -+ group->fatal_queues |= BIT(cs_id); -+ -+ sched_queue_delayed_work(sched, tick, 0); -+ drm_warn(&ptdev->base, -+ "CSG slot %d CS slot: %d\n" -+ "CS_FATAL.EXCEPTION_TYPE: 0x%x (%s)\n" -+ "CS_FATAL.EXCEPTION_DATA: 0x%x\n" -+ "CS_FATAL_INFO.EXCEPTION_DATA: 0x%llx\n", -+ csg_id, cs_id, -+ (unsigned int)CS_EXCEPTION_TYPE(fatal), -+ panthor_exception_name(ptdev, CS_EXCEPTION_TYPE(fatal)), -+ (unsigned int)CS_EXCEPTION_DATA(fatal), -+ info); -+} -+ -+static void -+cs_slot_process_fault_event_locked(struct panthor_device *ptdev, -+ u32 csg_id, u32 cs_id) -+{ -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; -+ struct panthor_group *group = csg_slot->group; -+ struct panthor_queue *queue = group && cs_id < group->queue_count ? -+ group->queues[cs_id] : NULL; -+ struct panthor_fw_cs_iface *cs_iface; -+ u32 fault; -+ u64 info; -+ -+ lockdep_assert_held(&sched->lock); -+ -+ cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); -+ fault = cs_iface->output->fault; -+ info = cs_iface->output->fault_info; -+ -+ if (queue && CS_EXCEPTION_TYPE(fault) == DRM_PANTHOR_EXCEPTION_CS_INHERIT_FAULT) { -+ u64 cs_extract = queue->iface.output->extract; -+ struct panthor_job *job; -+ -+ spin_lock(&queue->fence_ctx.lock); -+ list_for_each_entry(job, &queue->fence_ctx.in_flight_jobs, node) { -+ if (cs_extract >= job->ringbuf.end) -+ continue; -+ -+ if (cs_extract < job->ringbuf.start) -+ break; -+ -+ dma_fence_set_error(job->done_fence, -EINVAL); -+ } -+ spin_unlock(&queue->fence_ctx.lock); -+ } -+ -+ drm_warn(&ptdev->base, -+ "CSG slot %d CS slot: %d\n" -+ "CS_FAULT.EXCEPTION_TYPE: 0x%x (%s)\n" -+ "CS_FAULT.EXCEPTION_DATA: 0x%x\n" -+ "CS_FAULT_INFO.EXCEPTION_DATA: 0x%llx\n", -+ csg_id, cs_id, -+ (unsigned int)CS_EXCEPTION_TYPE(fault), -+ panthor_exception_name(ptdev, CS_EXCEPTION_TYPE(fault)), -+ (unsigned int)CS_EXCEPTION_DATA(fault), -+ info); -+} -+ -+static int group_process_tiler_oom(struct panthor_group *group, u32 cs_id) -+{ -+ struct panthor_device *ptdev = group->ptdev; -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ u32 renderpasses_in_flight, pending_frag_count; -+ struct panthor_heap_pool *heaps = NULL; -+ u64 heap_address, new_chunk_va = 0; -+ u32 vt_start, vt_end, frag_end; -+ int ret, csg_id; -+ -+ mutex_lock(&sched->lock); -+ csg_id = group->csg_id; -+ if (csg_id >= 0) { -+ struct panthor_fw_cs_iface *cs_iface; -+ -+ cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); -+ heaps = panthor_vm_get_heap_pool(group->vm, false); -+ heap_address = cs_iface->output->heap_address; -+ vt_start = cs_iface->output->heap_vt_start; -+ vt_end = cs_iface->output->heap_vt_end; -+ frag_end = cs_iface->output->heap_frag_end; -+ renderpasses_in_flight = vt_start - frag_end; -+ pending_frag_count = vt_end - frag_end; -+ } -+ mutex_unlock(&sched->lock); -+ -+ /* The group got scheduled out, we stop here. We will get a new tiler OOM event -+ * when it's scheduled again. -+ */ -+ if (unlikely(csg_id < 0)) -+ return 0; -+ -+ if (!heaps || frag_end > vt_end || vt_end >= vt_start) { -+ ret = -EINVAL; -+ } else { -+ /* We do the allocation without holding the scheduler lock to avoid -+ * blocking the scheduling. -+ */ -+ ret = panthor_heap_grow(heaps, heap_address, -+ renderpasses_in_flight, -+ pending_frag_count, &new_chunk_va); -+ } -+ -+ if (ret && ret != -EBUSY) { -+ drm_warn(&ptdev->base, "Failed to extend the tiler heap\n"); -+ group->fatal_queues |= BIT(cs_id); -+ sched_queue_delayed_work(sched, tick, 0); -+ goto out_put_heap_pool; -+ } -+ -+ mutex_lock(&sched->lock); -+ csg_id = group->csg_id; -+ if (csg_id >= 0) { -+ struct panthor_fw_csg_iface *csg_iface; -+ struct panthor_fw_cs_iface *cs_iface; -+ -+ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); -+ cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); -+ -+ cs_iface->input->heap_start = new_chunk_va; -+ cs_iface->input->heap_end = new_chunk_va; -+ panthor_fw_update_reqs(cs_iface, req, cs_iface->output->ack, CS_TILER_OOM); -+ panthor_fw_toggle_reqs(csg_iface, doorbell_req, doorbell_ack, BIT(cs_id)); -+ panthor_fw_ring_csg_doorbells(ptdev, BIT(csg_id)); -+ } -+ mutex_unlock(&sched->lock); -+ -+ /* We allocated a chunck, but couldn't link it to the heap -+ * context because the group was scheduled out while we were -+ * allocating memory. We need to return this chunk to the heap. -+ */ -+ if (unlikely(csg_id < 0 && new_chunk_va)) -+ panthor_heap_return_chunk(heaps, heap_address, new_chunk_va); -+ -+ ret = 0; -+ -+out_put_heap_pool: -+ panthor_heap_pool_put(heaps); -+ return ret; -+} -+ -+static void group_tiler_oom_work(struct work_struct *work) -+{ -+ struct panthor_group *group = -+ container_of(work, struct panthor_group, tiler_oom_work); -+ u32 tiler_oom = atomic_xchg(&group->tiler_oom, 0); -+ -+ while (tiler_oom) { -+ u32 cs_id = ffs(tiler_oom) - 1; -+ -+ group_process_tiler_oom(group, cs_id); -+ tiler_oom &= ~BIT(cs_id); -+ } -+ -+ group_put(group); -+} -+ -+static void -+cs_slot_process_tiler_oom_event_locked(struct panthor_device *ptdev, -+ u32 csg_id, u32 cs_id) -+{ -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; -+ struct panthor_group *group = csg_slot->group; -+ -+ lockdep_assert_held(&sched->lock); -+ -+ if (drm_WARN_ON(&ptdev->base, !group)) -+ return; -+ -+ atomic_or(BIT(cs_id), &group->tiler_oom); -+ -+ /* We don't use group_queue_work() here because we want to queue the -+ * work item to the heap_alloc_wq. -+ */ -+ group_get(group); -+ if (!queue_work(sched->heap_alloc_wq, &group->tiler_oom_work)) -+ group_put(group); -+} -+ -+static bool cs_slot_process_irq_locked(struct panthor_device *ptdev, -+ u32 csg_id, u32 cs_id) -+{ -+ struct panthor_fw_cs_iface *cs_iface; -+ u32 req, ack, events; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); -+ req = cs_iface->input->req; -+ ack = cs_iface->output->ack; -+ events = (req ^ ack) & CS_EVT_MASK; -+ -+ if (events & CS_FATAL) -+ cs_slot_process_fatal_event_locked(ptdev, csg_id, cs_id); -+ -+ if (events & CS_FAULT) -+ cs_slot_process_fault_event_locked(ptdev, csg_id, cs_id); -+ -+ if (events & CS_TILER_OOM) -+ cs_slot_process_tiler_oom_event_locked(ptdev, csg_id, cs_id); -+ -+ /* We don't acknowledge the TILER_OOM event since its handling is -+ * deferred to a separate work. -+ */ -+ panthor_fw_update_reqs(cs_iface, req, ack, CS_FATAL | CS_FAULT); -+ -+ return (events & (CS_FAULT | CS_TILER_OOM)) != 0; -+} -+ -+static void csg_slot_sync_idle_state_locked(struct panthor_device *ptdev, u32 csg_id) -+{ -+ struct panthor_csg_slot *csg_slot = &ptdev->scheduler->csg_slots[csg_id]; -+ struct panthor_fw_csg_iface *csg_iface; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); -+ csg_slot->idle = csg_iface->output->status_state & CSG_STATUS_STATE_IS_IDLE; -+} -+ -+static void csg_slot_process_idle_event_locked(struct panthor_device *ptdev, u32 csg_id) -+{ -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ -+ lockdep_assert_held(&sched->lock); -+ -+ sched->might_have_idle_groups = true; -+ -+ /* Schedule a tick so we can evict idle groups and schedule non-idle -+ * ones. This will also update runtime PM and devfreq busy/idle states, -+ * so the device can lower its frequency or get suspended. -+ */ -+ sched_queue_delayed_work(sched, tick, 0); -+} -+ -+static void csg_slot_sync_update_locked(struct panthor_device *ptdev, -+ u32 csg_id) -+{ -+ struct panthor_csg_slot *csg_slot = &ptdev->scheduler->csg_slots[csg_id]; -+ struct panthor_group *group = csg_slot->group; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ if (group) -+ group_queue_work(group, sync_upd); -+ -+ sched_queue_work(ptdev->scheduler, sync_upd); -+} -+ -+static void -+csg_slot_process_progress_timer_event_locked(struct panthor_device *ptdev, u32 csg_id) -+{ -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; -+ struct panthor_group *group = csg_slot->group; -+ -+ lockdep_assert_held(&sched->lock); -+ -+ drm_warn(&ptdev->base, "CSG slot %d progress timeout\n", csg_id); -+ -+ group = csg_slot->group; -+ if (!drm_WARN_ON(&ptdev->base, !group)) -+ group->timedout = true; -+ -+ sched_queue_delayed_work(sched, tick, 0); -+} -+ -+static void sched_process_csg_irq_locked(struct panthor_device *ptdev, u32 csg_id) -+{ -+ u32 req, ack, cs_irq_req, cs_irq_ack, cs_irqs, csg_events; -+ struct panthor_fw_csg_iface *csg_iface; -+ u32 ring_cs_db_mask = 0; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ if (drm_WARN_ON(&ptdev->base, csg_id >= ptdev->scheduler->csg_slot_count)) -+ return; -+ -+ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); -+ req = READ_ONCE(csg_iface->input->req); -+ ack = READ_ONCE(csg_iface->output->ack); -+ cs_irq_req = READ_ONCE(csg_iface->output->cs_irq_req); -+ cs_irq_ack = READ_ONCE(csg_iface->input->cs_irq_ack); -+ csg_events = (req ^ ack) & CSG_EVT_MASK; -+ -+ /* There may not be any pending CSG/CS interrupts to process */ -+ if (req == ack && cs_irq_req == cs_irq_ack) -+ return; -+ -+ /* Immediately set IRQ_ACK bits to be same as the IRQ_REQ bits before -+ * examining the CS_ACK & CS_REQ bits. This would ensure that Host -+ * doesn't miss an interrupt for the CS in the race scenario where -+ * whilst Host is servicing an interrupt for the CS, firmware sends -+ * another interrupt for that CS. -+ */ -+ csg_iface->input->cs_irq_ack = cs_irq_req; -+ -+ panthor_fw_update_reqs(csg_iface, req, ack, -+ CSG_SYNC_UPDATE | -+ CSG_IDLE | -+ CSG_PROGRESS_TIMER_EVENT); -+ -+ if (csg_events & CSG_IDLE) -+ csg_slot_process_idle_event_locked(ptdev, csg_id); -+ -+ if (csg_events & CSG_PROGRESS_TIMER_EVENT) -+ csg_slot_process_progress_timer_event_locked(ptdev, csg_id); -+ -+ cs_irqs = cs_irq_req ^ cs_irq_ack; -+ while (cs_irqs) { -+ u32 cs_id = ffs(cs_irqs) - 1; -+ -+ if (cs_slot_process_irq_locked(ptdev, csg_id, cs_id)) -+ ring_cs_db_mask |= BIT(cs_id); -+ -+ cs_irqs &= ~BIT(cs_id); -+ } -+ -+ if (csg_events & CSG_SYNC_UPDATE) -+ csg_slot_sync_update_locked(ptdev, csg_id); -+ -+ if (ring_cs_db_mask) -+ panthor_fw_toggle_reqs(csg_iface, doorbell_req, doorbell_ack, ring_cs_db_mask); -+ -+ panthor_fw_ring_csg_doorbells(ptdev, BIT(csg_id)); -+} -+ -+static void sched_process_idle_event_locked(struct panthor_device *ptdev) -+{ -+ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ /* Acknowledge the idle event and schedule a tick. */ -+ panthor_fw_update_reqs(glb_iface, req, glb_iface->output->ack, GLB_IDLE); -+ sched_queue_delayed_work(ptdev->scheduler, tick, 0); -+} -+ -+/** -+ * panthor_sched_process_global_irq() - Process the scheduling part of a global IRQ -+ * @ptdev: Device. -+ */ -+static void sched_process_global_irq_locked(struct panthor_device *ptdev) -+{ -+ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); -+ u32 req, ack, evts; -+ -+ lockdep_assert_held(&ptdev->scheduler->lock); -+ -+ req = READ_ONCE(glb_iface->input->req); -+ ack = READ_ONCE(glb_iface->output->ack); -+ evts = (req ^ ack) & GLB_EVT_MASK; -+ -+ if (evts & GLB_IDLE) -+ sched_process_idle_event_locked(ptdev); -+} -+ -+static void process_fw_events_work(struct work_struct *work) -+{ -+ struct panthor_scheduler *sched = container_of(work, struct panthor_scheduler, -+ fw_events_work); -+ u32 events = atomic_xchg(&sched->fw_events, 0); -+ struct panthor_device *ptdev = sched->ptdev; -+ -+ mutex_lock(&sched->lock); -+ -+ if (events & JOB_INT_GLOBAL_IF) { -+ sched_process_global_irq_locked(ptdev); -+ events &= ~JOB_INT_GLOBAL_IF; -+ } -+ -+ while (events) { -+ u32 csg_id = ffs(events) - 1; -+ -+ sched_process_csg_irq_locked(ptdev, csg_id); -+ events &= ~BIT(csg_id); -+ } -+ -+ mutex_unlock(&sched->lock); -+} -+ -+/** -+ * panthor_sched_report_fw_events() - Report FW events to the scheduler. -+ */ -+void panthor_sched_report_fw_events(struct panthor_device *ptdev, u32 events) -+{ -+ if (!ptdev->scheduler) -+ return; -+ -+ atomic_or(events, &ptdev->scheduler->fw_events); -+ sched_queue_work(ptdev->scheduler, fw_events); -+} -+ -+static const char *fence_get_driver_name(struct dma_fence *fence) -+{ -+ return "panthor"; -+} -+ -+static const char *queue_fence_get_timeline_name(struct dma_fence *fence) -+{ -+ return "queue-fence"; -+} -+ -+static const struct dma_fence_ops panthor_queue_fence_ops = { -+ .get_driver_name = fence_get_driver_name, -+ .get_timeline_name = queue_fence_get_timeline_name, -+}; -+ -+/** -+ */ -+struct panthor_csg_slots_upd_ctx { -+ u32 update_mask; -+ u32 timedout_mask; -+ struct { -+ u32 value; -+ u32 mask; -+ } requests[MAX_CSGS]; -+}; -+ -+static void csgs_upd_ctx_init(struct panthor_csg_slots_upd_ctx *ctx) -+{ -+ memset(ctx, 0, sizeof(*ctx)); -+} -+ -+static void csgs_upd_ctx_queue_reqs(struct panthor_device *ptdev, -+ struct panthor_csg_slots_upd_ctx *ctx, -+ u32 csg_id, u32 value, u32 mask) -+{ -+ if (drm_WARN_ON(&ptdev->base, !mask) || -+ drm_WARN_ON(&ptdev->base, csg_id >= ptdev->scheduler->csg_slot_count)) -+ return; -+ -+ ctx->requests[csg_id].value = (ctx->requests[csg_id].value & ~mask) | (value & mask); -+ ctx->requests[csg_id].mask |= mask; -+ ctx->update_mask |= BIT(csg_id); -+} -+ -+static int csgs_upd_ctx_apply_locked(struct panthor_device *ptdev, -+ struct panthor_csg_slots_upd_ctx *ctx) -+{ -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ u32 update_slots = ctx->update_mask; -+ -+ lockdep_assert_held(&sched->lock); -+ -+ if (!ctx->update_mask) -+ return 0; -+ -+ while (update_slots) { -+ struct panthor_fw_csg_iface *csg_iface; -+ u32 csg_id = ffs(update_slots) - 1; -+ -+ update_slots &= ~BIT(csg_id); -+ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); -+ panthor_fw_update_reqs(csg_iface, req, -+ ctx->requests[csg_id].value, -+ ctx->requests[csg_id].mask); -+ } -+ -+ panthor_fw_ring_csg_doorbells(ptdev, ctx->update_mask); -+ -+ update_slots = ctx->update_mask; -+ while (update_slots) { -+ struct panthor_fw_csg_iface *csg_iface; -+ u32 csg_id = ffs(update_slots) - 1; -+ u32 req_mask = ctx->requests[csg_id].mask, acked; -+ int ret; -+ -+ update_slots &= ~BIT(csg_id); -+ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); -+ -+ ret = panthor_fw_csg_wait_acks(ptdev, csg_id, req_mask, &acked, 100); -+ -+ if (acked & CSG_ENDPOINT_CONFIG) -+ csg_slot_sync_priority_locked(ptdev, csg_id); -+ -+ if (acked & CSG_STATE_MASK) -+ csg_slot_sync_state_locked(ptdev, csg_id); -+ -+ if (acked & CSG_STATUS_UPDATE) { -+ csg_slot_sync_queues_state_locked(ptdev, csg_id); -+ csg_slot_sync_idle_state_locked(ptdev, csg_id); -+ } -+ -+ if (ret && acked != req_mask && -+ ((csg_iface->input->req ^ csg_iface->output->ack) & req_mask) != 0) { -+ drm_err(&ptdev->base, "CSG %d update request timedout", csg_id); -+ ctx->timedout_mask |= BIT(csg_id); -+ } -+ } -+ -+ if (ctx->timedout_mask) -+ return -ETIMEDOUT; -+ -+ return 0; -+} -+ -+struct panthor_sched_tick_ctx { -+ struct list_head old_groups[PANTHOR_CSG_PRIORITY_COUNT]; -+ struct list_head groups[PANTHOR_CSG_PRIORITY_COUNT]; -+ u32 idle_group_count; -+ u32 group_count; -+ enum panthor_csg_priority min_priority; -+ struct panthor_vm *vms[MAX_CS_PER_CSG]; -+ u32 as_count; -+ bool immediate_tick; -+ u32 csg_upd_failed_mask; -+}; -+ -+static bool -+tick_ctx_is_full(const struct panthor_scheduler *sched, -+ const struct panthor_sched_tick_ctx *ctx) -+{ -+ return ctx->group_count == sched->csg_slot_count; -+} -+ -+static bool -+group_is_idle(struct panthor_group *group) -+{ -+ struct panthor_device *ptdev = group->ptdev; -+ u32 inactive_queues; -+ -+ if (group->csg_id >= 0) -+ return ptdev->scheduler->csg_slots[group->csg_id].idle; -+ -+ inactive_queues = group->idle_queues | group->blocked_queues; -+ return hweight32(inactive_queues) == group->queue_count; -+} -+ -+static bool -+group_can_run(struct panthor_group *group) -+{ -+ return group->state != PANTHOR_CS_GROUP_TERMINATED && -+ !group->destroyed && group->fatal_queues == 0 && -+ !group->timedout; -+} -+ -+static void -+tick_ctx_pick_groups_from_list(const struct panthor_scheduler *sched, -+ struct panthor_sched_tick_ctx *ctx, -+ struct list_head *queue, -+ bool skip_idle_groups, -+ bool owned_by_tick_ctx) -+{ -+ struct panthor_group *group, *tmp; -+ -+ if (tick_ctx_is_full(sched, ctx)) -+ return; -+ -+ list_for_each_entry_safe(group, tmp, queue, run_node) { -+ u32 i; -+ -+ if (!group_can_run(group)) -+ continue; -+ -+ if (skip_idle_groups && group_is_idle(group)) -+ continue; -+ -+ for (i = 0; i < ctx->as_count; i++) { -+ if (ctx->vms[i] == group->vm) -+ break; -+ } -+ -+ if (i == ctx->as_count && ctx->as_count == sched->as_slot_count) -+ continue; -+ -+ if (!owned_by_tick_ctx) -+ group_get(group); -+ -+ list_move_tail(&group->run_node, &ctx->groups[group->priority]); -+ ctx->group_count++; -+ if (group_is_idle(group)) -+ ctx->idle_group_count++; -+ -+ if (i == ctx->as_count) -+ ctx->vms[ctx->as_count++] = group->vm; -+ -+ if (ctx->min_priority > group->priority) -+ ctx->min_priority = group->priority; -+ -+ if (tick_ctx_is_full(sched, ctx)) -+ return; -+ } -+} -+ -+static void -+tick_ctx_insert_old_group(struct panthor_scheduler *sched, -+ struct panthor_sched_tick_ctx *ctx, -+ struct panthor_group *group, -+ bool full_tick) -+{ -+ struct panthor_csg_slot *csg_slot = &sched->csg_slots[group->csg_id]; -+ struct panthor_group *other_group; -+ -+ if (!full_tick) { -+ list_add_tail(&group->run_node, &ctx->old_groups[group->priority]); -+ return; -+ } -+ -+ /* Rotate to make sure groups with lower CSG slot -+ * priorities have a chance to get a higher CSG slot -+ * priority next time they get picked. This priority -+ * has an impact on resource request ordering, so it's -+ * important to make sure we don't let one group starve -+ * all other groups with the same group priority. -+ */ -+ list_for_each_entry(other_group, -+ &ctx->old_groups[csg_slot->group->priority], -+ run_node) { -+ struct panthor_csg_slot *other_csg_slot = &sched->csg_slots[other_group->csg_id]; -+ -+ if (other_csg_slot->priority > csg_slot->priority) { -+ list_add_tail(&csg_slot->group->run_node, &other_group->run_node); -+ return; -+ } -+ } -+ -+ list_add_tail(&group->run_node, &ctx->old_groups[group->priority]); -+} -+ -+static void -+tick_ctx_init(struct panthor_scheduler *sched, -+ struct panthor_sched_tick_ctx *ctx, -+ bool full_tick) -+{ -+ struct panthor_device *ptdev = sched->ptdev; -+ struct panthor_csg_slots_upd_ctx upd_ctx; -+ int ret; -+ u32 i; -+ -+ memset(ctx, 0, sizeof(*ctx)); -+ csgs_upd_ctx_init(&upd_ctx); -+ -+ ctx->min_priority = PANTHOR_CSG_PRIORITY_COUNT; -+ for (i = 0; i < ARRAY_SIZE(ctx->groups); i++) { -+ INIT_LIST_HEAD(&ctx->groups[i]); -+ INIT_LIST_HEAD(&ctx->old_groups[i]); -+ } -+ -+ for (i = 0; i < sched->csg_slot_count; i++) { -+ struct panthor_csg_slot *csg_slot = &sched->csg_slots[i]; -+ struct panthor_group *group = csg_slot->group; -+ struct panthor_fw_csg_iface *csg_iface; -+ -+ if (!group) -+ continue; -+ -+ csg_iface = panthor_fw_get_csg_iface(ptdev, i); -+ group_get(group); -+ -+ /* If there was unhandled faults on the VM, force processing of -+ * CSG IRQs, so we can flag the faulty queue. -+ */ -+ if (panthor_vm_has_unhandled_faults(group->vm)) { -+ sched_process_csg_irq_locked(ptdev, i); -+ -+ /* No fatal fault reported, flag all queues as faulty. */ -+ if (!group->fatal_queues) -+ group->fatal_queues |= GENMASK(group->queue_count - 1, 0); -+ } -+ -+ tick_ctx_insert_old_group(sched, ctx, group, full_tick); -+ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, i, -+ csg_iface->output->ack ^ CSG_STATUS_UPDATE, -+ CSG_STATUS_UPDATE); -+ } -+ -+ ret = csgs_upd_ctx_apply_locked(ptdev, &upd_ctx); -+ if (ret) { -+ panthor_device_schedule_reset(ptdev); -+ ctx->csg_upd_failed_mask |= upd_ctx.timedout_mask; -+ } -+} -+ -+#define NUM_INSTRS_PER_SLOT 16 -+ -+static void -+group_term_post_processing(struct panthor_group *group) -+{ -+ struct panthor_job *job, *tmp; -+ LIST_HEAD(faulty_jobs); -+ bool cookie; -+ u32 i = 0; -+ -+ if (drm_WARN_ON(&group->ptdev->base, group_can_run(group))) -+ return; -+ -+ cookie = dma_fence_begin_signalling(); -+ for (i = 0; i < group->queue_count; i++) { -+ struct panthor_queue *queue = group->queues[i]; -+ struct panthor_syncobj_64b *syncobj; -+ int err; -+ -+ if (group->fatal_queues & BIT(i)) -+ err = -EINVAL; -+ else if (group->timedout) -+ err = -ETIMEDOUT; -+ else -+ err = -ECANCELED; -+ -+ if (!queue) -+ continue; -+ -+ spin_lock(&queue->fence_ctx.lock); -+ list_for_each_entry_safe(job, tmp, &queue->fence_ctx.in_flight_jobs, node) { -+ list_move_tail(&job->node, &faulty_jobs); -+ dma_fence_set_error(job->done_fence, err); -+ dma_fence_signal_locked(job->done_fence); -+ } -+ spin_unlock(&queue->fence_ctx.lock); -+ -+ /* Manually update the syncobj seqno to unblock waiters. */ -+ syncobj = group->syncobjs->kmap + (i * sizeof(*syncobj)); -+ syncobj->status = ~0; -+ syncobj->seqno = atomic64_read(&queue->fence_ctx.seqno); -+ sched_queue_work(group->ptdev->scheduler, sync_upd); -+ } -+ dma_fence_end_signalling(cookie); -+ -+ list_for_each_entry_safe(job, tmp, &faulty_jobs, node) { -+ list_del_init(&job->node); -+ panthor_job_put(&job->base); -+ } -+} -+ -+static void group_term_work(struct work_struct *work) -+{ -+ struct panthor_group *group = -+ container_of(work, struct panthor_group, term_work); -+ -+ group_term_post_processing(group); -+ group_put(group); -+} -+ -+static void -+tick_ctx_cleanup(struct panthor_scheduler *sched, -+ struct panthor_sched_tick_ctx *ctx) -+{ -+ struct panthor_group *group, *tmp; -+ u32 i; -+ -+ for (i = 0; i < ARRAY_SIZE(ctx->old_groups); i++) { -+ list_for_each_entry_safe(group, tmp, &ctx->old_groups[i], run_node) { -+ /* If everything went fine, we should only have groups -+ * to be terminated in the old_groups lists. -+ */ -+ drm_WARN_ON(&group->ptdev->base, !ctx->csg_upd_failed_mask && -+ group_can_run(group)); -+ -+ if (!group_can_run(group)) { -+ list_del_init(&group->run_node); -+ list_del_init(&group->wait_node); -+ group_queue_work(group, term); -+ } else if (group->csg_id >= 0) { -+ list_del_init(&group->run_node); -+ } else { -+ list_move(&group->run_node, -+ group_is_idle(group) ? -+ &sched->groups.idle[group->priority] : -+ &sched->groups.runnable[group->priority]); -+ } -+ group_put(group); -+ } -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(ctx->groups); i++) { -+ /* If everything went fine, the groups to schedule lists should -+ * be empty. -+ */ -+ drm_WARN_ON(&group->ptdev->base, -+ !ctx->csg_upd_failed_mask && !list_empty(&ctx->groups[i])); -+ -+ list_for_each_entry_safe(group, tmp, &ctx->groups[i], run_node) { -+ if (group->csg_id >= 0) { -+ list_del_init(&group->run_node); -+ } else { -+ list_move(&group->run_node, -+ group_is_idle(group) ? -+ &sched->groups.idle[group->priority] : -+ &sched->groups.runnable[group->priority]); -+ } -+ group_put(group); -+ } -+ } -+} -+ -+static void -+tick_ctx_apply(struct panthor_scheduler *sched, struct panthor_sched_tick_ctx *ctx) -+{ -+ struct panthor_group *group, *tmp; -+ struct panthor_device *ptdev = sched->ptdev; -+ struct panthor_csg_slot *csg_slot; -+ int prio, new_csg_prio = MAX_CSG_PRIO, i; -+ u32 csg_mod_mask = 0, free_csg_slots = 0; -+ struct panthor_csg_slots_upd_ctx upd_ctx; -+ int ret; -+ -+ csgs_upd_ctx_init(&upd_ctx); -+ -+ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { -+ /* Suspend or terminate evicted groups. */ -+ list_for_each_entry(group, &ctx->old_groups[prio], run_node) { -+ bool term = !group_can_run(group); -+ int csg_id = group->csg_id; -+ -+ if (drm_WARN_ON(&ptdev->base, csg_id < 0)) -+ continue; -+ -+ csg_slot = &sched->csg_slots[csg_id]; -+ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, -+ term ? CSG_STATE_TERMINATE : CSG_STATE_SUSPEND, -+ CSG_STATE_MASK); -+ } -+ -+ /* Update priorities on already running groups. */ -+ list_for_each_entry(group, &ctx->groups[prio], run_node) { -+ struct panthor_fw_csg_iface *csg_iface; -+ int csg_id = group->csg_id; -+ -+ if (csg_id < 0) { -+ new_csg_prio--; -+ continue; -+ } -+ -+ csg_slot = &sched->csg_slots[csg_id]; -+ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); -+ if (csg_slot->priority == new_csg_prio) { -+ new_csg_prio--; -+ continue; -+ } -+ -+ panthor_fw_update_reqs(csg_iface, endpoint_req, -+ CSG_EP_REQ_PRIORITY(new_csg_prio), -+ CSG_EP_REQ_PRIORITY_MASK); -+ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, -+ csg_iface->output->ack ^ CSG_ENDPOINT_CONFIG, -+ CSG_ENDPOINT_CONFIG); -+ new_csg_prio--; -+ } -+ } -+ -+ ret = csgs_upd_ctx_apply_locked(ptdev, &upd_ctx); -+ if (ret) { -+ panthor_device_schedule_reset(ptdev); -+ ctx->csg_upd_failed_mask |= upd_ctx.timedout_mask; -+ return; -+ } -+ -+ /* Unbind evicted groups. */ -+ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { -+ list_for_each_entry(group, &ctx->old_groups[prio], run_node) { -+ /* This group is gone. Process interrupts to clear -+ * any pending interrupts before we start the new -+ * group. -+ */ -+ if (group->csg_id >= 0) -+ sched_process_csg_irq_locked(ptdev, group->csg_id); -+ -+ group_unbind_locked(group); -+ } -+ } -+ -+ for (i = 0; i < sched->csg_slot_count; i++) { -+ if (!sched->csg_slots[i].group) -+ free_csg_slots |= BIT(i); -+ } -+ -+ csgs_upd_ctx_init(&upd_ctx); -+ new_csg_prio = MAX_CSG_PRIO; -+ -+ /* Start new groups. */ -+ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { -+ list_for_each_entry(group, &ctx->groups[prio], run_node) { -+ int csg_id = group->csg_id; -+ struct panthor_fw_csg_iface *csg_iface; -+ -+ if (csg_id >= 0) { -+ new_csg_prio--; -+ continue; -+ } -+ -+ csg_id = ffs(free_csg_slots) - 1; -+ if (drm_WARN_ON(&ptdev->base, csg_id < 0)) -+ break; -+ -+ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); -+ csg_slot = &sched->csg_slots[csg_id]; -+ csg_mod_mask |= BIT(csg_id); -+ group_bind_locked(group, csg_id); -+ csg_slot_prog_locked(ptdev, csg_id, new_csg_prio--); -+ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, -+ group->state == PANTHOR_CS_GROUP_SUSPENDED ? -+ CSG_STATE_RESUME : CSG_STATE_START, -+ CSG_STATE_MASK); -+ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, -+ csg_iface->output->ack ^ CSG_ENDPOINT_CONFIG, -+ CSG_ENDPOINT_CONFIG); -+ free_csg_slots &= ~BIT(csg_id); -+ } -+ } -+ -+ ret = csgs_upd_ctx_apply_locked(ptdev, &upd_ctx); -+ if (ret) { -+ panthor_device_schedule_reset(ptdev); -+ ctx->csg_upd_failed_mask |= upd_ctx.timedout_mask; -+ return; -+ } -+ -+ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { -+ list_for_each_entry_safe(group, tmp, &ctx->groups[prio], run_node) { -+ list_del_init(&group->run_node); -+ -+ /* If the group has been destroyed while we were -+ * scheduling, ask for an immediate tick to -+ * re-evaluate as soon as possible and get rid of -+ * this dangling group. -+ */ -+ if (group->destroyed) -+ ctx->immediate_tick = true; -+ group_put(group); -+ } -+ -+ /* Return evicted groups to the idle or run queues. Groups -+ * that can no longer be run (because they've been destroyed -+ * or experienced an unrecoverable error) will be scheduled -+ * for destruction in tick_ctx_cleanup(). -+ */ -+ list_for_each_entry_safe(group, tmp, &ctx->old_groups[prio], run_node) { -+ if (!group_can_run(group)) -+ continue; -+ -+ if (group_is_idle(group)) -+ list_move_tail(&group->run_node, &sched->groups.idle[prio]); -+ else -+ list_move_tail(&group->run_node, &sched->groups.runnable[prio]); -+ group_put(group); -+ } -+ } -+ -+ sched->used_csg_slot_count = ctx->group_count; -+ sched->might_have_idle_groups = ctx->idle_group_count > 0; -+} -+ -+static u64 -+tick_ctx_update_resched_target(struct panthor_scheduler *sched, -+ const struct panthor_sched_tick_ctx *ctx) -+{ -+ /* We had space left, no need to reschedule until some external event happens. */ -+ if (!tick_ctx_is_full(sched, ctx)) -+ goto no_tick; -+ -+ /* If idle groups were scheduled, no need to wake up until some external -+ * event happens (group unblocked, new job submitted, ...). -+ */ -+ if (ctx->idle_group_count) -+ goto no_tick; -+ -+ if (drm_WARN_ON(&sched->ptdev->base, ctx->min_priority >= PANTHOR_CSG_PRIORITY_COUNT)) -+ goto no_tick; -+ -+ /* If there are groups of the same priority waiting, we need to -+ * keep the scheduler ticking, otherwise, we'll just wait for -+ * new groups with higher priority to be queued. -+ */ -+ if (!list_empty(&sched->groups.runnable[ctx->min_priority])) { -+ u64 resched_target = sched->last_tick + sched->tick_period; -+ -+ if (time_before64(sched->resched_target, sched->last_tick) || -+ time_before64(resched_target, sched->resched_target)) -+ sched->resched_target = resched_target; -+ -+ return sched->resched_target - sched->last_tick; -+ } -+ -+no_tick: -+ sched->resched_target = U64_MAX; -+ return U64_MAX; -+} -+ -+static void tick_work(struct work_struct *work) -+{ -+ struct panthor_scheduler *sched = container_of(work, struct panthor_scheduler, -+ tick_work.work); -+ struct panthor_device *ptdev = sched->ptdev; -+ struct panthor_sched_tick_ctx ctx; -+ u64 remaining_jiffies = 0, resched_delay; -+ u64 now = get_jiffies_64(); -+ int prio, ret, cookie; -+ -+ if (!drm_dev_enter(&ptdev->base, &cookie)) -+ return; -+ -+ ret = pm_runtime_resume_and_get(ptdev->base.dev); -+ if (drm_WARN_ON(&ptdev->base, ret)) -+ goto out_dev_exit; -+ -+ if (time_before64(now, sched->resched_target)) -+ remaining_jiffies = sched->resched_target - now; -+ -+ mutex_lock(&sched->lock); -+ if (panthor_device_reset_is_pending(sched->ptdev)) -+ goto out_unlock; -+ -+ tick_ctx_init(sched, &ctx, remaining_jiffies != 0); -+ if (ctx.csg_upd_failed_mask) -+ goto out_cleanup_ctx; -+ -+ if (remaining_jiffies) { -+ /* Scheduling forced in the middle of a tick. Only RT groups -+ * can preempt non-RT ones. Currently running RT groups can't be -+ * preempted. -+ */ -+ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; -+ prio >= 0 && !tick_ctx_is_full(sched, &ctx); -+ prio--) { -+ tick_ctx_pick_groups_from_list(sched, &ctx, &ctx.old_groups[prio], -+ true, true); -+ if (prio == PANTHOR_CSG_PRIORITY_RT) { -+ tick_ctx_pick_groups_from_list(sched, &ctx, -+ &sched->groups.runnable[prio], -+ true, false); -+ } -+ } -+ } -+ -+ /* First pick non-idle groups */ -+ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; -+ prio >= 0 && !tick_ctx_is_full(sched, &ctx); -+ prio--) { -+ tick_ctx_pick_groups_from_list(sched, &ctx, &sched->groups.runnable[prio], -+ true, false); -+ tick_ctx_pick_groups_from_list(sched, &ctx, &ctx.old_groups[prio], true, true); -+ } -+ -+ /* If we have free CSG slots left, pick idle groups */ -+ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; -+ prio >= 0 && !tick_ctx_is_full(sched, &ctx); -+ prio--) { -+ /* Check the old_group queue first to avoid reprogramming the slots */ -+ tick_ctx_pick_groups_from_list(sched, &ctx, &ctx.old_groups[prio], false, true); -+ tick_ctx_pick_groups_from_list(sched, &ctx, &sched->groups.idle[prio], -+ false, false); -+ } -+ -+ tick_ctx_apply(sched, &ctx); -+ if (ctx.csg_upd_failed_mask) -+ goto out_cleanup_ctx; -+ -+ if (ctx.idle_group_count == ctx.group_count) { -+ panthor_devfreq_record_idle(sched->ptdev); -+ if (sched->pm.has_ref) { -+ pm_runtime_put_autosuspend(ptdev->base.dev); -+ sched->pm.has_ref = false; -+ } -+ } else { -+ panthor_devfreq_record_busy(sched->ptdev); -+ if (!sched->pm.has_ref) { -+ pm_runtime_get(ptdev->base.dev); -+ sched->pm.has_ref = true; -+ } -+ } -+ -+ sched->last_tick = now; -+ resched_delay = tick_ctx_update_resched_target(sched, &ctx); -+ if (ctx.immediate_tick) -+ resched_delay = 0; -+ -+ if (resched_delay != U64_MAX) -+ sched_queue_delayed_work(sched, tick, resched_delay); -+ -+out_cleanup_ctx: -+ tick_ctx_cleanup(sched, &ctx); -+ -+out_unlock: -+ mutex_unlock(&sched->lock); -+ pm_runtime_mark_last_busy(ptdev->base.dev); -+ pm_runtime_put_autosuspend(ptdev->base.dev); -+ -+out_dev_exit: -+ drm_dev_exit(cookie); -+} -+ -+static int panthor_queue_eval_syncwait(struct panthor_group *group, u8 queue_idx) -+{ -+ struct panthor_queue *queue = group->queues[queue_idx]; -+ union { -+ struct panthor_syncobj_64b sync64; -+ struct panthor_syncobj_32b sync32; -+ } *syncobj; -+ bool result; -+ u64 value; -+ -+ syncobj = panthor_queue_get_syncwait_obj(group, queue); -+ if (!syncobj) -+ return -EINVAL; -+ -+ value = queue->syncwait.sync64 ? -+ syncobj->sync64.seqno : -+ syncobj->sync32.seqno; -+ -+ if (queue->syncwait.gt) -+ result = value > queue->syncwait.ref; -+ else -+ result = value <= queue->syncwait.ref; -+ -+ if (result) -+ panthor_queue_put_syncwait_obj(queue); -+ -+ return result; -+} -+ -+static void sync_upd_work(struct work_struct *work) -+{ -+ struct panthor_scheduler *sched = container_of(work, -+ struct panthor_scheduler, -+ sync_upd_work); -+ struct panthor_group *group, *tmp; -+ bool immediate_tick = false; -+ -+ mutex_lock(&sched->lock); -+ list_for_each_entry_safe(group, tmp, &sched->groups.waiting, wait_node) { -+ u32 tested_queues = group->blocked_queues; -+ u32 unblocked_queues = 0; -+ -+ while (tested_queues) { -+ u32 cs_id = ffs(tested_queues) - 1; -+ int ret; -+ -+ ret = panthor_queue_eval_syncwait(group, cs_id); -+ drm_WARN_ON(&group->ptdev->base, ret < 0); -+ if (ret) -+ unblocked_queues |= BIT(cs_id); -+ -+ tested_queues &= ~BIT(cs_id); -+ } -+ -+ if (unblocked_queues) { -+ group->blocked_queues &= ~unblocked_queues; -+ -+ if (group->csg_id < 0) { -+ list_move(&group->run_node, -+ &sched->groups.runnable[group->priority]); -+ if (group->priority == PANTHOR_CSG_PRIORITY_RT) -+ immediate_tick = true; -+ } -+ } -+ -+ if (!group->blocked_queues) -+ list_del_init(&group->wait_node); -+ } -+ mutex_unlock(&sched->lock); -+ -+ if (immediate_tick) -+ sched_queue_delayed_work(sched, tick, 0); -+} -+ -+static void group_schedule_locked(struct panthor_group *group, u32 queue_mask) -+{ -+ struct panthor_device *ptdev = group->ptdev; -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct list_head *queue = &sched->groups.runnable[group->priority]; -+ u64 delay_jiffies = 0; -+ bool was_idle; -+ u64 now; -+ -+ if (!group_can_run(group)) -+ return; -+ -+ /* All updated queues are blocked, no need to wake up the scheduler. */ -+ if ((queue_mask & group->blocked_queues) == queue_mask) -+ return; -+ -+ was_idle = group_is_idle(group); -+ group->idle_queues &= ~queue_mask; -+ -+ /* Don't mess up with the lists if we're in a middle of a reset. */ -+ if (atomic_read(&sched->reset.in_progress)) -+ return; -+ -+ if (was_idle && !group_is_idle(group)) -+ list_move_tail(&group->run_node, queue); -+ -+ /* RT groups are preemptive. */ -+ if (group->priority == PANTHOR_CSG_PRIORITY_RT) { -+ sched_queue_delayed_work(sched, tick, 0); -+ return; -+ } -+ -+ /* Some groups might be idle, force an immediate tick to -+ * re-evaluate. -+ */ -+ if (sched->might_have_idle_groups) { -+ sched_queue_delayed_work(sched, tick, 0); -+ return; -+ } -+ -+ /* Scheduler is ticking, nothing to do. */ -+ if (sched->resched_target != U64_MAX) { -+ /* If there are free slots, force immediating ticking. */ -+ if (sched->used_csg_slot_count < sched->csg_slot_count) -+ sched_queue_delayed_work(sched, tick, 0); -+ -+ return; -+ } -+ -+ /* Scheduler tick was off, recalculate the resched_target based on the -+ * last tick event, and queue the scheduler work. -+ */ -+ now = get_jiffies_64(); -+ sched->resched_target = sched->last_tick + sched->tick_period; -+ if (sched->used_csg_slot_count == sched->csg_slot_count && -+ time_before64(now, sched->resched_target)) -+ delay_jiffies = min_t(unsigned long, sched->resched_target - now, ULONG_MAX); -+ -+ sched_queue_delayed_work(sched, tick, delay_jiffies); -+} -+ -+static void queue_stop(struct panthor_queue *queue, -+ struct panthor_job *bad_job) -+{ -+ drm_sched_stop(&queue->scheduler, bad_job ? &bad_job->base : NULL); -+} -+ -+static void queue_start(struct panthor_queue *queue) -+{ -+ struct panthor_job *job; -+ -+ /* Re-assign the parent fences. */ -+ list_for_each_entry(job, &queue->scheduler.pending_list, base.list) -+ job->base.s_fence->parent = dma_fence_get(job->done_fence); -+ -+ drm_sched_start(&queue->scheduler, true); -+} -+ -+static void panthor_group_stop(struct panthor_group *group) -+{ -+ struct panthor_scheduler *sched = group->ptdev->scheduler; -+ -+ lockdep_assert_held(&sched->reset.lock); -+ -+ for (u32 i = 0; i < group->queue_count; i++) -+ queue_stop(group->queues[i], NULL); -+ -+ group_get(group); -+ list_move_tail(&group->run_node, &sched->reset.stopped_groups); -+} -+ -+static void panthor_group_start(struct panthor_group *group) -+{ -+ struct panthor_scheduler *sched = group->ptdev->scheduler; -+ -+ lockdep_assert_held(&group->ptdev->scheduler->reset.lock); -+ -+ for (u32 i = 0; i < group->queue_count; i++) -+ queue_start(group->queues[i]); -+ -+ if (group_can_run(group)) { -+ list_move_tail(&group->run_node, -+ group_is_idle(group) ? -+ &sched->groups.idle[group->priority] : -+ &sched->groups.runnable[group->priority]); -+ } else { -+ list_del_init(&group->run_node); -+ list_del_init(&group->wait_node); -+ group_queue_work(group, term); -+ } -+ -+ group_put(group); -+} -+ -+static void panthor_sched_immediate_tick(struct panthor_device *ptdev) -+{ -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ -+ sched_queue_delayed_work(sched, tick, 0); -+} -+ -+/** -+ * panthor_sched_report_mmu_fault() - Report MMU faults to the scheduler. -+ */ -+void panthor_sched_report_mmu_fault(struct panthor_device *ptdev) -+{ -+ /* Force a tick to immediately kill faulty groups. */ -+ if (ptdev->scheduler) -+ panthor_sched_immediate_tick(ptdev); -+} -+ -+void panthor_sched_resume(struct panthor_device *ptdev) -+{ -+ /* Force a tick to re-evaluate after a resume. */ -+ panthor_sched_immediate_tick(ptdev); -+} -+ -+void panthor_sched_suspend(struct panthor_device *ptdev) -+{ -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct panthor_csg_slots_upd_ctx upd_ctx; -+ u64 suspended_slots, faulty_slots; -+ struct panthor_group *group; -+ u32 i; -+ -+ mutex_lock(&sched->lock); -+ csgs_upd_ctx_init(&upd_ctx); -+ for (i = 0; i < sched->csg_slot_count; i++) { -+ struct panthor_csg_slot *csg_slot = &sched->csg_slots[i]; -+ -+ if (csg_slot->group) { -+ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, i, -+ CSG_STATE_SUSPEND, -+ CSG_STATE_MASK); -+ } -+ } -+ -+ suspended_slots = upd_ctx.update_mask; -+ -+ csgs_upd_ctx_apply_locked(ptdev, &upd_ctx); -+ suspended_slots &= ~upd_ctx.timedout_mask; -+ faulty_slots = upd_ctx.timedout_mask; -+ -+ if (faulty_slots) { -+ u32 slot_mask = faulty_slots; -+ -+ drm_err(&ptdev->base, "CSG suspend failed, escalating to termination"); -+ csgs_upd_ctx_init(&upd_ctx); -+ while (slot_mask) { -+ u32 csg_id = ffs(slot_mask) - 1; -+ -+ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, -+ CSG_STATE_TERMINATE, -+ CSG_STATE_MASK); -+ slot_mask &= ~BIT(csg_id); -+ } -+ -+ csgs_upd_ctx_apply_locked(ptdev, &upd_ctx); -+ -+ slot_mask = upd_ctx.timedout_mask; -+ while (slot_mask) { -+ u32 csg_id = ffs(slot_mask) - 1; -+ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; -+ -+ /* Terminate command timedout, but the soft-reset will -+ * automatically terminate all active groups, so let's -+ * force the state to halted here. -+ */ -+ if (csg_slot->group->state != PANTHOR_CS_GROUP_TERMINATED) -+ csg_slot->group->state = PANTHOR_CS_GROUP_TERMINATED; -+ slot_mask &= ~BIT(csg_id); -+ } -+ } -+ -+ /* Flush L2 and LSC caches to make sure suspend state is up-to-date. -+ * If the flush fails, flag all queues for termination. -+ */ -+ if (suspended_slots) { -+ bool flush_caches_failed = false; -+ u32 slot_mask = suspended_slots; -+ -+ if (panthor_gpu_flush_caches(ptdev, CACHE_CLEAN, CACHE_CLEAN, 0)) -+ flush_caches_failed = true; -+ -+ while (slot_mask) { -+ u32 csg_id = ffs(slot_mask) - 1; -+ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; -+ -+ if (flush_caches_failed) -+ csg_slot->group->state = PANTHOR_CS_GROUP_TERMINATED; -+ else -+ csg_slot_sync_update_locked(ptdev, csg_id); -+ -+ slot_mask &= ~BIT(csg_id); -+ } -+ -+ if (flush_caches_failed) -+ faulty_slots |= suspended_slots; -+ } -+ -+ for (i = 0; i < sched->csg_slot_count; i++) { -+ struct panthor_csg_slot *csg_slot = &sched->csg_slots[i]; -+ -+ group = csg_slot->group; -+ if (!group) -+ continue; -+ -+ group_get(group); -+ -+ if (group->csg_id >= 0) -+ sched_process_csg_irq_locked(ptdev, group->csg_id); -+ -+ group_unbind_locked(group); -+ -+ drm_WARN_ON(&group->ptdev->base, !list_empty(&group->run_node)); -+ -+ if (group_can_run(group)) { -+ list_add(&group->run_node, -+ &sched->groups.idle[group->priority]); -+ } else { -+ /* We don't bother stopping the scheduler if the group is -+ * faulty, the group termination work will finish the job. -+ */ -+ list_del_init(&group->wait_node); -+ group_queue_work(group, term); -+ } -+ group_put(group); -+ } -+ mutex_unlock(&sched->lock); -+} -+ -+void panthor_sched_pre_reset(struct panthor_device *ptdev) -+{ -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct panthor_group *group, *group_tmp; -+ u32 i; -+ -+ mutex_lock(&sched->reset.lock); -+ atomic_set(&sched->reset.in_progress, true); -+ -+ /* Cancel all scheduler works. Once this is done, these works can't be -+ * scheduled again until the reset operation is complete. -+ */ -+ cancel_work_sync(&sched->sync_upd_work); -+ cancel_delayed_work_sync(&sched->tick_work); -+ -+ panthor_sched_suspend(ptdev); -+ -+ /* Stop all groups that might still accept jobs, so we don't get passed -+ * new jobs while we're resetting. -+ */ -+ for (i = 0; i < ARRAY_SIZE(sched->groups.runnable); i++) { -+ /* All groups should be in the idle lists. */ -+ drm_WARN_ON(&ptdev->base, !list_empty(&sched->groups.runnable[i])); -+ list_for_each_entry_safe(group, group_tmp, &sched->groups.runnable[i], run_node) -+ panthor_group_stop(group); -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(sched->groups.idle); i++) { -+ list_for_each_entry_safe(group, group_tmp, &sched->groups.idle[i], run_node) -+ panthor_group_stop(group); -+ } -+ -+ mutex_unlock(&sched->reset.lock); -+} -+ -+void panthor_sched_post_reset(struct panthor_device *ptdev) -+{ -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct panthor_group *group, *group_tmp; -+ -+ mutex_lock(&sched->reset.lock); -+ -+ list_for_each_entry_safe(group, group_tmp, &sched->reset.stopped_groups, run_node) -+ panthor_group_start(group); -+ -+ /* We're done resetting the GPU, clear the reset.in_progress bit so we can -+ * kick the scheduler. -+ */ -+ atomic_set(&sched->reset.in_progress, false); -+ mutex_unlock(&sched->reset.lock); -+ -+ sched_queue_delayed_work(sched, tick, 0); -+ -+ sched_queue_work(sched, sync_upd); -+} -+ -+static void group_sync_upd_work(struct work_struct *work) -+{ -+ struct panthor_group *group = -+ container_of(work, struct panthor_group, sync_upd_work); -+ struct panthor_job *job, *job_tmp; -+ LIST_HEAD(done_jobs); -+ u32 queue_idx; -+ bool cookie; -+ -+ cookie = dma_fence_begin_signalling(); -+ for (queue_idx = 0; queue_idx < group->queue_count; queue_idx++) { -+ struct panthor_queue *queue = group->queues[queue_idx]; -+ struct panthor_syncobj_64b *syncobj; -+ -+ if (!queue) -+ continue; -+ -+ syncobj = group->syncobjs->kmap + (queue_idx * sizeof(*syncobj)); -+ -+ spin_lock(&queue->fence_ctx.lock); -+ list_for_each_entry_safe(job, job_tmp, &queue->fence_ctx.in_flight_jobs, node) { -+ if (!job->call_info.size) -+ continue; -+ -+ if (syncobj->seqno < job->done_fence->seqno) -+ break; -+ -+ list_move_tail(&job->node, &done_jobs); -+ dma_fence_signal_locked(job->done_fence); -+ } -+ spin_unlock(&queue->fence_ctx.lock); -+ } -+ dma_fence_end_signalling(cookie); -+ -+ list_for_each_entry_safe(job, job_tmp, &done_jobs, node) { -+ list_del_init(&job->node); -+ panthor_job_put(&job->base); -+ } -+ -+ group_put(group); -+} -+ -+static struct dma_fence * -+queue_run_job(struct drm_sched_job *sched_job) -+{ -+ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); -+ struct panthor_group *group = job->group; -+ struct panthor_queue *queue = group->queues[job->queue_idx]; -+ struct panthor_device *ptdev = group->ptdev; -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ u32 ringbuf_size = panthor_kernel_bo_size(queue->ringbuf); -+ u32 ringbuf_insert = queue->iface.input->insert & (ringbuf_size - 1); -+ u64 addr_reg = ptdev->csif_info.cs_reg_count - -+ ptdev->csif_info.unpreserved_cs_reg_count; -+ u64 val_reg = addr_reg + 2; -+ u64 sync_addr = panthor_kernel_bo_gpuva(group->syncobjs) + -+ job->queue_idx * sizeof(struct panthor_syncobj_64b); -+ u32 waitall_mask = GENMASK(sched->sb_slot_count - 1, 0); -+ struct dma_fence *done_fence; -+ int ret; -+ -+ u64 call_instrs[NUM_INSTRS_PER_SLOT] = { -+ /* MOV32 rX+2, cs.latest_flush */ -+ (2ull << 56) | (val_reg << 48) | job->call_info.latest_flush, -+ -+ /* FLUSH_CACHE2.clean_inv_all.no_wait.signal(0) rX+2 */ -+ (36ull << 56) | (0ull << 48) | (val_reg << 40) | (0 << 16) | 0x233, -+ -+ /* MOV48 rX:rX+1, cs.start */ -+ (1ull << 56) | (addr_reg << 48) | job->call_info.start, -+ -+ /* MOV32 rX+2, cs.size */ -+ (2ull << 56) | (val_reg << 48) | job->call_info.size, -+ -+ /* WAIT(0) => waits for FLUSH_CACHE2 instruction */ -+ (3ull << 56) | (1 << 16), -+ -+ /* CALL rX:rX+1, rX+2 */ -+ (32ull << 56) | (addr_reg << 40) | (val_reg << 32), -+ -+ /* MOV48 rX:rX+1, sync_addr */ -+ (1ull << 56) | (addr_reg << 48) | sync_addr, -+ -+ /* MOV48 rX+2, #1 */ -+ (1ull << 56) | (val_reg << 48) | 1, -+ -+ /* WAIT(all) */ -+ (3ull << 56) | (waitall_mask << 16), -+ -+ /* SYNC_ADD64.system_scope.propage_err.nowait rX:rX+1, rX+2*/ -+ (51ull << 56) | (0ull << 48) | (addr_reg << 40) | (val_reg << 32) | (0 << 16) | 1, -+ -+ /* ERROR_BARRIER, so we can recover from faults at job -+ * boundaries. -+ */ -+ (47ull << 56), -+ }; -+ -+ /* Need to be cacheline aligned to please the prefetcher. */ -+ static_assert(sizeof(call_instrs) % 64 == 0, -+ "call_instrs is not aligned on a cacheline"); -+ -+ /* Stream size is zero, nothing to do => return a NULL fence and let -+ * drm_sched signal the parent. -+ */ -+ if (!job->call_info.size) -+ return NULL; -+ -+ ret = pm_runtime_resume_and_get(ptdev->base.dev); -+ if (drm_WARN_ON(&ptdev->base, ret)) -+ return ERR_PTR(ret); -+ -+ mutex_lock(&sched->lock); -+ if (!group_can_run(group)) { -+ done_fence = ERR_PTR(-ECANCELED); -+ goto out_unlock; -+ } -+ -+ dma_fence_init(job->done_fence, -+ &panthor_queue_fence_ops, -+ &queue->fence_ctx.lock, -+ queue->fence_ctx.id, -+ atomic64_inc_return(&queue->fence_ctx.seqno)); -+ -+ memcpy(queue->ringbuf->kmap + ringbuf_insert, -+ call_instrs, sizeof(call_instrs)); -+ -+ panthor_job_get(&job->base); -+ spin_lock(&queue->fence_ctx.lock); -+ list_add_tail(&job->node, &queue->fence_ctx.in_flight_jobs); -+ spin_unlock(&queue->fence_ctx.lock); -+ -+ job->ringbuf.start = queue->iface.input->insert; -+ job->ringbuf.end = job->ringbuf.start + sizeof(call_instrs); -+ -+ /* Make sure the ring buffer is updated before the INSERT -+ * register. -+ */ -+ wmb(); -+ -+ queue->iface.input->extract = queue->iface.output->extract; -+ queue->iface.input->insert = job->ringbuf.end; -+ -+ if (group->csg_id < 0) { -+ /* If the queue is blocked, we want to keep the timeout running, so we -+ * can detect unbounded waits and kill the group when that happens. -+ * Otherwise, we suspend the timeout so the time we spend waiting for -+ * a CSG slot is not counted. -+ */ -+ if (!(group->blocked_queues & BIT(job->queue_idx)) && -+ !queue->timeout_suspended) { -+ queue->remaining_time = drm_sched_suspend_timeout(&queue->scheduler); -+ queue->timeout_suspended = true; -+ } -+ -+ group_schedule_locked(group, BIT(job->queue_idx)); -+ } else { -+ gpu_write(ptdev, CSF_DOORBELL(queue->doorbell_id), 1); -+ if (!sched->pm.has_ref && -+ !(group->blocked_queues & BIT(job->queue_idx))) { -+ pm_runtime_get(ptdev->base.dev); -+ sched->pm.has_ref = true; -+ } -+ } -+ -+ done_fence = dma_fence_get(job->done_fence); -+ -+out_unlock: -+ mutex_unlock(&sched->lock); -+ pm_runtime_mark_last_busy(ptdev->base.dev); -+ pm_runtime_put_autosuspend(ptdev->base.dev); -+ -+ return done_fence; -+} -+ -+static enum drm_gpu_sched_stat -+queue_timedout_job(struct drm_sched_job *sched_job) -+{ -+ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); -+ struct panthor_group *group = job->group; -+ struct panthor_device *ptdev = group->ptdev; -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct panthor_queue *queue = group->queues[job->queue_idx]; -+ -+ drm_warn(&ptdev->base, "job timeout\n"); -+ -+ drm_WARN_ON(&ptdev->base, atomic_read(&sched->reset.in_progress)); -+ -+ queue_stop(queue, job); -+ -+ mutex_lock(&sched->lock); -+ group->timedout = true; -+ if (group->csg_id >= 0) { -+ sched_queue_delayed_work(ptdev->scheduler, tick, 0); -+ } else { -+ /* Remove from the run queues, so the scheduler can't -+ * pick the group on the next tick. -+ */ -+ list_del_init(&group->run_node); -+ list_del_init(&group->wait_node); -+ -+ group_queue_work(group, term); -+ } -+ mutex_unlock(&sched->lock); -+ -+ queue_start(queue); -+ -+ return DRM_GPU_SCHED_STAT_NOMINAL; -+} -+ -+static void queue_free_job(struct drm_sched_job *sched_job) -+{ -+ drm_sched_job_cleanup(sched_job); -+ panthor_job_put(sched_job); -+} -+ -+static const struct drm_sched_backend_ops panthor_queue_sched_ops = { -+ .run_job = queue_run_job, -+ .timedout_job = queue_timedout_job, -+ .free_job = queue_free_job, -+}; -+ -+static struct panthor_queue * -+group_create_queue(struct panthor_group *group, -+ const struct drm_panthor_queue_create *args) -+{ -+ struct drm_gpu_scheduler *drm_sched; -+ struct panthor_queue *queue; -+ int ret; -+ -+ if (args->pad[0] || args->pad[1] || args->pad[2]) -+ return ERR_PTR(-EINVAL); -+ -+ if (args->ringbuf_size < SZ_4K || args->ringbuf_size > SZ_64K || -+ !is_power_of_2(args->ringbuf_size)) -+ return ERR_PTR(-EINVAL); -+ -+ if (args->priority > CSF_MAX_QUEUE_PRIO) -+ return ERR_PTR(-EINVAL); -+ -+ queue = kzalloc(sizeof(*queue), GFP_KERNEL); -+ if (!queue) -+ return ERR_PTR(-ENOMEM); -+ -+ queue->fence_ctx.id = dma_fence_context_alloc(1); -+ spin_lock_init(&queue->fence_ctx.lock); -+ INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); -+ -+ queue->priority = args->priority; -+ -+ queue->ringbuf = panthor_kernel_bo_create(group->ptdev, group->vm, -+ args->ringbuf_size, -+ DRM_PANTHOR_BO_NO_MMAP, -+ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | -+ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED, -+ PANTHOR_VM_KERNEL_AUTO_VA); -+ if (IS_ERR(queue->ringbuf)) { -+ ret = PTR_ERR(queue->ringbuf); -+ goto err_free_queue; -+ } -+ -+ ret = panthor_kernel_bo_vmap(queue->ringbuf); -+ if (ret) -+ goto err_free_queue; -+ -+ queue->iface.mem = panthor_fw_alloc_queue_iface_mem(group->ptdev, -+ &queue->iface.input, -+ &queue->iface.output, -+ &queue->iface.input_fw_va, -+ &queue->iface.output_fw_va); -+ if (IS_ERR(queue->iface.mem)) { -+ ret = PTR_ERR(queue->iface.mem); -+ goto err_free_queue; -+ } -+ -+ ret = drm_sched_init(&queue->scheduler, &panthor_queue_sched_ops, -+ group->ptdev->scheduler->wq, 1, -+ args->ringbuf_size / (NUM_INSTRS_PER_SLOT * sizeof(u64)), -+ 0, msecs_to_jiffies(JOB_TIMEOUT_MS), -+ group->ptdev->reset.wq, -+ NULL, "panthor-queue", group->ptdev->base.dev); -+ if (ret) -+ goto err_free_queue; -+ -+ drm_sched = &queue->scheduler; -+ ret = drm_sched_entity_init(&queue->entity, 0, &drm_sched, 1, NULL); -+ -+ return queue; -+ -+err_free_queue: -+ group_free_queue(group, queue); -+ return ERR_PTR(ret); -+} -+ -+#define MAX_GROUPS_PER_POOL 128 -+ -+int panthor_group_create(struct panthor_file *pfile, -+ const struct drm_panthor_group_create *group_args, -+ const struct drm_panthor_queue_create *queue_args) -+{ -+ struct panthor_device *ptdev = pfile->ptdev; -+ struct panthor_group_pool *gpool = pfile->groups; -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct panthor_fw_csg_iface *csg_iface = panthor_fw_get_csg_iface(ptdev, 0); -+ struct panthor_group *group = NULL; -+ u32 gid, i, suspend_size; -+ int ret; -+ -+ if (group_args->pad) -+ return -EINVAL; -+ -+ if (group_args->priority > PANTHOR_CSG_PRIORITY_HIGH) -+ return -EINVAL; -+ -+ if ((group_args->compute_core_mask & ~ptdev->gpu_info.shader_present) || -+ (group_args->fragment_core_mask & ~ptdev->gpu_info.shader_present) || -+ (group_args->tiler_core_mask & ~ptdev->gpu_info.tiler_present)) -+ return -EINVAL; -+ -+ if (hweight64(group_args->compute_core_mask) < group_args->max_compute_cores || -+ hweight64(group_args->fragment_core_mask) < group_args->max_fragment_cores || -+ hweight64(group_args->tiler_core_mask) < group_args->max_tiler_cores) -+ return -EINVAL; -+ -+ group = kzalloc(sizeof(*group), GFP_KERNEL); -+ if (!group) -+ return -ENOMEM; -+ -+ spin_lock_init(&group->fatal_lock); -+ kref_init(&group->refcount); -+ group->state = PANTHOR_CS_GROUP_CREATED; -+ group->csg_id = -1; -+ -+ group->ptdev = ptdev; -+ group->max_compute_cores = group_args->max_compute_cores; -+ group->compute_core_mask = group_args->compute_core_mask; -+ group->max_fragment_cores = group_args->max_fragment_cores; -+ group->fragment_core_mask = group_args->fragment_core_mask; -+ group->max_tiler_cores = group_args->max_tiler_cores; -+ group->tiler_core_mask = group_args->tiler_core_mask; -+ group->priority = group_args->priority; -+ -+ INIT_LIST_HEAD(&group->wait_node); -+ INIT_LIST_HEAD(&group->run_node); -+ INIT_WORK(&group->term_work, group_term_work); -+ INIT_WORK(&group->sync_upd_work, group_sync_upd_work); -+ INIT_WORK(&group->tiler_oom_work, group_tiler_oom_work); -+ INIT_WORK(&group->release_work, group_release_work); -+ -+ group->vm = panthor_vm_pool_get_vm(pfile->vms, group_args->vm_id); -+ if (!group->vm) { -+ ret = -EINVAL; -+ goto err_put_group; -+ } -+ -+ suspend_size = csg_iface->control->suspend_size; -+ group->suspend_buf = panthor_fw_alloc_suspend_buf_mem(ptdev, suspend_size); -+ if (IS_ERR(group->suspend_buf)) { -+ ret = PTR_ERR(group->suspend_buf); -+ group->suspend_buf = NULL; -+ goto err_put_group; -+ } -+ -+ suspend_size = csg_iface->control->protm_suspend_size; -+ group->protm_suspend_buf = panthor_fw_alloc_suspend_buf_mem(ptdev, suspend_size); -+ if (IS_ERR(group->protm_suspend_buf)) { -+ ret = PTR_ERR(group->protm_suspend_buf); -+ group->protm_suspend_buf = NULL; -+ goto err_put_group; -+ } -+ -+ group->syncobjs = panthor_kernel_bo_create(ptdev, group->vm, -+ group_args->queues.count * -+ sizeof(struct panthor_syncobj_64b), -+ DRM_PANTHOR_BO_NO_MMAP, -+ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | -+ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED, -+ PANTHOR_VM_KERNEL_AUTO_VA); -+ if (IS_ERR(group->syncobjs)) { -+ ret = PTR_ERR(group->syncobjs); -+ goto err_put_group; -+ } -+ -+ ret = panthor_kernel_bo_vmap(group->syncobjs); -+ if (ret) -+ goto err_put_group; -+ -+ memset(group->syncobjs->kmap, 0, -+ group_args->queues.count * sizeof(struct panthor_syncobj_64b)); -+ -+ for (i = 0; i < group_args->queues.count; i++) { -+ group->queues[i] = group_create_queue(group, &queue_args[i]); -+ if (IS_ERR(group->queues[i])) { -+ ret = PTR_ERR(group->queues[i]); -+ group->queues[i] = NULL; -+ goto err_put_group; -+ } -+ -+ group->queue_count++; -+ } -+ -+ group->idle_queues = GENMASK(group->queue_count - 1, 0); -+ -+ ret = xa_alloc(&gpool->xa, &gid, group, XA_LIMIT(1, MAX_GROUPS_PER_POOL), GFP_KERNEL); -+ if (ret) -+ goto err_put_group; -+ -+ mutex_lock(&sched->reset.lock); -+ if (atomic_read(&sched->reset.in_progress)) { -+ panthor_group_stop(group); -+ } else { -+ mutex_lock(&sched->lock); -+ list_add_tail(&group->run_node, -+ &sched->groups.idle[group->priority]); -+ mutex_unlock(&sched->lock); -+ } -+ mutex_unlock(&sched->reset.lock); -+ -+ return gid; -+ -+err_put_group: -+ group_put(group); -+ return ret; -+} -+ -+int panthor_group_destroy(struct panthor_file *pfile, u32 group_handle) -+{ -+ struct panthor_group_pool *gpool = pfile->groups; -+ struct panthor_device *ptdev = pfile->ptdev; -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct panthor_group *group; -+ -+ group = xa_erase(&gpool->xa, group_handle); -+ if (!group) -+ return -EINVAL; -+ -+ for (u32 i = 0; i < group->queue_count; i++) { -+ if (group->queues[i]) -+ drm_sched_entity_destroy(&group->queues[i]->entity); -+ } -+ -+ mutex_lock(&sched->reset.lock); -+ mutex_lock(&sched->lock); -+ group->destroyed = true; -+ if (group->csg_id >= 0) { -+ sched_queue_delayed_work(sched, tick, 0); -+ } else if (!atomic_read(&sched->reset.in_progress)) { -+ /* Remove from the run queues, so the scheduler can't -+ * pick the group on the next tick. -+ */ -+ list_del_init(&group->run_node); -+ list_del_init(&group->wait_node); -+ group_queue_work(group, term); -+ } -+ mutex_unlock(&sched->lock); -+ mutex_unlock(&sched->reset.lock); -+ -+ group_put(group); -+ return 0; -+} -+ -+int panthor_group_get_state(struct panthor_file *pfile, -+ struct drm_panthor_group_get_state *get_state) -+{ -+ struct panthor_group_pool *gpool = pfile->groups; -+ struct panthor_device *ptdev = pfile->ptdev; -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ struct panthor_group *group; -+ -+ if (get_state->pad) -+ return -EINVAL; -+ -+ group = group_get(xa_load(&gpool->xa, get_state->group_handle)); -+ if (!group) -+ return -EINVAL; -+ -+ memset(get_state, 0, sizeof(*get_state)); -+ -+ mutex_lock(&sched->lock); -+ if (group->timedout) -+ get_state->state |= DRM_PANTHOR_GROUP_STATE_TIMEDOUT; -+ if (group->fatal_queues) { -+ get_state->state |= DRM_PANTHOR_GROUP_STATE_FATAL_FAULT; -+ get_state->fatal_queues = group->fatal_queues; -+ } -+ mutex_unlock(&sched->lock); -+ -+ group_put(group); -+ return 0; -+} -+ -+int panthor_group_pool_create(struct panthor_file *pfile) -+{ -+ struct panthor_group_pool *gpool; -+ -+ gpool = kzalloc(sizeof(*gpool), GFP_KERNEL); -+ if (!gpool) -+ return -ENOMEM; -+ -+ xa_init_flags(&gpool->xa, XA_FLAGS_ALLOC1); -+ pfile->groups = gpool; -+ return 0; -+} -+ -+void panthor_group_pool_destroy(struct panthor_file *pfile) -+{ -+ struct panthor_group_pool *gpool = pfile->groups; -+ struct panthor_group *group; -+ unsigned long i; -+ -+ if (IS_ERR_OR_NULL(gpool)) -+ return; -+ -+ xa_for_each(&gpool->xa, i, group) -+ panthor_group_destroy(pfile, i); -+ -+ xa_destroy(&gpool->xa); -+ kfree(gpool); -+ pfile->groups = NULL; -+} -+ -+static void job_release(struct kref *ref) -+{ -+ struct panthor_job *job = container_of(ref, struct panthor_job, refcount); -+ -+ drm_WARN_ON(&job->group->ptdev->base, !list_empty(&job->node)); -+ -+ if (job->base.s_fence) -+ drm_sched_job_cleanup(&job->base); -+ -+ if (job->done_fence && job->done_fence->ops) -+ dma_fence_put(job->done_fence); -+ else -+ dma_fence_free(job->done_fence); -+ -+ group_put(job->group); -+ -+ kfree(job); -+} -+ -+struct drm_sched_job *panthor_job_get(struct drm_sched_job *sched_job) -+{ -+ if (sched_job) { -+ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); -+ -+ kref_get(&job->refcount); -+ } -+ -+ return sched_job; -+} -+ -+void panthor_job_put(struct drm_sched_job *sched_job) -+{ -+ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); -+ -+ if (sched_job) -+ kref_put(&job->refcount, job_release); -+} -+ -+struct panthor_vm *panthor_job_vm(struct drm_sched_job *sched_job) -+{ -+ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); -+ -+ return job->group->vm; -+} -+ -+struct drm_sched_job * -+panthor_job_create(struct panthor_file *pfile, -+ u16 group_handle, -+ const struct drm_panthor_queue_submit *qsubmit) -+{ -+ struct panthor_group_pool *gpool = pfile->groups; -+ struct panthor_job *job; -+ int ret; -+ -+ if (qsubmit->pad) -+ return ERR_PTR(-EINVAL); -+ -+ /* If stream_addr is zero, so stream_size should be. */ -+ if ((qsubmit->stream_size == 0) != (qsubmit->stream_addr == 0)) -+ return ERR_PTR(-EINVAL); -+ -+ /* Make sure the address is aligned on 64-byte (cacheline) and the size is -+ * aligned on 8-byte (instruction size). -+ */ -+ if ((qsubmit->stream_addr & 63) || (qsubmit->stream_size & 7)) -+ return ERR_PTR(-EINVAL); -+ -+ /* bits 24:30 must be zero. */ -+ if (qsubmit->latest_flush & GENMASK(30, 24)) -+ return ERR_PTR(-EINVAL); -+ -+ job = kzalloc(sizeof(*job), GFP_KERNEL); -+ if (!job) -+ return ERR_PTR(-ENOMEM); -+ -+ kref_init(&job->refcount); -+ job->queue_idx = qsubmit->queue_index; -+ job->call_info.size = qsubmit->stream_size; -+ job->call_info.start = qsubmit->stream_addr; -+ job->call_info.latest_flush = qsubmit->latest_flush; -+ INIT_LIST_HEAD(&job->node); -+ -+ job->group = group_get(xa_load(&gpool->xa, group_handle)); -+ if (!job->group) { -+ ret = -EINVAL; -+ goto err_put_job; -+ } -+ -+ if (job->queue_idx >= job->group->queue_count || -+ !job->group->queues[job->queue_idx]) { -+ ret = -EINVAL; -+ goto err_put_job; -+ } -+ -+ job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL); -+ if (!job->done_fence) { -+ ret = -ENOMEM; -+ goto err_put_job; -+ } -+ -+ ret = drm_sched_job_init(&job->base, -+ &job->group->queues[job->queue_idx]->entity, -+ 1, job->group); -+ if (ret) -+ goto err_put_job; -+ -+ return &job->base; -+ -+err_put_job: -+ panthor_job_put(&job->base); -+ return ERR_PTR(ret); -+} -+ -+void panthor_job_update_resvs(struct drm_exec *exec, struct drm_sched_job *sched_job) -+{ -+ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); -+ -+ /* Still not sure why we want USAGE_WRITE for external objects, since I -+ * was assuming this would be handled through explicit syncs being imported -+ * to external BOs with DMA_BUF_IOCTL_IMPORT_SYNC_FILE, but other drivers -+ * seem to pass DMA_RESV_USAGE_WRITE, so there must be a good reason. -+ */ -+ panthor_vm_update_resvs(job->group->vm, exec, &sched_job->s_fence->finished, -+ DMA_RESV_USAGE_BOOKKEEP, DMA_RESV_USAGE_WRITE); -+} -+ -+void panthor_sched_unplug(struct panthor_device *ptdev) -+{ -+ struct panthor_scheduler *sched = ptdev->scheduler; -+ -+ cancel_delayed_work_sync(&sched->tick_work); -+ -+ mutex_lock(&sched->lock); -+ if (sched->pm.has_ref) { -+ pm_runtime_put(ptdev->base.dev); -+ sched->pm.has_ref = false; -+ } -+ mutex_unlock(&sched->lock); -+} -+ -+static void panthor_sched_fini(struct drm_device *ddev, void *res) -+{ -+ struct panthor_scheduler *sched = res; -+ int prio; -+ -+ if (!sched || !sched->csg_slot_count) -+ return; -+ -+ cancel_delayed_work_sync(&sched->tick_work); -+ -+ if (sched->wq) -+ destroy_workqueue(sched->wq); -+ -+ if (sched->heap_alloc_wq) -+ destroy_workqueue(sched->heap_alloc_wq); -+ -+ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { -+ drm_WARN_ON(ddev, !list_empty(&sched->groups.runnable[prio])); -+ drm_WARN_ON(ddev, !list_empty(&sched->groups.idle[prio])); -+ } -+ -+ drm_WARN_ON(ddev, !list_empty(&sched->groups.waiting)); -+} -+ -+int panthor_sched_init(struct panthor_device *ptdev) -+{ -+ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); -+ struct panthor_fw_csg_iface *csg_iface = panthor_fw_get_csg_iface(ptdev, 0); -+ struct panthor_fw_cs_iface *cs_iface = panthor_fw_get_cs_iface(ptdev, 0, 0); -+ struct panthor_scheduler *sched; -+ u32 gpu_as_count, num_groups; -+ int prio, ret; -+ -+ sched = drmm_kzalloc(&ptdev->base, sizeof(*sched), GFP_KERNEL); -+ if (!sched) -+ return -ENOMEM; -+ -+ /* The highest bit in JOB_INT_* is reserved for globabl IRQs. That -+ * leaves 31 bits for CSG IRQs, hence the MAX_CSGS clamp here. -+ */ -+ num_groups = min_t(u32, MAX_CSGS, glb_iface->control->group_num); -+ -+ /* The FW-side scheduler might deadlock if two groups with the same -+ * priority try to access a set of resources that overlaps, with part -+ * of the resources being allocated to one group and the other part to -+ * the other group, both groups waiting for the remaining resources to -+ * be allocated. To avoid that, it is recommended to assign each CSG a -+ * different priority. In theory we could allow several groups to have -+ * the same CSG priority if they don't request the same resources, but -+ * that makes the scheduling logic more complicated, so let's clamp -+ * the number of CSG slots to MAX_CSG_PRIO + 1 for now. -+ */ -+ num_groups = min_t(u32, MAX_CSG_PRIO + 1, num_groups); -+ -+ /* We need at least one AS for the MCU and one for the GPU contexts. */ -+ gpu_as_count = hweight32(ptdev->gpu_info.as_present & GENMASK(31, 1)); -+ if (!gpu_as_count) { -+ drm_err(&ptdev->base, "Not enough AS (%d, expected at least 2)", -+ gpu_as_count + 1); -+ return -EINVAL; -+ } -+ -+ sched->ptdev = ptdev; -+ sched->sb_slot_count = CS_FEATURES_SCOREBOARDS(cs_iface->control->features); -+ sched->csg_slot_count = num_groups; -+ sched->cs_slot_count = csg_iface->control->stream_num; -+ sched->as_slot_count = gpu_as_count; -+ ptdev->csif_info.csg_slot_count = sched->csg_slot_count; -+ ptdev->csif_info.cs_slot_count = sched->cs_slot_count; -+ ptdev->csif_info.scoreboard_slot_count = sched->sb_slot_count; -+ -+ sched->last_tick = 0; -+ sched->resched_target = U64_MAX; -+ sched->tick_period = msecs_to_jiffies(10); -+ INIT_DELAYED_WORK(&sched->tick_work, tick_work); -+ INIT_WORK(&sched->sync_upd_work, sync_upd_work); -+ INIT_WORK(&sched->fw_events_work, process_fw_events_work); -+ -+ ret = drmm_mutex_init(&ptdev->base, &sched->lock); -+ if (ret) -+ return ret; -+ -+ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { -+ INIT_LIST_HEAD(&sched->groups.runnable[prio]); -+ INIT_LIST_HEAD(&sched->groups.idle[prio]); -+ } -+ INIT_LIST_HEAD(&sched->groups.waiting); -+ -+ ret = drmm_mutex_init(&ptdev->base, &sched->reset.lock); -+ if (ret) -+ return ret; -+ -+ INIT_LIST_HEAD(&sched->reset.stopped_groups); -+ -+ /* sched->heap_alloc_wq will be used for heap chunk allocation on -+ * tiler OOM events, which means we can't use the same workqueue for -+ * the scheduler because works queued by the scheduler are in -+ * the dma-signalling path. Allocate a dedicated heap_alloc_wq to -+ * work around this limitation. -+ * -+ * FIXME: Ultimately, what we need is a failable/non-blocking GEM -+ * allocation path that we can call when a heap OOM is reported. The -+ * FW is smart enough to fall back on other methods if the kernel can't -+ * allocate memory, and fail the tiling job if none of these -+ * countermeasures worked. -+ * -+ * Set WQ_MEM_RECLAIM on sched->wq to unblock the situation when the -+ * system is running out of memory. -+ */ -+ sched->heap_alloc_wq = alloc_workqueue("panthor-heap-alloc", WQ_UNBOUND, 0); -+ sched->wq = alloc_workqueue("panthor-csf-sched", WQ_MEM_RECLAIM | WQ_UNBOUND, 0); -+ if (!sched->wq || !sched->heap_alloc_wq) { -+ panthor_sched_fini(&ptdev->base, sched); -+ drm_err(&ptdev->base, "Failed to allocate the workqueues"); -+ return -ENOMEM; -+ } -+ -+ ret = drmm_add_action_or_reset(&ptdev->base, panthor_sched_fini, sched); -+ if (ret) -+ return ret; -+ -+ ptdev->scheduler = sched; -+ return 0; -+} -diff --git a/drivers/gpu/drm/panthor/panthor_sched.h b/drivers/gpu/drm/panthor/panthor_sched.h -new file mode 100644 -index 000000000000..66438b1f331f ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_sched.h -@@ -0,0 +1,50 @@ -+/* SPDX-License-Identifier: GPL-2.0 or MIT */ -+/* Copyright 2023 Collabora ltd. */ -+ -+#ifndef __PANTHOR_SCHED_H__ -+#define __PANTHOR_SCHED_H__ -+ -+struct drm_exec; -+struct dma_fence; -+struct drm_file; -+struct drm_gem_object; -+struct drm_sched_job; -+struct drm_panthor_group_create; -+struct drm_panthor_queue_create; -+struct drm_panthor_group_get_state; -+struct drm_panthor_queue_submit; -+struct panthor_device; -+struct panthor_file; -+struct panthor_group_pool; -+struct panthor_job; -+ -+int panthor_group_create(struct panthor_file *pfile, -+ const struct drm_panthor_group_create *group_args, -+ const struct drm_panthor_queue_create *queue_args); -+int panthor_group_destroy(struct panthor_file *pfile, u32 group_handle); -+int panthor_group_get_state(struct panthor_file *pfile, -+ struct drm_panthor_group_get_state *get_state); -+ -+struct drm_sched_job * -+panthor_job_create(struct panthor_file *pfile, -+ u16 group_handle, -+ const struct drm_panthor_queue_submit *qsubmit); -+struct drm_sched_job *panthor_job_get(struct drm_sched_job *job); -+struct panthor_vm *panthor_job_vm(struct drm_sched_job *sched_job); -+void panthor_job_put(struct drm_sched_job *job); -+void panthor_job_update_resvs(struct drm_exec *exec, struct drm_sched_job *job); -+ -+int panthor_group_pool_create(struct panthor_file *pfile); -+void panthor_group_pool_destroy(struct panthor_file *pfile); -+ -+int panthor_sched_init(struct panthor_device *ptdev); -+void panthor_sched_unplug(struct panthor_device *ptdev); -+void panthor_sched_pre_reset(struct panthor_device *ptdev); -+void panthor_sched_post_reset(struct panthor_device *ptdev); -+void panthor_sched_suspend(struct panthor_device *ptdev); -+void panthor_sched_resume(struct panthor_device *ptdev); -+ -+void panthor_sched_report_mmu_fault(struct panthor_device *ptdev); -+void panthor_sched_report_fw_events(struct panthor_device *ptdev, u32 events); -+ -+#endif --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:25 +0100 -Subject: drm/panthor: Add the driver frontend block - -This is the last piece missing to expose the driver to the outside -world. - -This is basically a wrapper between the ioctls and the other logical -blocks. - -v6: -- Add Maxime's and Heiko's acks -- Return a page-aligned BO size to userspace -- Keep header inclusion alphabetically ordered - -v5: -- Account for the drm_exec_init() prototype change -- Include platform_device.h - -v4: -- Add an ioctl to let the UMD query the VM state -- Fix kernel doc -- Let panthor_device_init() call panthor_device_init() -- Fix cleanup ordering in the panthor_init() error path -- Add Steve's and Liviu's R-b - -v3: -- Add acks for the MIT/GPL2 relicensing -- Fix 32-bit support -- Account for panthor_vm and panthor_sched changes -- Simplify the resv preparation/update logic -- Use a linked list rather than xarray for list of signals. -- Simplify panthor_get_uobj_array by returning the newly allocated - array. -- Drop the "DOC" for job submission helpers and move the relevant - comments to panthor_ioctl_group_submit(). -- Add helpers sync_op_is_signal()/sync_op_is_wait(). -- Simplify return type of panthor_submit_ctx_add_sync_signal() and - panthor_submit_ctx_get_sync_signal(). -- Drop WARN_ON from panthor_submit_ctx_add_job(). -- Fix typos in comments. - -Co-developed-by: Steven Price -Signed-off-by: Steven Price -Signed-off-by: Boris Brezillon -Acked-by: Steven Price # MIT+GPL2 relicensing,Arm -Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro -Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora -Reviewed-by: Steven Price -Reviewed-by: Liviu Dudau -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - drivers/gpu/drm/panthor/panthor_drv.c | 1473 ++++++++++ - 1 file changed, 1473 insertions(+) - -diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c -new file mode 100644 -index 000000000000..ff484506229f ---- /dev/null -+++ b/drivers/gpu/drm/panthor/panthor_drv.c -@@ -0,0 +1,1473 @@ -+// SPDX-License-Identifier: GPL-2.0 or MIT -+/* Copyright 2018 Marty E. Plummer */ -+/* Copyright 2019 Linaro, Ltd., Rob Herring */ -+/* Copyright 2019 Collabora ltd. */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "panthor_device.h" -+#include "panthor_fw.h" -+#include "panthor_gem.h" -+#include "panthor_gpu.h" -+#include "panthor_heap.h" -+#include "panthor_mmu.h" -+#include "panthor_regs.h" -+#include "panthor_sched.h" -+ -+/** -+ * DOC: user <-> kernel object copy helpers. -+ */ -+ -+/** -+ * panthor_set_uobj() - Copy kernel object to user object. -+ * @usr_ptr: Users pointer. -+ * @usr_size: Size of the user object. -+ * @min_size: Minimum size for this object. -+ * @kern_size: Size of the kernel object. -+ * @in: Address of the kernel object to copy. -+ * -+ * Helper automating kernel -> user object copies. -+ * -+ * Don't use this function directly, use PANTHOR_UOBJ_SET() instead. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+static int -+panthor_set_uobj(u64 usr_ptr, u32 usr_size, u32 min_size, u32 kern_size, const void *in) -+{ -+ /* User size shouldn't be smaller than the minimal object size. */ -+ if (usr_size < min_size) -+ return -EINVAL; -+ -+ if (copy_to_user(u64_to_user_ptr(usr_ptr), in, min_t(u32, usr_size, kern_size))) -+ return -EFAULT; -+ -+ /* When the kernel object is smaller than the user object, we fill the gap with -+ * zeros. -+ */ -+ if (usr_size > kern_size && -+ clear_user(u64_to_user_ptr(usr_ptr + kern_size), usr_size - kern_size)) { -+ return -EFAULT; -+ } -+ -+ return 0; -+} -+ -+/** -+ * panthor_get_uobj_array() - Copy a user object array into a kernel accessible object array. -+ * @in: The object array to copy. -+ * @min_stride: Minimum array stride. -+ * @obj_size: Kernel object size. -+ * -+ * Helper automating user -> kernel object copies. -+ * -+ * Don't use this function directly, use PANTHOR_UOBJ_GET_ARRAY() instead. -+ * -+ * Return: newly allocated object array or an ERR_PTR on error. -+ */ -+static void * -+panthor_get_uobj_array(const struct drm_panthor_obj_array *in, u32 min_stride, -+ u32 obj_size) -+{ -+ int ret = 0; -+ void *out_alloc; -+ -+ /* User stride must be at least the minimum object size, otherwise it might -+ * lack useful information. -+ */ -+ if (in->stride < min_stride) -+ return ERR_PTR(-EINVAL); -+ -+ if (!in->count) -+ return NULL; -+ -+ out_alloc = kvmalloc_array(in->count, obj_size, GFP_KERNEL); -+ if (!out_alloc) -+ return ERR_PTR(-ENOMEM); -+ -+ if (obj_size == in->stride) { -+ /* Fast path when user/kernel have the same uAPI header version. */ -+ if (copy_from_user(out_alloc, u64_to_user_ptr(in->array), -+ (unsigned long)obj_size * in->count)) -+ ret = -EFAULT; -+ } else { -+ void __user *in_ptr = u64_to_user_ptr(in->array); -+ void *out_ptr = out_alloc; -+ -+ /* If the sizes differ, we need to copy elements one by one. */ -+ for (u32 i = 0; i < in->count; i++) { -+ ret = copy_struct_from_user(out_ptr, obj_size, in_ptr, in->stride); -+ if (ret) -+ break; -+ -+ out_ptr += obj_size; -+ in_ptr += in->stride; -+ } -+ } -+ -+ if (ret) { -+ kvfree(out_alloc); -+ return ERR_PTR(ret); -+ } -+ -+ return out_alloc; -+} -+ -+/** -+ * PANTHOR_UOBJ_MIN_SIZE_INTERNAL() - Get the minimum user object size -+ * @_typename: Object type. -+ * @_last_mandatory_field: Last mandatory field. -+ * -+ * Get the minimum user object size based on the last mandatory field name, -+ * A.K.A, the name of the last field of the structure at the time this -+ * structure was added to the uAPI. -+ * -+ * Don't use directly, use PANTHOR_UOBJ_DECL() instead. -+ */ -+#define PANTHOR_UOBJ_MIN_SIZE_INTERNAL(_typename, _last_mandatory_field) \ -+ (offsetof(_typename, _last_mandatory_field) + \ -+ sizeof(((_typename *)NULL)->_last_mandatory_field)) -+ -+/** -+ * PANTHOR_UOBJ_DECL() - Declare a new uAPI object whose subject to -+ * evolutions. -+ * @_typename: Object type. -+ * @_last_mandatory_field: Last mandatory field. -+ * -+ * Should be used to extend the PANTHOR_UOBJ_MIN_SIZE() list. -+ */ -+#define PANTHOR_UOBJ_DECL(_typename, _last_mandatory_field) \ -+ _typename : PANTHOR_UOBJ_MIN_SIZE_INTERNAL(_typename, _last_mandatory_field) -+ -+/** -+ * PANTHOR_UOBJ_MIN_SIZE() - Get the minimum size of a given uAPI object -+ * @_obj_name: Object to get the minimum size of. -+ * -+ * Don't use this macro directly, it's automatically called by -+ * PANTHOR_UOBJ_{SET,GET_ARRAY}(). -+ */ -+#define PANTHOR_UOBJ_MIN_SIZE(_obj_name) \ -+ _Generic(_obj_name, \ -+ PANTHOR_UOBJ_DECL(struct drm_panthor_gpu_info, tiler_present), \ -+ PANTHOR_UOBJ_DECL(struct drm_panthor_csif_info, pad), \ -+ PANTHOR_UOBJ_DECL(struct drm_panthor_sync_op, timeline_value), \ -+ PANTHOR_UOBJ_DECL(struct drm_panthor_queue_submit, syncs), \ -+ PANTHOR_UOBJ_DECL(struct drm_panthor_queue_create, ringbuf_size), \ -+ PANTHOR_UOBJ_DECL(struct drm_panthor_vm_bind_op, syncs)) -+ -+/** -+ * PANTHOR_UOBJ_SET() - Copy a kernel object to a user object. -+ * @_dest_usr_ptr: User pointer to copy to. -+ * @_usr_size: Size of the user object. -+ * @_src_obj: Kernel object to copy (not a pointer). -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+#define PANTHOR_UOBJ_SET(_dest_usr_ptr, _usr_size, _src_obj) \ -+ panthor_set_uobj(_dest_usr_ptr, _usr_size, \ -+ PANTHOR_UOBJ_MIN_SIZE(_src_obj), \ -+ sizeof(_src_obj), &(_src_obj)) -+ -+/** -+ * PANTHOR_UOBJ_GET_ARRAY() - Copy a user object array to a kernel accessible -+ * object array. -+ * @_dest_array: Local variable that will hold the newly allocated kernel -+ * object array. -+ * @_uobj_array: The drm_panthor_obj_array object describing the user object -+ * array. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+#define PANTHOR_UOBJ_GET_ARRAY(_dest_array, _uobj_array) \ -+ ({ \ -+ typeof(_dest_array) _tmp; \ -+ _tmp = panthor_get_uobj_array(_uobj_array, \ -+ PANTHOR_UOBJ_MIN_SIZE((_dest_array)[0]), \ -+ sizeof((_dest_array)[0])); \ -+ if (!IS_ERR(_tmp)) \ -+ _dest_array = _tmp; \ -+ PTR_ERR_OR_ZERO(_tmp); \ -+ }) -+ -+/** -+ * struct panthor_sync_signal - Represent a synchronization object point to attach -+ * our job fence to. -+ * -+ * This structure is here to keep track of fences that are currently bound to -+ * a specific syncobj point. -+ * -+ * At the beginning of a job submission, the fence -+ * is retrieved from the syncobj itself, and can be NULL if no fence was attached -+ * to this point. -+ * -+ * At the end, it points to the fence of the last job that had a -+ * %DRM_PANTHOR_SYNC_OP_SIGNAL on this syncobj. -+ * -+ * With jobs being submitted in batches, the fence might change several times during -+ * the process, allowing one job to wait on a job that's part of the same submission -+ * but appears earlier in the drm_panthor_group_submit::queue_submits array. -+ */ -+struct panthor_sync_signal { -+ /** @node: list_head to track signal ops within a submit operation */ -+ struct list_head node; -+ -+ /** @handle: The syncobj handle. */ -+ u32 handle; -+ -+ /** -+ * @point: The syncobj point. -+ * -+ * Zero for regular syncobjs, and non-zero for timeline syncobjs. -+ */ -+ u64 point; -+ -+ /** -+ * @syncobj: The sync object pointed by @handle. -+ */ -+ struct drm_syncobj *syncobj; -+ -+ /** -+ * @chain: Chain object used to link the new fence to an existing -+ * timeline syncobj. -+ * -+ * NULL for regular syncobj, non-NULL for timeline syncobjs. -+ */ -+ struct dma_fence_chain *chain; -+ -+ /** -+ * @fence: The fence to assign to the syncobj or syncobj-point. -+ */ -+ struct dma_fence *fence; -+}; -+ -+/** -+ * struct panthor_job_ctx - Job context -+ */ -+struct panthor_job_ctx { -+ /** @job: The job that is about to be submitted to drm_sched. */ -+ struct drm_sched_job *job; -+ -+ /** @syncops: Array of sync operations. */ -+ struct drm_panthor_sync_op *syncops; -+ -+ /** @syncop_count: Number of sync operations. */ -+ u32 syncop_count; -+}; -+ -+/** -+ * struct panthor_submit_ctx - Submission context -+ * -+ * Anything that's related to a submission (%DRM_IOCTL_PANTHOR_VM_BIND or -+ * %DRM_IOCTL_PANTHOR_GROUP_SUBMIT) is kept here, so we can automate the -+ * initialization and cleanup steps. -+ */ -+struct panthor_submit_ctx { -+ /** @file: DRM file this submission happens on. */ -+ struct drm_file *file; -+ -+ /** -+ * @signals: List of struct panthor_sync_signal. -+ * -+ * %DRM_PANTHOR_SYNC_OP_SIGNAL operations will be recorded here, -+ * and %DRM_PANTHOR_SYNC_OP_WAIT will first check if an entry -+ * matching the syncobj+point exists before calling -+ * drm_syncobj_find_fence(). This allows us to describe dependencies -+ * existing between jobs that are part of the same batch. -+ */ -+ struct list_head signals; -+ -+ /** @jobs: Array of jobs. */ -+ struct panthor_job_ctx *jobs; -+ -+ /** @job_count: Number of entries in the @jobs array. */ -+ u32 job_count; -+ -+ /** @exec: drm_exec context used to acquire and prepare resv objects. */ -+ struct drm_exec exec; -+}; -+ -+#define PANTHOR_SYNC_OP_FLAGS_MASK \ -+ (DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK | DRM_PANTHOR_SYNC_OP_SIGNAL) -+ -+static bool sync_op_is_signal(const struct drm_panthor_sync_op *sync_op) -+{ -+ return !!(sync_op->flags & DRM_PANTHOR_SYNC_OP_SIGNAL); -+} -+ -+static bool sync_op_is_wait(const struct drm_panthor_sync_op *sync_op) -+{ -+ /* Note that DRM_PANTHOR_SYNC_OP_WAIT == 0 */ -+ return !(sync_op->flags & DRM_PANTHOR_SYNC_OP_SIGNAL); -+} -+ -+/** -+ * panthor_check_sync_op() - Check drm_panthor_sync_op fields -+ * @sync_op: The sync operation to check. -+ * -+ * Return: 0 on success, -EINVAL otherwise. -+ */ -+static int -+panthor_check_sync_op(const struct drm_panthor_sync_op *sync_op) -+{ -+ u8 handle_type; -+ -+ if (sync_op->flags & ~PANTHOR_SYNC_OP_FLAGS_MASK) -+ return -EINVAL; -+ -+ handle_type = sync_op->flags & DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK; -+ if (handle_type != DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ && -+ handle_type != DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ) -+ return -EINVAL; -+ -+ if (handle_type == DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ && -+ sync_op->timeline_value != 0) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+/** -+ * panthor_sync_signal_free() - Release resources and free a panthor_sync_signal object -+ * @sig_sync: Signal object to free. -+ */ -+static void -+panthor_sync_signal_free(struct panthor_sync_signal *sig_sync) -+{ -+ if (!sig_sync) -+ return; -+ -+ drm_syncobj_put(sig_sync->syncobj); -+ dma_fence_chain_free(sig_sync->chain); -+ dma_fence_put(sig_sync->fence); -+ kfree(sig_sync); -+} -+ -+/** -+ * panthor_submit_ctx_add_sync_signal() - Add a signal operation to a submit context -+ * @ctx: Context to add the signal operation to. -+ * @handle: Syncobj handle. -+ * @point: Syncobj point. -+ * -+ * Return: 0 on success, otherwise negative error value. -+ */ -+static int -+panthor_submit_ctx_add_sync_signal(struct panthor_submit_ctx *ctx, u32 handle, u64 point) -+{ -+ struct panthor_sync_signal *sig_sync; -+ struct dma_fence *cur_fence; -+ int ret; -+ -+ sig_sync = kzalloc(sizeof(*sig_sync), GFP_KERNEL); -+ if (!sig_sync) -+ return -ENOMEM; -+ -+ sig_sync->handle = handle; -+ sig_sync->point = point; -+ -+ if (point > 0) { -+ sig_sync->chain = dma_fence_chain_alloc(); -+ if (!sig_sync->chain) { -+ ret = -ENOMEM; -+ goto err_free_sig_sync; -+ } -+ } -+ -+ sig_sync->syncobj = drm_syncobj_find(ctx->file, handle); -+ if (!sig_sync->syncobj) { -+ ret = -EINVAL; -+ goto err_free_sig_sync; -+ } -+ -+ /* Retrieve the current fence attached to that point. It's -+ * perfectly fine to get a NULL fence here, it just means there's -+ * no fence attached to that point yet. -+ */ -+ if (!drm_syncobj_find_fence(ctx->file, handle, point, 0, &cur_fence)) -+ sig_sync->fence = cur_fence; -+ -+ list_add_tail(&sig_sync->node, &ctx->signals); -+ -+ return 0; -+ -+err_free_sig_sync: -+ panthor_sync_signal_free(sig_sync); -+ return ret; -+} -+ -+/** -+ * panthor_submit_ctx_search_sync_signal() - Search an existing signal operation in a -+ * submit context. -+ * @ctx: Context to search the signal operation in. -+ * @handle: Syncobj handle. -+ * @point: Syncobj point. -+ * -+ * Return: A valid panthor_sync_signal object if found, NULL otherwise. -+ */ -+static struct panthor_sync_signal * -+panthor_submit_ctx_search_sync_signal(struct panthor_submit_ctx *ctx, u32 handle, u64 point) -+{ -+ struct panthor_sync_signal *sig_sync; -+ -+ list_for_each_entry(sig_sync, &ctx->signals, node) { -+ if (handle == sig_sync->handle && point == sig_sync->point) -+ return sig_sync; -+ } -+ -+ return NULL; -+} -+ -+/** -+ * panthor_submit_ctx_add_job() - Add a job to a submit context -+ * @ctx: Context to search the signal operation in. -+ * @idx: Index of the job in the context. -+ * @job: Job to add. -+ * @syncs: Sync operations provided by userspace. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+static int -+panthor_submit_ctx_add_job(struct panthor_submit_ctx *ctx, u32 idx, -+ struct drm_sched_job *job, -+ const struct drm_panthor_obj_array *syncs) -+{ -+ int ret; -+ -+ ctx->jobs[idx].job = job; -+ -+ ret = PANTHOR_UOBJ_GET_ARRAY(ctx->jobs[idx].syncops, syncs); -+ if (ret) -+ return ret; -+ -+ ctx->jobs[idx].syncop_count = syncs->count; -+ return 0; -+} -+ -+/** -+ * panthor_submit_ctx_get_sync_signal() - Search signal operation and add one if none was found. -+ * @ctx: Context to search the signal operation in. -+ * @handle: Syncobj handle. -+ * @point: Syncobj point. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+static int -+panthor_submit_ctx_get_sync_signal(struct panthor_submit_ctx *ctx, u32 handle, u64 point) -+{ -+ struct panthor_sync_signal *sig_sync; -+ -+ sig_sync = panthor_submit_ctx_search_sync_signal(ctx, handle, point); -+ if (sig_sync) -+ return 0; -+ -+ return panthor_submit_ctx_add_sync_signal(ctx, handle, point); -+} -+ -+/** -+ * panthor_submit_ctx_update_job_sync_signal_fences() - Update fences -+ * on the signal operations specified by a job. -+ * @ctx: Context to search the signal operation in. -+ * @job_idx: Index of the job to operate on. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+static int -+panthor_submit_ctx_update_job_sync_signal_fences(struct panthor_submit_ctx *ctx, -+ u32 job_idx) -+{ -+ struct panthor_device *ptdev = container_of(ctx->file->minor->dev, -+ struct panthor_device, -+ base); -+ struct dma_fence *done_fence = &ctx->jobs[job_idx].job->s_fence->finished; -+ const struct drm_panthor_sync_op *sync_ops = ctx->jobs[job_idx].syncops; -+ u32 sync_op_count = ctx->jobs[job_idx].syncop_count; -+ -+ for (u32 i = 0; i < sync_op_count; i++) { -+ struct dma_fence *old_fence; -+ struct panthor_sync_signal *sig_sync; -+ -+ if (!sync_op_is_signal(&sync_ops[i])) -+ continue; -+ -+ sig_sync = panthor_submit_ctx_search_sync_signal(ctx, sync_ops[i].handle, -+ sync_ops[i].timeline_value); -+ if (drm_WARN_ON(&ptdev->base, !sig_sync)) -+ return -EINVAL; -+ -+ old_fence = sig_sync->fence; -+ sig_sync->fence = dma_fence_get(done_fence); -+ dma_fence_put(old_fence); -+ -+ if (drm_WARN_ON(&ptdev->base, !sig_sync->fence)) -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/** -+ * panthor_submit_ctx_collect_job_signal_ops() - Iterate over all job signal operations -+ * and add them to the context. -+ * @ctx: Context to search the signal operation in. -+ * @job_idx: Index of the job to operate on. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+static int -+panthor_submit_ctx_collect_job_signal_ops(struct panthor_submit_ctx *ctx, -+ u32 job_idx) -+{ -+ const struct drm_panthor_sync_op *sync_ops = ctx->jobs[job_idx].syncops; -+ u32 sync_op_count = ctx->jobs[job_idx].syncop_count; -+ -+ for (u32 i = 0; i < sync_op_count; i++) { -+ int ret; -+ -+ if (!sync_op_is_signal(&sync_ops[i])) -+ continue; -+ -+ ret = panthor_check_sync_op(&sync_ops[i]); -+ if (ret) -+ return ret; -+ -+ ret = panthor_submit_ctx_get_sync_signal(ctx, -+ sync_ops[i].handle, -+ sync_ops[i].timeline_value); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * panthor_submit_ctx_push_fences() - Iterate over the signal array, and for each entry, push -+ * the currently assigned fence to the associated syncobj. -+ * @ctx: Context to push fences on. -+ * -+ * This is the last step of a submission procedure, and is done once we know the submission -+ * is effective and job fences are guaranteed to be signaled in finite time. -+ */ -+static void -+panthor_submit_ctx_push_fences(struct panthor_submit_ctx *ctx) -+{ -+ struct panthor_sync_signal *sig_sync; -+ -+ list_for_each_entry(sig_sync, &ctx->signals, node) { -+ if (sig_sync->chain) { -+ drm_syncobj_add_point(sig_sync->syncobj, sig_sync->chain, -+ sig_sync->fence, sig_sync->point); -+ sig_sync->chain = NULL; -+ } else { -+ drm_syncobj_replace_fence(sig_sync->syncobj, sig_sync->fence); -+ } -+ } -+} -+ -+/** -+ * panthor_submit_ctx_add_sync_deps_to_job() - Add sync wait operations as -+ * job dependencies. -+ * @ctx: Submit context. -+ * @job_idx: Index of the job to operate on. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+static int -+panthor_submit_ctx_add_sync_deps_to_job(struct panthor_submit_ctx *ctx, -+ u32 job_idx) -+{ -+ struct panthor_device *ptdev = container_of(ctx->file->minor->dev, -+ struct panthor_device, -+ base); -+ const struct drm_panthor_sync_op *sync_ops = ctx->jobs[job_idx].syncops; -+ struct drm_sched_job *job = ctx->jobs[job_idx].job; -+ u32 sync_op_count = ctx->jobs[job_idx].syncop_count; -+ int ret = 0; -+ -+ for (u32 i = 0; i < sync_op_count; i++) { -+ struct panthor_sync_signal *sig_sync; -+ struct dma_fence *fence; -+ -+ if (!sync_op_is_wait(&sync_ops[i])) -+ continue; -+ -+ ret = panthor_check_sync_op(&sync_ops[i]); -+ if (ret) -+ return ret; -+ -+ sig_sync = panthor_submit_ctx_search_sync_signal(ctx, sync_ops[i].handle, -+ sync_ops[i].timeline_value); -+ if (sig_sync) { -+ if (drm_WARN_ON(&ptdev->base, !sig_sync->fence)) -+ return -EINVAL; -+ -+ fence = dma_fence_get(sig_sync->fence); -+ } else { -+ ret = drm_syncobj_find_fence(ctx->file, sync_ops[i].handle, -+ sync_ops[i].timeline_value, -+ 0, &fence); -+ if (ret) -+ return ret; -+ } -+ -+ ret = drm_sched_job_add_dependency(job, fence); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * panthor_submit_ctx_collect_jobs_signal_ops() - Collect all signal operations -+ * and add them to the submit context. -+ * @ctx: Submit context. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+static int -+panthor_submit_ctx_collect_jobs_signal_ops(struct panthor_submit_ctx *ctx) -+{ -+ for (u32 i = 0; i < ctx->job_count; i++) { -+ int ret; -+ -+ ret = panthor_submit_ctx_collect_job_signal_ops(ctx, i); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * panthor_submit_ctx_add_deps_and_arm_jobs() - Add jobs dependencies and arm jobs -+ * @ctx: Submit context. -+ * -+ * Must be called after the resv preparation has been taken care of. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+static int -+panthor_submit_ctx_add_deps_and_arm_jobs(struct panthor_submit_ctx *ctx) -+{ -+ for (u32 i = 0; i < ctx->job_count; i++) { -+ int ret; -+ -+ ret = panthor_submit_ctx_add_sync_deps_to_job(ctx, i); -+ if (ret) -+ return ret; -+ -+ drm_sched_job_arm(ctx->jobs[i].job); -+ -+ ret = panthor_submit_ctx_update_job_sync_signal_fences(ctx, i); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/** -+ * panthor_submit_ctx_push_jobs() - Push jobs to their scheduling entities. -+ * @ctx: Submit context. -+ * @upd_resvs: Callback used to update reservation objects that were previously -+ * preapred. -+ */ -+static void -+panthor_submit_ctx_push_jobs(struct panthor_submit_ctx *ctx, -+ void (*upd_resvs)(struct drm_exec *, struct drm_sched_job *)) -+{ -+ for (u32 i = 0; i < ctx->job_count; i++) { -+ upd_resvs(&ctx->exec, ctx->jobs[i].job); -+ drm_sched_entity_push_job(ctx->jobs[i].job); -+ -+ /* Job is owned by the scheduler now. */ -+ ctx->jobs[i].job = NULL; -+ } -+ -+ panthor_submit_ctx_push_fences(ctx); -+} -+ -+/** -+ * panthor_submit_ctx_init() - Initializes a submission context -+ * @ctx: Submit context to initialize. -+ * @file: drm_file this submission happens on. -+ * @job_count: Number of jobs that will be submitted. -+ * -+ * Return: 0 on success, a negative error code otherwise. -+ */ -+static int panthor_submit_ctx_init(struct panthor_submit_ctx *ctx, -+ struct drm_file *file, u32 job_count) -+{ -+ ctx->jobs = kvmalloc_array(job_count, sizeof(*ctx->jobs), -+ GFP_KERNEL | __GFP_ZERO); -+ if (!ctx->jobs) -+ return -ENOMEM; -+ -+ ctx->file = file; -+ ctx->job_count = job_count; -+ INIT_LIST_HEAD(&ctx->signals); -+ drm_exec_init(&ctx->exec, -+ DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES, -+ 0); -+ return 0; -+} -+ -+/** -+ * panthor_submit_ctx_cleanup() - Cleanup a submission context -+ * @ctx: Submit context to cleanup. -+ * @job_put: Job put callback. -+ */ -+static void panthor_submit_ctx_cleanup(struct panthor_submit_ctx *ctx, -+ void (*job_put)(struct drm_sched_job *)) -+{ -+ struct panthor_sync_signal *sig_sync, *tmp; -+ unsigned long i; -+ -+ drm_exec_fini(&ctx->exec); -+ -+ list_for_each_entry_safe(sig_sync, tmp, &ctx->signals, node) -+ panthor_sync_signal_free(sig_sync); -+ -+ for (i = 0; i < ctx->job_count; i++) { -+ job_put(ctx->jobs[i].job); -+ kvfree(ctx->jobs[i].syncops); -+ } -+ -+ kvfree(ctx->jobs); -+} -+ -+static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct drm_file *file) -+{ -+ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); -+ struct drm_panthor_dev_query *args = data; -+ -+ if (!args->pointer) { -+ switch (args->type) { -+ case DRM_PANTHOR_DEV_QUERY_GPU_INFO: -+ args->size = sizeof(ptdev->gpu_info); -+ return 0; -+ -+ case DRM_PANTHOR_DEV_QUERY_CSIF_INFO: -+ args->size = sizeof(ptdev->csif_info); -+ return 0; -+ -+ default: -+ return -EINVAL; -+ } -+ } -+ -+ switch (args->type) { -+ case DRM_PANTHOR_DEV_QUERY_GPU_INFO: -+ return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->gpu_info); -+ -+ case DRM_PANTHOR_DEV_QUERY_CSIF_INFO: -+ return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->csif_info); -+ -+ default: -+ return -EINVAL; -+ } -+} -+ -+#define PANTHOR_VM_CREATE_FLAGS 0 -+ -+static int panthor_ioctl_vm_create(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_vm_create *args = data; -+ int cookie, ret; -+ -+ if (!drm_dev_enter(ddev, &cookie)) -+ return -ENODEV; -+ -+ ret = panthor_vm_pool_create_vm(ptdev, pfile->vms, args); -+ if (ret >= 0) { -+ args->id = ret; -+ ret = 0; -+ } -+ -+ drm_dev_exit(cookie); -+ return ret; -+} -+ -+static int panthor_ioctl_vm_destroy(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_vm_destroy *args = data; -+ -+ if (args->pad) -+ return -EINVAL; -+ -+ return panthor_vm_pool_destroy_vm(pfile->vms, args->id); -+} -+ -+#define PANTHOR_BO_FLAGS DRM_PANTHOR_BO_NO_MMAP -+ -+static int panthor_ioctl_bo_create(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_bo_create *args = data; -+ struct panthor_vm *vm = NULL; -+ int cookie, ret; -+ -+ if (!drm_dev_enter(ddev, &cookie)) -+ return -ENODEV; -+ -+ if (!args->size || args->pad || -+ (args->flags & ~PANTHOR_BO_FLAGS)) { -+ ret = -EINVAL; -+ goto out_dev_exit; -+ } -+ -+ if (args->exclusive_vm_id) { -+ vm = panthor_vm_pool_get_vm(pfile->vms, args->exclusive_vm_id); -+ if (!vm) { -+ ret = -EINVAL; -+ goto out_dev_exit; -+ } -+ } -+ -+ ret = panthor_gem_create_with_handle(file, ddev, vm, &args->size, -+ args->flags, &args->handle); -+ -+ panthor_vm_put(vm); -+ -+out_dev_exit: -+ drm_dev_exit(cookie); -+ return ret; -+} -+ -+static int panthor_ioctl_bo_mmap_offset(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct drm_panthor_bo_mmap_offset *args = data; -+ struct drm_gem_object *obj; -+ int ret; -+ -+ if (args->pad) -+ return -EINVAL; -+ -+ obj = drm_gem_object_lookup(file, args->handle); -+ if (!obj) -+ return -ENOENT; -+ -+ ret = drm_gem_create_mmap_offset(obj); -+ if (ret) -+ goto out; -+ -+ args->offset = drm_vma_node_offset_addr(&obj->vma_node); -+ -+out: -+ drm_gem_object_put(obj); -+ return ret; -+} -+ -+static int panthor_ioctl_group_submit(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_group_submit *args = data; -+ struct drm_panthor_queue_submit *jobs_args; -+ struct panthor_submit_ctx ctx; -+ int ret = 0, cookie; -+ -+ if (args->pad) -+ return -EINVAL; -+ -+ if (!drm_dev_enter(ddev, &cookie)) -+ return -ENODEV; -+ -+ ret = PANTHOR_UOBJ_GET_ARRAY(jobs_args, &args->queue_submits); -+ if (ret) -+ goto out_dev_exit; -+ -+ ret = panthor_submit_ctx_init(&ctx, file, args->queue_submits.count); -+ if (ret) -+ goto out_free_jobs_args; -+ -+ /* Create jobs and attach sync operations */ -+ for (u32 i = 0; i < args->queue_submits.count; i++) { -+ const struct drm_panthor_queue_submit *qsubmit = &jobs_args[i]; -+ struct drm_sched_job *job; -+ -+ job = panthor_job_create(pfile, args->group_handle, qsubmit); -+ if (IS_ERR(job)) { -+ ret = PTR_ERR(job); -+ goto out_cleanup_submit_ctx; -+ } -+ -+ ret = panthor_submit_ctx_add_job(&ctx, i, job, &qsubmit->syncs); -+ if (ret) -+ goto out_cleanup_submit_ctx; -+ } -+ -+ /* -+ * Collect signal operations on all jobs, such that each job can pick -+ * from it for its dependencies and update the fence to signal when the -+ * job is submitted. -+ */ -+ ret = panthor_submit_ctx_collect_jobs_signal_ops(&ctx); -+ if (ret) -+ goto out_cleanup_submit_ctx; -+ -+ /* -+ * We acquire/prepare revs on all jobs before proceeding with the -+ * dependency registration. -+ * -+ * This is solving two problems: -+ * 1. drm_sched_job_arm() and drm_sched_entity_push_job() must be -+ * protected by a lock to make sure no concurrent access to the same -+ * entity get interleaved, which would mess up with the fence seqno -+ * ordering. Luckily, one of the resv being acquired is the VM resv, -+ * and a scheduling entity is only bound to a single VM. As soon as -+ * we acquire the VM resv, we should be safe. -+ * 2. Jobs might depend on fences that were issued by previous jobs in -+ * the same batch, so we can't add dependencies on all jobs before -+ * arming previous jobs and registering the fence to the signal -+ * array, otherwise we might miss dependencies, or point to an -+ * outdated fence. -+ */ -+ if (args->queue_submits.count > 0) { -+ /* All jobs target the same group, so they also point to the same VM. */ -+ struct panthor_vm *vm = panthor_job_vm(ctx.jobs[0].job); -+ -+ drm_exec_until_all_locked(&ctx.exec) { -+ ret = panthor_vm_prepare_mapped_bos_resvs(&ctx.exec, vm, -+ args->queue_submits.count); -+ } -+ -+ if (ret) -+ goto out_cleanup_submit_ctx; -+ } -+ -+ /* -+ * Now that resvs are locked/prepared, we can iterate over each job to -+ * add the dependencies, arm the job fence, register the job fence to -+ * the signal array. -+ */ -+ ret = panthor_submit_ctx_add_deps_and_arm_jobs(&ctx); -+ if (ret) -+ goto out_cleanup_submit_ctx; -+ -+ /* Nothing can fail after that point, so we can make our job fences -+ * visible to the outside world. Push jobs and set the job fences to -+ * the resv slots we reserved. This also pushes the fences to the -+ * syncobjs that are part of the signal array. -+ */ -+ panthor_submit_ctx_push_jobs(&ctx, panthor_job_update_resvs); -+ -+out_cleanup_submit_ctx: -+ panthor_submit_ctx_cleanup(&ctx, panthor_job_put); -+ -+out_free_jobs_args: -+ kvfree(jobs_args); -+ -+out_dev_exit: -+ drm_dev_exit(cookie); -+ return ret; -+} -+ -+static int panthor_ioctl_group_destroy(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_group_destroy *args = data; -+ -+ if (args->pad) -+ return -EINVAL; -+ -+ return panthor_group_destroy(pfile, args->group_handle); -+} -+ -+static int panthor_ioctl_group_create(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_group_create *args = data; -+ struct drm_panthor_queue_create *queue_args; -+ int ret; -+ -+ if (!args->queues.count) -+ return -EINVAL; -+ -+ ret = PANTHOR_UOBJ_GET_ARRAY(queue_args, &args->queues); -+ if (ret) -+ return ret; -+ -+ ret = panthor_group_create(pfile, args, queue_args); -+ if (ret >= 0) { -+ args->group_handle = ret; -+ ret = 0; -+ } -+ -+ kvfree(queue_args); -+ return ret; -+} -+ -+static int panthor_ioctl_group_get_state(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_group_get_state *args = data; -+ -+ return panthor_group_get_state(pfile, args); -+} -+ -+static int panthor_ioctl_tiler_heap_create(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_tiler_heap_create *args = data; -+ struct panthor_heap_pool *pool; -+ struct panthor_vm *vm; -+ int ret; -+ -+ vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); -+ if (!vm) -+ return -EINVAL; -+ -+ pool = panthor_vm_get_heap_pool(vm, true); -+ if (IS_ERR(pool)) { -+ ret = PTR_ERR(pool); -+ goto out_put_vm; -+ } -+ -+ ret = panthor_heap_create(pool, -+ args->initial_chunk_count, -+ args->chunk_size, -+ args->max_chunks, -+ args->target_in_flight, -+ &args->tiler_heap_ctx_gpu_va, -+ &args->first_heap_chunk_gpu_va); -+ if (ret < 0) -+ goto out_put_heap_pool; -+ -+ /* Heap pools are per-VM. We combine the VM and HEAP id to make -+ * a unique heap handle. -+ */ -+ args->handle = (args->vm_id << 16) | ret; -+ ret = 0; -+ -+out_put_heap_pool: -+ panthor_heap_pool_put(pool); -+ -+out_put_vm: -+ panthor_vm_put(vm); -+ return ret; -+} -+ -+static int panthor_ioctl_tiler_heap_destroy(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_tiler_heap_destroy *args = data; -+ struct panthor_heap_pool *pool; -+ struct panthor_vm *vm; -+ int ret; -+ -+ if (args->pad) -+ return -EINVAL; -+ -+ vm = panthor_vm_pool_get_vm(pfile->vms, args->handle >> 16); -+ if (!vm) -+ return -EINVAL; -+ -+ pool = panthor_vm_get_heap_pool(vm, false); -+ if (!pool) { -+ ret = -EINVAL; -+ goto out_put_vm; -+ } -+ -+ ret = panthor_heap_destroy(pool, args->handle & GENMASK(15, 0)); -+ panthor_heap_pool_put(pool); -+ -+out_put_vm: -+ panthor_vm_put(vm); -+ return ret; -+} -+ -+static int panthor_ioctl_vm_bind_async(struct drm_device *ddev, -+ struct drm_panthor_vm_bind *args, -+ struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_vm_bind_op *jobs_args; -+ struct panthor_submit_ctx ctx; -+ struct panthor_vm *vm; -+ int ret = 0; -+ -+ vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); -+ if (!vm) -+ return -EINVAL; -+ -+ ret = PANTHOR_UOBJ_GET_ARRAY(jobs_args, &args->ops); -+ if (ret) -+ goto out_put_vm; -+ -+ ret = panthor_submit_ctx_init(&ctx, file, args->ops.count); -+ if (ret) -+ goto out_free_jobs_args; -+ -+ for (u32 i = 0; i < args->ops.count; i++) { -+ struct drm_panthor_vm_bind_op *op = &jobs_args[i]; -+ struct drm_sched_job *job; -+ -+ job = panthor_vm_bind_job_create(file, vm, op); -+ if (IS_ERR(job)) { -+ ret = PTR_ERR(job); -+ goto out_cleanup_submit_ctx; -+ } -+ -+ ret = panthor_submit_ctx_add_job(&ctx, i, job, &op->syncs); -+ if (ret) -+ goto out_cleanup_submit_ctx; -+ } -+ -+ ret = panthor_submit_ctx_collect_jobs_signal_ops(&ctx); -+ if (ret) -+ goto out_cleanup_submit_ctx; -+ -+ /* Prepare reservation objects for each VM_BIND job. */ -+ drm_exec_until_all_locked(&ctx.exec) { -+ for (u32 i = 0; i < ctx.job_count; i++) { -+ ret = panthor_vm_bind_job_prepare_resvs(&ctx.exec, ctx.jobs[i].job); -+ drm_exec_retry_on_contention(&ctx.exec); -+ if (ret) -+ goto out_cleanup_submit_ctx; -+ } -+ } -+ -+ ret = panthor_submit_ctx_add_deps_and_arm_jobs(&ctx); -+ if (ret) -+ goto out_cleanup_submit_ctx; -+ -+ /* Nothing can fail after that point. */ -+ panthor_submit_ctx_push_jobs(&ctx, panthor_vm_bind_job_update_resvs); -+ -+out_cleanup_submit_ctx: -+ panthor_submit_ctx_cleanup(&ctx, panthor_vm_bind_job_put); -+ -+out_free_jobs_args: -+ kvfree(jobs_args); -+ -+out_put_vm: -+ panthor_vm_put(vm); -+ return ret; -+} -+ -+static int panthor_ioctl_vm_bind_sync(struct drm_device *ddev, -+ struct drm_panthor_vm_bind *args, -+ struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_vm_bind_op *jobs_args; -+ struct panthor_vm *vm; -+ int ret; -+ -+ vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); -+ if (!vm) -+ return -EINVAL; -+ -+ ret = PANTHOR_UOBJ_GET_ARRAY(jobs_args, &args->ops); -+ if (ret) -+ goto out_put_vm; -+ -+ for (u32 i = 0; i < args->ops.count; i++) { -+ ret = panthor_vm_bind_exec_sync_op(file, vm, &jobs_args[i]); -+ if (ret) { -+ /* Update ops.count so the user knows where things failed. */ -+ args->ops.count = i; -+ break; -+ } -+ } -+ -+ kvfree(jobs_args); -+ -+out_put_vm: -+ panthor_vm_put(vm); -+ return ret; -+} -+ -+#define PANTHOR_VM_BIND_FLAGS DRM_PANTHOR_VM_BIND_ASYNC -+ -+static int panthor_ioctl_vm_bind(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct drm_panthor_vm_bind *args = data; -+ int cookie, ret; -+ -+ if (!drm_dev_enter(ddev, &cookie)) -+ return -ENODEV; -+ -+ if (args->flags & DRM_PANTHOR_VM_BIND_ASYNC) -+ ret = panthor_ioctl_vm_bind_async(ddev, args, file); -+ else -+ ret = panthor_ioctl_vm_bind_sync(ddev, args, file); -+ -+ drm_dev_exit(cookie); -+ return ret; -+} -+ -+static int panthor_ioctl_vm_get_state(struct drm_device *ddev, void *data, -+ struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ struct drm_panthor_vm_get_state *args = data; -+ struct panthor_vm *vm; -+ -+ vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); -+ if (!vm) -+ return -EINVAL; -+ -+ if (panthor_vm_is_unusable(vm)) -+ args->state = DRM_PANTHOR_VM_STATE_UNUSABLE; -+ else -+ args->state = DRM_PANTHOR_VM_STATE_USABLE; -+ -+ panthor_vm_put(vm); -+ return 0; -+} -+ -+static int -+panthor_open(struct drm_device *ddev, struct drm_file *file) -+{ -+ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); -+ struct panthor_file *pfile; -+ int ret; -+ -+ if (!try_module_get(THIS_MODULE)) -+ return -EINVAL; -+ -+ pfile = kzalloc(sizeof(*pfile), GFP_KERNEL); -+ if (!pfile) { -+ ret = -ENOMEM; -+ goto err_put_mod; -+ } -+ -+ pfile->ptdev = ptdev; -+ -+ ret = panthor_vm_pool_create(pfile); -+ if (ret) -+ goto err_free_file; -+ -+ ret = panthor_group_pool_create(pfile); -+ if (ret) -+ goto err_destroy_vm_pool; -+ -+ file->driver_priv = pfile; -+ return 0; -+ -+err_destroy_vm_pool: -+ panthor_vm_pool_destroy(pfile); -+ -+err_free_file: -+ kfree(pfile); -+ -+err_put_mod: -+ module_put(THIS_MODULE); -+ return ret; -+} -+ -+static void -+panthor_postclose(struct drm_device *ddev, struct drm_file *file) -+{ -+ struct panthor_file *pfile = file->driver_priv; -+ -+ panthor_group_pool_destroy(pfile); -+ panthor_vm_pool_destroy(pfile); -+ -+ kfree(pfile); -+ module_put(THIS_MODULE); -+} -+ -+static const struct drm_ioctl_desc panthor_drm_driver_ioctls[] = { -+#define PANTHOR_IOCTL(n, func, flags) \ -+ DRM_IOCTL_DEF_DRV(PANTHOR_##n, panthor_ioctl_##func, flags) -+ -+ PANTHOR_IOCTL(DEV_QUERY, dev_query, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(VM_CREATE, vm_create, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(VM_DESTROY, vm_destroy, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(VM_BIND, vm_bind, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(VM_GET_STATE, vm_get_state, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(BO_CREATE, bo_create, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(BO_MMAP_OFFSET, bo_mmap_offset, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(GROUP_CREATE, group_create, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(GROUP_DESTROY, group_destroy, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(GROUP_GET_STATE, group_get_state, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(TILER_HEAP_CREATE, tiler_heap_create, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(TILER_HEAP_DESTROY, tiler_heap_destroy, DRM_RENDER_ALLOW), -+ PANTHOR_IOCTL(GROUP_SUBMIT, group_submit, DRM_RENDER_ALLOW), -+}; -+ -+static int panthor_mmap(struct file *filp, struct vm_area_struct *vma) -+{ -+ struct drm_file *file = filp->private_data; -+ struct panthor_file *pfile = file->driver_priv; -+ struct panthor_device *ptdev = pfile->ptdev; -+ u64 offset = (u64)vma->vm_pgoff << PAGE_SHIFT; -+ int ret, cookie; -+ -+ if (!drm_dev_enter(file->minor->dev, &cookie)) -+ return -ENODEV; -+ -+ if (panthor_device_mmio_offset(offset) >= DRM_PANTHOR_USER_MMIO_OFFSET) -+ ret = panthor_device_mmap_io(ptdev, vma); -+ else -+ ret = drm_gem_mmap(filp, vma); -+ -+ drm_dev_exit(cookie); -+ return ret; -+} -+ -+static const struct file_operations panthor_drm_driver_fops = { -+ .open = drm_open, -+ .release = drm_release, -+ .unlocked_ioctl = drm_ioctl, -+ .compat_ioctl = drm_compat_ioctl, -+ .poll = drm_poll, -+ .read = drm_read, -+ .llseek = noop_llseek, -+ .mmap = panthor_mmap, -+}; -+ -+#ifdef CONFIG_DEBUG_FS -+static void panthor_debugfs_init(struct drm_minor *minor) -+{ -+ panthor_mmu_debugfs_init(minor); -+} -+#endif -+ -+/* -+ * PanCSF driver version: -+ * - 1.0 - initial interface -+ */ -+static const struct drm_driver panthor_drm_driver = { -+ .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ | -+ DRIVER_SYNCOBJ_TIMELINE | DRIVER_GEM_GPUVA, -+ .open = panthor_open, -+ .postclose = panthor_postclose, -+ .ioctls = panthor_drm_driver_ioctls, -+ .num_ioctls = ARRAY_SIZE(panthor_drm_driver_ioctls), -+ .fops = &panthor_drm_driver_fops, -+ .name = "panthor", -+ .desc = "Panthor DRM driver", -+ .date = "20230801", -+ .major = 1, -+ .minor = 0, -+ -+ .gem_create_object = panthor_gem_create_object, -+ .gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table, -+#ifdef CONFIG_DEBUG_FS -+ .debugfs_init = panthor_debugfs_init, -+#endif -+}; -+ -+static int panthor_probe(struct platform_device *pdev) -+{ -+ struct panthor_device *ptdev; -+ -+ ptdev = devm_drm_dev_alloc(&pdev->dev, &panthor_drm_driver, -+ struct panthor_device, base); -+ if (!ptdev) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, ptdev); -+ -+ return panthor_device_init(ptdev); -+} -+ -+static void panthor_remove(struct platform_device *pdev) -+{ -+ struct panthor_device *ptdev = platform_get_drvdata(pdev); -+ -+ panthor_device_unplug(ptdev); -+} -+ -+static const struct of_device_id dt_match[] = { -+ { .compatible = "rockchip,rk3588-mali" }, -+ { .compatible = "arm,mali-valhall-csf" }, -+ {} -+}; -+MODULE_DEVICE_TABLE(of, dt_match); -+ -+static DEFINE_RUNTIME_DEV_PM_OPS(panthor_pm_ops, -+ panthor_device_suspend, -+ panthor_device_resume, -+ NULL); -+ -+static struct platform_driver panthor_driver = { -+ .probe = panthor_probe, -+ .remove_new = panthor_remove, -+ .driver = { -+ .name = "panthor", -+ .pm = &panthor_pm_ops, -+ .of_match_table = dt_match, -+ }, -+}; -+ -+/* -+ * Workqueue used to cleanup stuff. -+ * -+ * We create a dedicated workqueue so we can drain on unplug and -+ * make sure all resources are freed before the module is unloaded. -+ */ -+struct workqueue_struct *panthor_cleanup_wq; -+ -+static int __init panthor_init(void) -+{ -+ int ret; -+ -+ ret = panthor_mmu_pt_cache_init(); -+ if (ret) -+ return ret; -+ -+ panthor_cleanup_wq = alloc_workqueue("panthor-cleanup", WQ_UNBOUND, 0); -+ if (!panthor_cleanup_wq) { -+ pr_err("panthor: Failed to allocate the workqueues"); -+ ret = -ENOMEM; -+ goto err_mmu_pt_cache_fini; -+ } -+ -+ ret = platform_driver_register(&panthor_driver); -+ if (ret) -+ goto err_destroy_cleanup_wq; -+ -+ return 0; -+ -+err_destroy_cleanup_wq: -+ destroy_workqueue(panthor_cleanup_wq); -+ -+err_mmu_pt_cache_fini: -+ panthor_mmu_pt_cache_fini(); -+ return ret; -+} -+module_init(panthor_init); -+ -+static void __exit panthor_exit(void) -+{ -+ platform_driver_unregister(&panthor_driver); -+ destroy_workqueue(panthor_cleanup_wq); -+ panthor_mmu_pt_cache_fini(); -+} -+module_exit(panthor_exit); -+ -+MODULE_AUTHOR("Panthor Project Developers"); -+MODULE_DESCRIPTION("Panthor DRM Driver"); -+MODULE_LICENSE("Dual MIT/GPL"); --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Thu, 29 Feb 2024 17:22:26 +0100 -Subject: drm/panthor: Allow driver compilation - -Now that all blocks are available, we can add/update Kconfig/Makefile -files to allow compilation. - -v6: -- Add Maxime's and Heiko's acks -- Keep source files alphabetically ordered in the Makefile - -v4: -- Add Steve's R-b - -v3: -- Add a dep on DRM_GPUVM -- Fix dependencies in Kconfig -- Expand help text to (hopefully) describe which GPUs are to be - supported by this driver and which are for panfrost. - -Co-developed-by: Steven Price -Signed-off-by: Steven Price -Signed-off-by: Boris Brezillon -Acked-by: Steven Price # MIT+GPL2 relicensing,Arm -Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro -Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora -Reviewed-by: Steven Price -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - drivers/gpu/drm/Kconfig | 2 + - drivers/gpu/drm/Makefile | 1 + - drivers/gpu/drm/panthor/Kconfig | 23 ++++++++++ - drivers/gpu/drm/panthor/Makefile | 14 ++++++ - 4 files changed, 40 insertions(+) - -diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig -index c7edba18a6f0..b94a2fe4f462 100644 ---- a/drivers/gpu/drm/Kconfig -+++ b/drivers/gpu/drm/Kconfig -@@ -384,6 +384,8 @@ source "drivers/gpu/drm/lima/Kconfig" - - source "drivers/gpu/drm/panfrost/Kconfig" - -+source "drivers/gpu/drm/panthor/Kconfig" -+ - source "drivers/gpu/drm/aspeed/Kconfig" - - source "drivers/gpu/drm/mcde/Kconfig" -diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile -index 104b42df2e95..6eb2b553a163 100644 ---- a/drivers/gpu/drm/Makefile -+++ b/drivers/gpu/drm/Makefile -@@ -179,6 +179,7 @@ obj-$(CONFIG_DRM_XEN) += xen/ - obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/ - obj-$(CONFIG_DRM_LIMA) += lima/ - obj-$(CONFIG_DRM_PANFROST) += panfrost/ -+obj-$(CONFIG_DRM_PANTHOR) += panthor/ - obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/ - obj-$(CONFIG_DRM_MCDE) += mcde/ - obj-$(CONFIG_DRM_TIDSS) += tidss/ -diff --git a/drivers/gpu/drm/panthor/Kconfig b/drivers/gpu/drm/panthor/Kconfig -new file mode 100644 -index 000000000000..55b40ad07f3b ---- /dev/null -+++ b/drivers/gpu/drm/panthor/Kconfig -@@ -0,0 +1,23 @@ -+# SPDX-License-Identifier: GPL-2.0 or MIT -+ -+config DRM_PANTHOR -+ tristate "Panthor (DRM support for ARM Mali CSF-based GPUs)" -+ depends on DRM -+ depends on ARM || ARM64 || COMPILE_TEST -+ depends on !GENERIC_ATOMIC64 # for IOMMU_IO_PGTABLE_LPAE -+ depends on MMU -+ select DEVFREQ_GOV_SIMPLE_ONDEMAND -+ select DRM_EXEC -+ select DRM_GEM_SHMEM_HELPER -+ select DRM_GPUVM -+ select DRM_SCHED -+ select IOMMU_IO_PGTABLE_LPAE -+ select IOMMU_SUPPORT -+ select PM_DEVFREQ -+ help -+ DRM driver for ARM Mali CSF-based GPUs. -+ -+ This driver is for Mali (or Immortalis) Valhall Gxxx GPUs. -+ -+ Note that the Mali-G68 and Mali-G78, while Valhall architecture, will -+ be supported with the panfrost driver as they are not CSF GPUs. -diff --git a/drivers/gpu/drm/panthor/Makefile b/drivers/gpu/drm/panthor/Makefile -new file mode 100644 -index 000000000000..15294719b09c ---- /dev/null -+++ b/drivers/gpu/drm/panthor/Makefile -@@ -0,0 +1,14 @@ -+# SPDX-License-Identifier: GPL-2.0 or MIT -+ -+panthor-y := \ -+ panthor_devfreq.o \ -+ panthor_device.o \ -+ panthor_drv.o \ -+ panthor_fw.o \ -+ panthor_gem.o \ -+ panthor_gpu.o \ -+ panthor_heap.o \ -+ panthor_mmu.o \ -+ panthor_sched.o -+ -+obj-$(CONFIG_DRM_PANTHOR) += panthor.o --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Liviu Dudau -Date: Thu, 29 Feb 2024 17:22:27 +0100 -Subject: dt-bindings: gpu: mali-valhall-csf: Add support for Arm Mali CSF GPUs - -Arm has introduced a new v10 GPU architecture that replaces the Job Manager -interface with a new Command Stream Frontend. It adds firmware driven -command stream queues that can be used by kernel and user space to submit -jobs to the GPU. - -Add the initial schema for the device tree that is based on support for -RK3588 SoC. The minimum number of clocks is one for the IP, but on Rockchip -platforms they will tend to expose the semi-independent clocks for better -power management. - -v6: -- Add Maxime's and Heiko's acks - -v5: -- Move the opp-table node under the gpu node - -v4: -- Fix formatting issue - -v3: -- Cleanup commit message to remove redundant text -- Added opp-table property and re-ordered entries -- Clarified power-domains and power-domain-names requirements for RK3588. -- Cleaned up example - -Note: power-domains and power-domain-names requirements for other platforms -are still work in progress, hence the bindings are left incomplete here. - -v2: -- New commit - -Signed-off-by: Liviu Dudau -Cc: Krzysztof Kozlowski -Cc: Rob Herring -Cc: Conor Dooley -Cc: devicetree@vger.kernel.org -Signed-off-by: Boris Brezillon -Reviewed-by: Rob Herring -Acked-by: Maxime Ripard -Acked-by: Heiko Stuebner ---- - Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml | 147 ++++++++++ - 1 file changed, 147 insertions(+) - -diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml -new file mode 100644 -index 000000000000..a5b4e0021758 ---- /dev/null -+++ b/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml -@@ -0,0 +1,147 @@ -+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/gpu/arm,mali-valhall-csf.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: ARM Mali Valhall GPU -+ -+maintainers: -+ - Liviu Dudau -+ - Boris Brezillon -+ -+properties: -+ $nodename: -+ pattern: '^gpu@[a-f0-9]+$' -+ -+ compatible: -+ oneOf: -+ - items: -+ - enum: -+ - rockchip,rk3588-mali -+ - const: arm,mali-valhall-csf # Mali Valhall GPU model/revision is fully discoverable -+ -+ reg: -+ maxItems: 1 -+ -+ interrupts: -+ items: -+ - description: Job interrupt -+ - description: MMU interrupt -+ - description: GPU interrupt -+ -+ interrupt-names: -+ items: -+ - const: job -+ - const: mmu -+ - const: gpu -+ -+ clocks: -+ minItems: 1 -+ maxItems: 3 -+ -+ clock-names: -+ minItems: 1 -+ items: -+ - const: core -+ - const: coregroup -+ - const: stacks -+ -+ mali-supply: true -+ -+ operating-points-v2: true -+ opp-table: -+ type: object -+ -+ power-domains: -+ minItems: 1 -+ maxItems: 5 -+ -+ power-domain-names: -+ minItems: 1 -+ maxItems: 5 -+ -+ sram-supply: true -+ -+ "#cooling-cells": -+ const: 2 -+ -+ dynamic-power-coefficient: -+ $ref: /schemas/types.yaml#/definitions/uint32 -+ description: -+ A u32 value that represents the running time dynamic -+ power coefficient in units of uW/MHz/V^2. The -+ coefficient can either be calculated from power -+ measurements or derived by analysis. -+ -+ The dynamic power consumption of the GPU is -+ proportional to the square of the Voltage (V) and -+ the clock frequency (f). The coefficient is used to -+ calculate the dynamic power as below - -+ -+ Pdyn = dynamic-power-coefficient * V^2 * f -+ -+ where voltage is in V, frequency is in MHz. -+ -+ dma-coherent: true -+ -+required: -+ - compatible -+ - reg -+ - interrupts -+ - interrupt-names -+ - clocks -+ - mali-supply -+ -+additionalProperties: false -+ -+allOf: -+ - if: -+ properties: -+ compatible: -+ contains: -+ const: rockchip,rk3588-mali -+ then: -+ properties: -+ clocks: -+ minItems: 3 -+ power-domains: -+ maxItems: 1 -+ power-domain-names: false -+ -+examples: -+ - | -+ #include -+ #include -+ #include -+ #include -+ -+ gpu: gpu@fb000000 { -+ compatible = "rockchip,rk3588-mali", "arm,mali-valhall-csf"; -+ reg = <0xfb000000 0x200000>; -+ interrupts = , -+ , -+ ; -+ interrupt-names = "job", "mmu", "gpu"; -+ clock-names = "core", "coregroup", "stacks"; -+ clocks = <&cru CLK_GPU>, <&cru CLK_GPU_COREGROUP>, -+ <&cru CLK_GPU_STACKS>; -+ power-domains = <&power RK3588_PD_GPU>; -+ operating-points-v2 = <&gpu_opp_table>; -+ mali-supply = <&vdd_gpu_s0>; -+ sram-supply = <&vdd_gpu_mem_s0>; -+ -+ gpu_opp_table: opp-table { -+ compatible = "operating-points-v2"; -+ opp-300000000 { -+ opp-hz = /bits/ 64 <300000000>; -+ opp-microvolt = <675000 675000 850000>; -+ }; -+ opp-400000000 { -+ opp-hz = /bits/ 64 <400000000>; -+ opp-microvolt = <675000 675000 850000>; -+ }; -+ }; -+ }; -+ -+... --- -Armbian - diff --git a/patch/kernel/rockchip-rk3588-edge/0142-arm64-dts-rockchip-rk3588-Add-GPU-nodes.patch b/patch/kernel/rockchip-rk3588-edge/0142-arm64-dts-rockchip-rk3588-Add-GPU-nodes.patch deleted file mode 100644 index 30f00d31fd6a..000000000000 --- a/patch/kernel/rockchip-rk3588-edge/0142-arm64-dts-rockchip-rk3588-Add-GPU-nodes.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Mon, 7 Aug 2023 17:30:58 +0200 -Subject: arm64: dts: rockchip: rk3588: Add GPU nodes - -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 120 ++++++++++ - 1 file changed, 120 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 58f7740b0e3c..0451a512a3dc 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -733,6 +733,121 @@ usb_host2_xhci: usb@fcd00000 { - status = "disabled"; - }; - -+ gpu_opp_table: gpu-opp-table { -+ compatible = "operating-points-v2"; -+ -+ nvmem-cells = <&gpu_leakage>; -+ nvmem-cell-names = "leakage"; -+ -+ rockchip,pvtm-voltage-sel = < -+ 0 815 0 -+ 816 835 1 -+ 836 860 2 -+ 861 885 3 -+ 886 910 4 -+ 911 9999 5 -+ >; -+ rockchip,pvtm-pvtpll; -+ rockchip,pvtm-offset = <0x1c>; -+ rockchip,pvtm-sample-time = <1100>; -+ rockchip,pvtm-freq = <800000>; -+ rockchip,pvtm-volt = <750000>; -+ rockchip,pvtm-ref-temp = <25>; -+ rockchip,pvtm-temp-prop = <(-135) (-135)>; -+ rockchip,pvtm-thermal-zone = "gpu-thermal"; -+ -+ clocks = <&cru CLK_GPU>; -+ clock-names = "clk"; -+ rockchip,grf = <&gpu_grf>; -+ volt-mem-read-margin = < -+ 855000 1 -+ 765000 2 -+ 675000 3 -+ 495000 4 -+ >; -+ low-volt-mem-read-margin = <4>; -+ intermediate-threshold-freq = <400000>; /* KHz */ -+ -+ rockchip,temp-hysteresis = <5000>; -+ rockchip,low-temp = <10000>; -+ rockchip,low-temp-min-volt = <750000>; -+ rockchip,high-temp = <85000>; -+ rockchip,high-temp-max-freq = <800000>; -+ -+ opp-300000000 { -+ opp-hz = /bits/ 64 <300000000>; -+ opp-microvolt = <675000 675000 850000>; -+ }; -+ opp-400000000 { -+ opp-hz = /bits/ 64 <400000000>; -+ opp-microvolt = <675000 675000 850000>; -+ }; -+ opp-500000000 { -+ opp-hz = /bits/ 64 <500000000>; -+ opp-microvolt = <675000 675000 850000>; -+ }; -+ opp-600000000 { -+ opp-hz = /bits/ 64 <600000000>; -+ opp-microvolt = <675000 675000 850000>; -+ }; -+ opp-700000000 { -+ opp-hz = /bits/ 64 <700000000>; -+ opp-microvolt = <700000 700000 850000>; -+ opp-microvolt-L2 = <687500 687500 850000>; -+ opp-microvolt-L3 = <675000 675000 850000>; -+ opp-microvolt-L4 = <675000 675000 850000>; -+ opp-microvolt-L5 = <675000 675000 850000>; -+ }; -+ opp-800000000 { -+ opp-hz = /bits/ 64 <800000000>; -+ opp-microvolt = <750000 750000 850000>; -+ opp-microvolt-L1 = <737500 737500 850000>; -+ opp-microvolt-L2 = <725000 725000 850000>; -+ opp-microvolt-L3 = <712500 712500 850000>; -+ opp-microvolt-L4 = <700000 700000 850000>; -+ opp-microvolt-L5 = <700000 700000 850000>; -+ }; -+ opp-900000000 { -+ opp-hz = /bits/ 64 <900000000>; -+ opp-microvolt = <800000 800000 850000>; -+ opp-microvolt-L1 = <787500 787500 850000>; -+ opp-microvolt-L2 = <775000 775000 850000>; -+ opp-microvolt-L3 = <762500 762500 850000>; -+ opp-microvolt-L4 = <750000 750000 850000>; -+ opp-microvolt-L5 = <737500 737500 850000>; -+ }; -+ opp-1000000000 { -+ opp-hz = /bits/ 64 <1000000000>; -+ opp-microvolt = <850000 850000 850000>; -+ opp-microvolt-L1 = <837500 837500 850000>; -+ opp-microvolt-L2 = <825000 825000 850000>; -+ opp-microvolt-L3 = <812500 812500 850000>; -+ opp-microvolt-L4 = <800000 800000 850000>; -+ opp-microvolt-L5 = <787500 787500 850000>; -+ }; -+ }; -+ -+ gpu: gpu@fb000000 { -+ compatible = "rockchip,rk3588-mali", "arm,mali-valhall-csf"; -+ reg = <0x0 0xfb000000 0x0 0x200000>; -+ interrupts = , -+ , -+ ; -+ interrupt-names = "job", "mmu", "gpu"; -+ -+ clock-names = "core", "coregroup", "stacks"; -+ clocks = <&cru CLK_GPU>, <&cru CLK_GPU_COREGROUP>, -+ <&cru CLK_GPU_STACKS>; -+ assigned-clocks = <&scmi_clk SCMI_CLK_GPU>; -+ assigned-clock-rates = <200000000>; -+ power-domains = <&power RK3588_PD_GPU>; -+ operating-points-v2 = <&gpu_opp_table>; -+ #cooling-cells = <2>; -+ dynamic-power-coefficient = <2982>; -+ -+ status = "disabled"; -+ }; -+ - pmu1grf: syscon@fd58a000 { - compatible = "rockchip,rk3588-pmugrf", "syscon", "simple-mfd"; - reg = <0x0 0xfd58a000 0x0 0x10000>; -@@ -3033,6 +3148,11 @@ gpio4: gpio@fec50000 { - }; - }; - -+ gpu_grf: syscon@fd5a0000 { -+ compatible = "rockchip,rk3588-gpu-grf", "syscon"; -+ reg = <0x0 0xfd5a0000 0x0 0x100>; -+ }; -+ - av1d: video-codec@fdc70000 { - compatible = "rockchip,rk3588-av1-vpu"; - reg = <0x0 0xfdc70000 0x0 0x800>; --- -Armbian - diff --git a/patch/kernel/rockchip-rk3588-edge/1013-arm64-dts-rockchip-rk3588-rock5b-Add-GPU-node.patch b/patch/kernel/rockchip-rk3588-edge/1013-arm64-dts-rockchip-rk3588-rock5b-Add-GPU-node.patch deleted file mode 100644 index 9b07bcaaeaf8..000000000000 --- a/patch/kernel/rockchip-rk3588-edge/1013-arm64-dts-rockchip-rk3588-rock5b-Add-GPU-node.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Tue, 8 Aug 2023 12:05:22 +0200 -Subject: arm64: dts: rockchip: rk3588-rock5b: Add GPU node - -Signed-off-by: Boris Brezillon -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index b697c707f3f3..7aefcb5498c0 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -@@ -174,6 +174,11 @@ &cpu_l3 { - cpu-supply = <&vdd_cpu_lit_s0>; - }; - -+&gpu { -+ mali-supply = <&vdd_gpu_s0>; -+ status = "okay"; -+}; -+ - &hdmi0 { - status = "okay"; - }; -@@ -509,6 +514,7 @@ rk806_dvs3_null: dvs3-null-pins { - - regulators { - vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { -+ regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <950000>; --- -Armbian - diff --git a/patch/kernel/rockchip-rk3588-edge/1040-board-khadas-edge2-add-nodes.patch b/patch/kernel/rockchip-rk3588-edge/1040-board-khadas-edge2-add-nodes.patch deleted file mode 100644 index 2bbc12ab5f05..000000000000 --- a/patch/kernel/rockchip-rk3588-edge/1040-board-khadas-edge2-add-nodes.patch +++ /dev/null @@ -1,1464 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sat, 10 Feb 2024 16:42:04 +0300 -Subject: arm64: dts: rockchip: Add cpu regulators and vcc5v0_sys to Khadas - Edge 2 - -This commit adds 5V fixed power regulator and CPU regulators to Khadas -Edge 2. - -Signed-off-by: Muhammed Efe Cetin ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 81 ++++++++++ - 1 file changed, 81 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index f53e993c785e..1d1ce70a0f3a 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -17,6 +17,87 @@ aliases { - chosen { - stdout-path = "serial2:1500000n8"; - }; -+ -+ vcc5v0_sys: vcc5v0-sys-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_sys"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+}; -+ -+&cpu_b0 { -+ cpu-supply = <&vdd_cpu_big0_s0>; -+}; -+ -+&cpu_b1 { -+ cpu-supply = <&vdd_cpu_big0_s0>; -+}; -+ -+&cpu_b2 { -+ cpu-supply = <&vdd_cpu_big1_s0>; -+}; -+ -+&cpu_b3 { -+ cpu-supply = <&vdd_cpu_big1_s0>; -+}; -+ -+&cpu_l0 { -+ cpu-supply = <&vdd_cpu_lit_s0>; -+}; -+ -+&cpu_l1 { -+ cpu-supply = <&vdd_cpu_lit_s0>; -+}; -+ -+&cpu_l2 { -+ cpu-supply = <&vdd_cpu_lit_s0>; -+}; -+ -+&cpu_l3 { -+ cpu-supply = <&vdd_cpu_lit_s0>; -+}; -+ -+&i2c0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c0m2_xfer>; -+ status = "okay"; -+ -+ vdd_cpu_big0_s0: regulator@42 { -+ compatible = "rockchip,rk8602"; -+ reg = <0x42>; -+ fcs,suspend-voltage-selector = <1>; -+ regulator-name = "vdd_cpu_big0_s0"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <550000>; -+ regulator-max-microvolt = <1050000>; -+ regulator-ramp-delay = <2300>; -+ vin-supply = <&vcc5v0_sys>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdd_cpu_big1_s0: regulator@43 { -+ compatible = "rockchip,rk8603", "rockchip,rk8602"; -+ reg = <0x43>; -+ fcs,suspend-voltage-selector = <1>; -+ regulator-name = "vdd_cpu_big1_s0"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <550000>; -+ regulator-max-microvolt = <1050000>; -+ regulator-ramp-delay = <2300>; -+ vin-supply = <&vcc5v0_sys>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; - }; - - &sdhci { --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sat, 10 Feb 2024 17:04:20 +0300 -Subject: arm64: dts: rockchip: Add PMIC to Khadas Edge 2 - -This commit adds PMIC to Khadas Edge 2 board. - -Signed-off-by: Muhammed Efe Cetin ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 335 ++++++++++ - 1 file changed, 335 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index 1d1ce70a0f3a..b99d2b82c787 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -26,6 +26,16 @@ vcc5v0_sys: vcc5v0-sys-regulator { - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - }; -+ -+ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc_1v1_nldo_s3"; -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1100000>; -+ regulator-max-microvolt = <1100000>; -+ vin-supply = <&vcc5v0_sys>; -+ }; - }; - - &cpu_b0 { -@@ -110,6 +120,331 @@ &sdhci { - status = "okay"; - }; - -+&spi2 { -+ status = "okay"; -+ assigned-clocks = <&cru CLK_SPI2>; -+ assigned-clock-rates = <200000000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; -+ num-cs = <1>; -+ -+ pmic@0 { -+ compatible = "rockchip,rk806"; -+ spi-max-frequency = <1000000>; -+ reg = <0x0>; -+ -+ interrupt-parent = <&gpio0>; -+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>; -+ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, -+ <&rk806_dvs2_null>, <&rk806_dvs3_null>; -+ -+ system-power-controller; -+ -+ vcc1-supply = <&vcc5v0_sys>; -+ vcc2-supply = <&vcc5v0_sys>; -+ vcc3-supply = <&vcc5v0_sys>; -+ vcc4-supply = <&vcc5v0_sys>; -+ vcc5-supply = <&vcc5v0_sys>; -+ vcc6-supply = <&vcc5v0_sys>; -+ vcc7-supply = <&vcc5v0_sys>; -+ vcc8-supply = <&vcc5v0_sys>; -+ vcc9-supply = <&vcc5v0_sys>; -+ vcc10-supply = <&vcc5v0_sys>; -+ vcc11-supply = <&vcc_2v0_pldo_s3>; -+ vcc12-supply = <&vcc5v0_sys>; -+ vcc13-supply = <&vcc_1v1_nldo_s3>; -+ vcc14-supply = <&vcc_1v1_nldo_s3>; -+ vcca-supply = <&vcc5v0_sys>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ rk806_dvs1_null: dvs1-null-pins { -+ pins = "gpio_pwrctrl1"; -+ function = "pin_fun0"; -+ }; -+ -+ rk806_dvs2_null: dvs2-null-pins { -+ pins = "gpio_pwrctrl2"; -+ function = "pin_fun0"; -+ }; -+ -+ rk806_dvs3_null: dvs3-null-pins { -+ pins = "gpio_pwrctrl3"; -+ function = "pin_fun0"; -+ }; -+ -+ regulators { -+ vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { -+ regulator-boot-on; -+ regulator-min-microvolt = <550000>; -+ regulator-max-microvolt = <950000>; -+ regulator-ramp-delay = <12500>; -+ regulator-name = "vdd_gpu_s0"; -+ regulator-enable-ramp-delay = <400>; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <550000>; -+ regulator-max-microvolt = <950000>; -+ regulator-ramp-delay = <12500>; -+ regulator-name = "vdd_cpu_lit_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdd_log_s0: dcdc-reg3 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <675000>; -+ regulator-max-microvolt = <750000>; -+ regulator-ramp-delay = <12500>; -+ regulator-name = "vdd_log_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ regulator-suspend-microvolt = <750000>; -+ }; -+ }; -+ -+ vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <550000>; -+ regulator-max-microvolt = <950000>; -+ regulator-ramp-delay = <12500>; -+ regulator-name = "vdd_vdenc_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdd_ddr_s0: dcdc-reg5 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <675000>; -+ regulator-max-microvolt = <900000>; -+ regulator-ramp-delay = <12500>; -+ regulator-name = "vdd_ddr_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ regulator-suspend-microvolt = <850000>; -+ }; -+ }; -+ -+ vdd2_ddr_s3: dcdc-reg6 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-name = "vdd2_ddr_s3"; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ }; -+ }; -+ -+ vcc_2v0_pldo_s3: dcdc-reg7 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <2000000>; -+ regulator-max-microvolt = <2000000>; -+ regulator-ramp-delay = <12500>; -+ regulator-name = "vdd_2v0_pldo_s3"; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <2000000>; -+ }; -+ }; -+ -+ vcc_3v3_s3: dcdc-reg8 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc_3v3_s3"; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <3300000>; -+ }; -+ }; -+ -+ vddq_ddr_s0: dcdc-reg9 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-name = "vddq_ddr_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc_1v8_s3: dcdc-reg10 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-name = "vcc_1v8_s3"; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ avcc_1v8_s0: pldo-reg1 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-name = "avcc_1v8_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc_1v8_s0: pldo-reg2 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-name = "vcc_1v8_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ avdd_1v2_s0: pldo-reg3 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1200000>; -+ regulator-name = "avdd_1v2_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vcc_3v3_s0: pldo-reg4 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-ramp-delay = <12500>; -+ regulator-name = "vcc_3v3_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vccio_sd_s0: pldo-reg5 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-ramp-delay = <12500>; -+ regulator-name = "vccio_sd_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ pldo6_s3: pldo-reg6 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-name = "pldo6_s3"; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <1800000>; -+ }; -+ }; -+ -+ vdd_0v75_s3: nldo-reg1 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <750000>; -+ regulator-max-microvolt = <750000>; -+ regulator-name = "vdd_0v75_s3"; -+ -+ regulator-state-mem { -+ regulator-on-in-suspend; -+ regulator-suspend-microvolt = <750000>; -+ }; -+ }; -+ -+ vdd_ddr_pll_s0: nldo-reg2 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <850000>; -+ regulator-max-microvolt = <850000>; -+ regulator-name = "vdd_ddr_pll_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ regulator-suspend-microvolt = <850000>; -+ }; -+ }; -+ -+ avdd_0v75_s0: nldo-reg3 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <750000>; -+ regulator-max-microvolt = <750000>; -+ regulator-name = "avdd_0v75_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdd_0v85_s0: nldo-reg4 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <850000>; -+ regulator-max-microvolt = <850000>; -+ regulator-name = "vdd_0v85_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ -+ vdd_0v75_s0: nldo-reg5 { -+ regulator-always-on; -+ regulator-boot-on; -+ regulator-min-microvolt = <750000>; -+ regulator-max-microvolt = <750000>; -+ regulator-name = "vdd_0v75_s0"; -+ -+ regulator-state-mem { -+ regulator-off-in-suspend; -+ }; -+ }; -+ }; -+ }; -+}; -+ - &uart2 { - pinctrl-0 = <&uart2m0_xfer>; - status = "okay"; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sat, 10 Feb 2024 17:17:29 +0300 -Subject: arm64: dts: rockchip: Add TF card to Khadas Edge 2 - -Add TF card support to Khadas Edge 2. -The board exposes sdmmc pins via EXTIO. TF card can be used with IO -module. - -Signed-off-by: Muhammed Efe Cetin ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 34 ++++++++++ - 1 file changed, 34 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index b99d2b82c787..856ce4f869a2 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -12,6 +12,7 @@ / { - - aliases { - mmc0 = &sdhci; -+ mmc1 = &sdmmc; - }; - - chosen { -@@ -36,6 +37,19 @@ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { - regulator-max-microvolt = <1100000>; - vin-supply = <&vcc5v0_sys>; - }; -+ -+ vdd_3v3_sd: vdd-3v3-sd-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vdd_3v3_sd"; -+ gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>; -+ regulator-boot-on; -+ enable-active-high; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ vin-supply = <&vcc_3v3_s3>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&vdd_sd_en>; -+ }; - }; - - &cpu_b0 { -@@ -110,6 +124,14 @@ regulator-state-mem { - }; - }; - -+&pinctrl { -+ vdd_sd { -+ vdd_sd_en: vdd-sd-en { -+ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ }; -+}; -+ - &sdhci { - bus-width = <8>; - no-sdio; -@@ -120,6 +142,18 @@ &sdhci { - status = "okay"; - }; - -+&sdmmc { -+ bus-width = <4>; -+ cap-sd-highspeed; -+ disable-wp; -+ no-mmc; -+ no-sdio; -+ sd-uhs-sdr104; -+ vmmc-supply = <&vdd_3v3_sd>; -+ vqmmc-supply = <&vccio_sd_s0>; -+ status = "okay"; -+}; -+ - &spi2 { - status = "okay"; - assigned-clocks = <&cru CLK_SPI2>; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sat, 10 Feb 2024 17:34:15 +0300 -Subject: arm64: dts: rockchip: USB2, USB3 Host, PCIe2 to Khadas Edge 2 - -Khadas Edge 2 has 1x USB2 with hub, 1x USB3 Host and 1x USB-C. -This commit adds support for PCIe2, USB3 Host and USB2. - -Signed-off-by: Muhammed Efe Cetin ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 97 ++++++++++ - 1 file changed, 97 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index 856ce4f869a2..ea7f1bb7c908 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -38,6 +38,33 @@ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { - vin-supply = <&vcc5v0_sys>; - }; - -+ vcc5v0_host: vcc5v0-host-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc5v0_host"; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ enable-active-high; -+ gpio = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&vcc5v0_host_en>; -+ vin-supply = <&vcc5v0_sys>; -+ }; -+ -+ vcc3v3_pcie_wl: vcc3v3-pcie-wl-regulator { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie2_2_vcc3v3_en>; -+ regulator-name = "vcc3v3_pcie_wl"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ startup-delay-us = <5000>; -+ vin-supply = <&vcc5v0_sys>; -+ }; -+ - vdd_3v3_sd: vdd-3v3-sd-regulator { - compatible = "regulator-fixed"; - regulator-name = "vdd_3v3_sd"; -@@ -84,6 +111,14 @@ &cpu_l3 { - cpu-supply = <&vdd_cpu_lit_s0>; - }; - -+&combphy0_ps { -+ status = "okay"; -+}; -+ -+&combphy2_psu { -+ status = "okay"; -+}; -+ - &i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0m2_xfer>; -@@ -130,6 +165,30 @@ vdd_sd_en: vdd-sd-en { - rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; -+ -+ pcie2 { -+ pcie2_2_rst: pcie2-2-rst { -+ rockchip,pins = <3 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ pcie2_2_vcc3v3_en: pcie2-2-vcc-en { -+ rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ -+ usb { -+ vcc5v0_host_en: vcc5v0-host-en { -+ rockchip,pins = <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+}; -+ -+&pcie2x1l2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pcie2_2_rst>; -+ reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; -+ vpcie3v3-supply = <&vcc3v3_pcie_wl>; -+ status = "okay"; - }; - - &sdhci { -@@ -483,3 +542,41 @@ &uart2 { - pinctrl-0 = <&uart2m0_xfer>; - status = "okay"; - }; -+ -+&u2phy2 { -+ status = "okay"; -+}; -+ -+&u2phy2_host { -+ phy-supply = <&vcc5v0_host>; -+ status = "okay"; -+}; -+ -+&u2phy3 { -+ status = "okay"; -+}; -+ -+&u2phy3_host { -+ phy-supply = <&vcc5v0_host>; -+ status = "okay"; -+}; -+ -+&usb_host0_ehci { -+ status = "okay"; -+}; -+ -+&usb_host0_ohci { -+ status = "okay"; -+}; -+ -+&usb_host1_ehci { -+ status = "okay"; -+}; -+ -+&usb_host1_ohci { -+ status = "okay"; -+}; -+ -+&usb_host2_xhci { -+ status = "okay"; -+}; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sat, 10 Feb 2024 18:13:56 +0300 -Subject: arm64: dts: rockchip: Add ir receiver and leds to Khadas Edge 2 - -Khadas Edge 2 exposes IR receiver pins as same as TF card via EXTIO. The -IR receiver is connected to MCU and SoC. - -The board also has 2 PWM RGB leds. One is controlled by MCU and the -other is controlled by SoC. This commit adds support for the led -controlled by SoC using pwm-leds. - -Signed-off-by: Muhammed Efe Cetin ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 66 ++++++++++ - 1 file changed, 66 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index ea7f1bb7c908..5a3b52e62dce 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -4,6 +4,7 @@ - - #include - #include -+#include - #include "rk3588s.dtsi" - - / { -@@ -19,6 +20,47 @@ chosen { - stdout-path = "serial2:1500000n8"; - }; - -+ ir-receiver { -+ compatible = "gpio-ir-receiver"; -+ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&ir_receiver_pin>; -+ }; -+ -+ leds { -+ compatible = "pwm-leds"; -+ -+ red_led: led-0 { -+ label = "red_led"; -+ linux,default-trigger = "none"; -+ default-state = "off"; -+ function = LED_FUNCTION_INDICATOR; -+ color = ; -+ max-brightness = <255>; -+ pwms = <&pwm11 0 25000 0>; -+ }; -+ -+ green_led: led-1 { -+ label = "green_led"; -+ linux,default-trigger = "default-on"; -+ default-state = "on"; -+ function = LED_FUNCTION_POWER; -+ color = ; -+ max-brightness = <255>; -+ pwms = <&pwm14 0 25000 0>; -+ }; -+ -+ blue_led: led-2 { -+ label = "blue_led"; -+ linux,default-trigger = "none"; -+ default-state = "off"; -+ function = LED_FUNCTION_INDICATOR; -+ color = ; -+ max-brightness = <255>; -+ pwms = <&pwm15 0 25000 0>; -+ }; -+ }; -+ - vcc5v0_sys: vcc5v0-sys-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_sys"; -@@ -181,6 +223,12 @@ vcc5v0_host_en: vcc5v0-host-en { - rockchip,pins = <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; -+ -+ ir-receiver { -+ ir_receiver_pin: ir-receiver-pin { -+ rockchip,pins = <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; - }; - - &pcie2x1l2 { -@@ -191,6 +239,24 @@ &pcie2x1l2 { - status = "okay"; - }; - -+&pwm11 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pwm11m1_pins>; -+ status = "okay"; -+}; -+ -+&pwm14 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pwm14m1_pins>; -+ status = "okay"; -+}; -+ -+&pwm15 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pwm15m1_pins>; -+ status = "okay"; -+}; -+ - &sdhci { - bus-width = <8>; - no-sdio; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sat, 10 Feb 2024 18:15:44 +0300 -Subject: arm64: dts: rockchip: Add saradc and adc buttons to Khadas Edge 2 and - enable tsadc - -This commit enables tsadc, saradc and the -function button on saradc line for Khadas Edge 2. - -Signed-off-by: Muhammed Efe Cetin ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 24 ++++++++++ - 1 file changed, 24 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index 5a3b52e62dce..dfcdbec3534d 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -3,6 +3,7 @@ - /dts-v1/; - - #include -+#include - #include - #include - #include "rk3588s.dtsi" -@@ -20,6 +21,20 @@ chosen { - stdout-path = "serial2:1500000n8"; - }; - -+ adc-keys { -+ compatible = "adc-keys"; -+ io-channels = <&saradc 1>; -+ io-channel-names = "buttons"; -+ keyup-threshold-microvolt = <1800000>; -+ poll-interval = <100>; -+ -+ button-function { -+ label = "Function"; -+ linux,code = ; -+ press-threshold-microvolt = <17000>; -+ }; -+ }; -+ - ir-receiver { - compatible = "gpio-ir-receiver"; - gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; -@@ -257,6 +272,11 @@ &pwm15 { - status = "okay"; - }; - -+&saradc { -+ vref-supply = <&avcc_1v8_s0>; -+ status = "okay"; -+}; -+ - &sdhci { - bus-width = <8>; - no-sdio; -@@ -604,6 +624,10 @@ regulator-state-mem { - }; - }; - -+&tsadc { -+ status = "okay"; -+}; -+ - &uart2 { - pinctrl-0 = <&uart2m0_xfer>; - status = "okay"; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sat, 10 Feb 2024 18:17:54 +0300 -Subject: arm64: dts: rockchip: Add SFC to Khadas Edge 2 - -This commit adds SPI flash support for Khadas Edge 2. - -Signed-off-by: Muhammed Efe Cetin ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 14 ++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index dfcdbec3534d..c2a329f151a1 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -299,6 +299,20 @@ &sdmmc { - status = "okay"; - }; - -+&sfc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&fspim2_pins>; -+ status = "okay"; -+ -+ flash@0 { -+ compatible = "jedec,spi-nor"; -+ reg = <0x0>; -+ spi-max-frequency = <100000000>; -+ spi-rx-bus-width = <4>; -+ spi-tx-bus-width = <1>; -+ }; -+}; -+ - &spi2 { - status = "okay"; - assigned-clocks = <&cru CLK_SPI2>; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sat, 10 Feb 2024 18:23:14 +0300 -Subject: arm64: dts: rockchip: Add UART9 (bluetooth) to Khadas Edge 2 - -Khadas Edge 2 has onboard AP6275P Wi-Fi6 (PCIe2) and BT5 (UART9) module. -This commit enables UART9. - -Signed-off-by: Muhammed Efe Cetin ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 20 ++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index c2a329f151a1..767e21b2dc34 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -244,6 +244,20 @@ ir_receiver_pin: ir-receiver-pin { - rockchip,pins = <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; -+ -+ wireless-bluetooth { -+ bt_reset_pin: bt-reset-pin { -+ rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ -+ bt_wake_pin: bt-wake-pin { -+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ -+ bt_wake_host_irq: bt-wake-host-irq { -+ rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_down>; -+ }; -+ }; - }; - - &pcie2x1l2 { -@@ -647,6 +661,12 @@ &uart2 { - status = "okay"; - }; - -+&uart9 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart9m2_xfer &uart9m2_ctsn>; -+ status = "okay"; -+}; -+ - &u2phy2 { - status = "okay"; - }; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sun, 11 Feb 2024 16:16:11 +0300 -Subject: arm64: dts: rockchip: Add RTC to Khadas Edge 2 - -Khadas Edge 2 has PT7C4363 RTC that compatible with HYM8563. -The RTC pinctrl is also connected to MCU. - -Signed-off-by: Muhammed Efe Cetin ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 12 ++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index 767e21b2dc34..2022a174594c 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -216,6 +216,18 @@ regulator-state-mem { - }; - }; - -+&i2c2 { -+ status = "okay"; -+ -+ hym8563: rtc@51 { -+ compatible = "haoyu,hym8563"; -+ reg = <0x51>; -+ #clock-cells = <0>; -+ clock-output-names = "hym8563"; -+ wakeup-source; -+ }; -+}; -+ - &pinctrl { - vdd_sd { - vdd_sd_en: vdd-sd-en { --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Mon, 12 Feb 2024 17:35:13 +0300 -Subject: arm64: dts: rockchip: Add USB-C to Khadas Edge 2 - -Khadas Edge 2 has 2x Type-C port. One just supports PD and -controlled by MCU. The other one supports PD, DP Alt mode and DRD. This -commit adds support for DRD. - -Signed-off-by: Muhammed Efe Cetin ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 120 ++++++++++ - 1 file changed, 120 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index 2022a174594c..62167dca75b7 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - #include "rk3588s.dtsi" - - / { -@@ -109,6 +110,18 @@ vcc5v0_host: vcc5v0-host-regulator { - vin-supply = <&vcc5v0_sys>; - }; - -+ vbus5v0_typec: vbus5v0-typec-regulator { -+ compatible = "regulator-fixed"; -+ regulator-name = "vbus5v0_typec"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ enable-active-high; -+ gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; -+ vin-supply = <&vcc5v0_sys>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&typec5v_pwren>; -+ }; -+ - vcc3v3_pcie_wl: vcc3v3-pcie-wl-regulator { - compatible = "regulator-fixed"; - enable-active-high; -@@ -219,6 +232,56 @@ regulator-state-mem { - &i2c2 { - status = "okay"; - -+ usbc0: usb-typec@22 { -+ compatible = "fcs,fusb302"; -+ reg = <0x22>; -+ interrupt-parent = <&gpio1>; -+ interrupts = ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usbc0_int>; -+ vbus-supply = <&vbus5v0_typec>; -+ status = "okay"; -+ -+ usb_con: connector { -+ compatible = "usb-c-connector"; -+ label = "USB-C"; -+ data-role = "dual"; -+ power-role = "dual"; -+ try-power-role = "source"; -+ op-sink-microwatt = <1000000>; -+ sink-pdos = ; -+ source-pdos = ; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ usbc0_orien_sw: endpoint { -+ remote-endpoint = <&usbdp_phy0_orientation_switch>; -+ }; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ usbc0_role_sw: endpoint { -+ remote-endpoint = <&dwc3_0_role_switch>; -+ }; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ dp_altmode_mux: endpoint { -+ remote-endpoint = <&usbdp_phy0_dp_altmode_mux>; -+ }; -+ }; -+ }; -+ }; -+ }; -+ - hym8563: rtc@51 { - compatible = "haoyu,hym8563"; - reg = <0x51>; -@@ -251,6 +314,16 @@ vcc5v0_host_en: vcc5v0-host-en { - }; - }; - -+ usb-typec { -+ usbc0_int: usbc0-int { -+ rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; -+ }; -+ -+ typec5v_pwren: typec5v-pwren { -+ rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; -+ - ir-receiver { - ir_receiver_pin: ir-receiver-pin { - rockchip,pins = <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; -@@ -679,6 +752,15 @@ &uart9 { - status = "okay"; - }; - -+&u2phy0 { -+ status = "okay"; -+}; -+ -+&u2phy0_otg { -+ status = "okay"; -+}; -+ -+ - &u2phy2 { - status = "okay"; - }; -@@ -705,6 +787,44 @@ &usb_host0_ohci { - status = "okay"; - }; - -+&usbdp_phy0 { -+ orientation-switch; -+ mode-switch; -+ svid = <0xff01>; -+ sbu1-dc-gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_HIGH>; -+ sbu2-dc-gpios = <&gpio4 RK_PA1 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+ -+ port { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ usbdp_phy0_orientation_switch: endpoint@0 { -+ reg = <0>; -+ remote-endpoint = <&usbc0_orien_sw>; -+ }; -+ -+ usbdp_phy0_dp_altmode_mux: endpoint@1 { -+ reg = <1>; -+ remote-endpoint = <&dp_altmode_mux>; -+ }; -+ }; -+}; -+ -+&usb_host0_xhci { -+ usb-role-switch; -+ status = "okay"; -+ -+ port { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ dwc3_0_role_switch: endpoint@0 { -+ reg = <0>; -+ remote-endpoint = <&usbc0_role_sw>; -+ }; -+ }; -+}; -+ - &usb_host1_ehci { - status = "okay"; - }; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Mon, 12 Feb 2024 17:35:13 +0300 -Subject: arm64: dts: rockchip: Add bluetooth rfkill to Khadas Edge 2 - ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index 62167dca75b7..b95a36b717f1 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -77,6 +77,15 @@ blue_led: led-2 { - }; - }; - -+ bluetooth-rfkill { -+ compatible = "rfkill-gpio"; -+ label = "rfkill-bluetooth"; -+ radio-type = "bluetooth"; -+ shutdown-gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_LOW>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&bt_reset_pin>; -+ }; -+ - vcc5v0_sys: vcc5v0-sys-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_sys"; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Mon, 19 Feb 2024 23:32:11 +0300 -Subject: arm64: dts: rockchip: Add HDMI & VOP2 to Khadas Edge 2 - ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 36 ++++++++++ - 1 file changed, 36 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index b95a36b717f1..c533b3b8c8dc 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include "rk3588s.dtsi" - - / { -@@ -821,6 +822,7 @@ usbdp_phy0_dp_altmode_mux: endpoint@1 { - }; - - &usb_host0_xhci { -+ dr-mode = "otg"; - usb-role-switch; - status = "okay"; - -@@ -845,3 +847,37 @@ &usb_host1_ohci { - &usb_host2_xhci { - status = "okay"; - }; -+ -+&hdmi0 { -+ status = "okay"; -+}; -+ -+&hdptxphy_hdmi0 { -+ status = "okay"; -+}; -+ -+&display_subsystem { -+ clocks = <&hdptxphy_hdmi0>; -+ clock-names = "hdmi0_phy_pll"; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; -+ -+&hdmi0_in { -+ hdmi0_in_vp0: endpoint { -+ remote-endpoint = <&vp0_out_hdmi0>; -+ }; -+}; -+ -+&vop { -+ status = "okay"; -+}; -+ -+&vp0 { -+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { -+ reg = ; -+ remote-endpoint = <&hdmi0_in_vp0>; -+ }; -+}; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sat, 2 Mar 2024 19:13:59 +0300 -Subject: arm64: dts: rockchip: Add AP6275P wireless support to Khadas Edge 2 - ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 17 ++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index c533b3b8c8dc..54df0a4c32a5 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -361,6 +361,23 @@ &pcie2x1l2 { - reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; - vpcie3v3-supply = <&vcc3v3_pcie_wl>; - status = "okay"; -+ -+ pcie@0,0 { -+ reg = <0x400000 0 0 0 0>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ ranges; -+ device_type = "pci"; -+ bus-range = <0x40 0x4f>; -+ -+ wifi: wifi@0,0 { -+ compatible = "pci14e4,449d"; -+ reg = <0x410000 0 0 0 0>; -+ clocks = <&hym8563>; -+ clock-names = "32k"; -+ }; -+ }; -+ - }; - - &pwm11 { --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sat, 2 Mar 2024 19:26:09 +0300 -Subject: arm64: dts: rockchip: Add cpufreq support to Khadas Edge 2 - ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 12 ++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index 54df0a4c32a5..3248356e3d8f 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -161,34 +161,42 @@ vdd_3v3_sd: vdd-3v3-sd-regulator { - - &cpu_b0 { - cpu-supply = <&vdd_cpu_big0_s0>; -+ mem-supply = <&vdd_cpu_big0_mem_s0>; - }; - - &cpu_b1 { - cpu-supply = <&vdd_cpu_big0_s0>; -+ mem-supply = <&vdd_cpu_big0_mem_s0>; - }; - - &cpu_b2 { - cpu-supply = <&vdd_cpu_big1_s0>; -+ mem-supply = <&vdd_cpu_big1_mem_s0>; - }; - - &cpu_b3 { - cpu-supply = <&vdd_cpu_big1_s0>; -+ mem-supply = <&vdd_cpu_big1_mem_s0>; - }; - - &cpu_l0 { - cpu-supply = <&vdd_cpu_lit_s0>; -+ mem-supply = <&vdd_cpu_lit_mem_s0>; - }; - - &cpu_l1 { - cpu-supply = <&vdd_cpu_lit_s0>; -+ mem-supply = <&vdd_cpu_lit_mem_s0>; - }; - - &cpu_l2 { - cpu-supply = <&vdd_cpu_lit_s0>; -+ mem-supply = <&vdd_cpu_lit_mem_s0>; - }; - - &cpu_l3 { - cpu-supply = <&vdd_cpu_lit_s0>; -+ mem-supply = <&vdd_cpu_lit_mem_s0>; - }; - - &combphy0_ps { -@@ -204,7 +212,7 @@ &i2c0 { - pinctrl-0 = <&i2c0m2_xfer>; - status = "okay"; - -- vdd_cpu_big0_s0: regulator@42 { -+ vdd_cpu_big0_s0: vdd_cpu_big0_mem_s0: regulator@42 { - compatible = "rockchip,rk8602"; - reg = <0x42>; - fcs,suspend-voltage-selector = <1>; -@@ -221,7 +229,7 @@ regulator-state-mem { - }; - }; - -- vdd_cpu_big1_s0: regulator@43 { -+ vdd_cpu_big1_s0: vdd_cpu_big1_mem_s0: regulator@43 { - compatible = "rockchip,rk8603", "rockchip,rk8602"; - reg = <0x43>; - fcs,suspend-voltage-selector = <1>; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Sat, 23 Mar 2024 16:09:41 +0300 -Subject: arm64: dts: rockchip: Add GPU to Khadas Edge 2 - ---- - arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index 3248356e3d8f..cf29563736ea 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -505,6 +505,7 @@ rk806_dvs3_null: dvs3-null-pins { - - regulators { - vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { -+ regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <950000>; -@@ -873,6 +874,11 @@ &usb_host2_xhci { - status = "okay"; - }; - -+&gpu { -+ mali-supply = <&vdd_gpu_s0>; -+ status = "okay"; -+}; -+ - &hdmi0 { - status = "okay"; - }; --- -Armbian - From de8d91b45f09c7ef6c1eef2a15643f51df1fb965 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Wed, 5 Jun 2024 23:32:51 +0200 Subject: [PATCH 22/53] rk3588: edge: Fix dtb overlay compilation and installation "general-add-overlay-compilation-support.patch" became obsolete in Linux 6.9 (see AR-2352 [1]). Fix this problem: - Rename *.dts sources in overlay directory to *.dtso - Change "target +=" line to "dts-y +=" in overlay Makefile - Remove "always +=" line in overlay Makefile - Add .scr compilation support in kernel scripts/Makefile.lib - Patch kernel scripts/Makefile.dtbinst to avoid flattening overlay directory For the last two points, see general-add-overlay-compilation-support.patch Credits for this fix go to @paolosabatino [1] https://armbian.atlassian.net/browse/AR-2352 --- .../0001-general-add-overlay-support.patch | 110 ++++++++---------- .../rockchip-rk3588-edge/overlay/Makefile | 4 +- ...m0-m0.dts => rockchip-rk3588-pwm0-m0.dtso} | 0 ...m0-m1.dts => rockchip-rk3588-pwm0-m1.dtso} | 0 ...m0-m2.dts => rockchip-rk3588-pwm0-m2.dtso} | 0 ...m1-m0.dts => rockchip-rk3588-pwm1-m0.dtso} | 0 ...m1-m1.dts => rockchip-rk3588-pwm1-m1.dtso} | 0 ...m1-m2.dts => rockchip-rk3588-pwm1-m2.dtso} | 0 ...0-m0.dts => rockchip-rk3588-pwm10-m0.dtso} | 0 ...1-m0.dts => rockchip-rk3588-pwm11-m0.dtso} | 0 ...1-m1.dts => rockchip-rk3588-pwm11-m1.dtso} | 0 ...2-m0.dts => rockchip-rk3588-pwm12-m0.dtso} | 0 ...3-m0.dts => rockchip-rk3588-pwm13-m0.dtso} | 0 ...3-m2.dts => rockchip-rk3588-pwm13-m2.dtso} | 0 ...4-m0.dts => rockchip-rk3588-pwm14-m0.dtso} | 0 ...4-m1.dts => rockchip-rk3588-pwm14-m1.dtso} | 0 ...4-m2.dts => rockchip-rk3588-pwm14-m2.dtso} | 0 ...5-m0.dts => rockchip-rk3588-pwm15-m0.dtso} | 0 ...5-m1.dts => rockchip-rk3588-pwm15-m1.dtso} | 0 ...5-m2.dts => rockchip-rk3588-pwm15-m2.dtso} | 0 ...5-m3.dts => rockchip-rk3588-pwm15-m3.dtso} | 0 ...m2-m1.dts => rockchip-rk3588-pwm2-m1.dtso} | 0 ...m3-m0.dts => rockchip-rk3588-pwm3-m0.dtso} | 0 ...m3-m1.dts => rockchip-rk3588-pwm3-m1.dtso} | 0 ...m3-m2.dts => rockchip-rk3588-pwm3-m2.dtso} | 0 ...m3-m3.dts => rockchip-rk3588-pwm3-m3.dtso} | 0 ...m5-m2.dts => rockchip-rk3588-pwm5-m2.dtso} | 0 ...m6-m0.dts => rockchip-rk3588-pwm6-m0.dtso} | 0 ...m6-m2.dts => rockchip-rk3588-pwm6-m2.dtso} | 0 ...m7-m0.dts => rockchip-rk3588-pwm7-m0.dtso} | 0 ...m7-m3.dts => rockchip-rk3588-pwm7-m3.dtso} | 0 ...m8-m0.dts => rockchip-rk3588-pwm8-m0.dtso} | 0 ...8-sata1.dts => rockchip-rk3588-sata1.dtso} | 0 ...8-sata2.dts => rockchip-rk3588-sata2.dtso} | 0 34 files changed, 52 insertions(+), 62 deletions(-) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm0-m0.dts => rockchip-rk3588-pwm0-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm0-m1.dts => rockchip-rk3588-pwm0-m1.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm0-m2.dts => rockchip-rk3588-pwm0-m2.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm1-m0.dts => rockchip-rk3588-pwm1-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm1-m1.dts => rockchip-rk3588-pwm1-m1.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm1-m2.dts => rockchip-rk3588-pwm1-m2.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm10-m0.dts => rockchip-rk3588-pwm10-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm11-m0.dts => rockchip-rk3588-pwm11-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm11-m1.dts => rockchip-rk3588-pwm11-m1.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm12-m0.dts => rockchip-rk3588-pwm12-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm13-m0.dts => rockchip-rk3588-pwm13-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm13-m2.dts => rockchip-rk3588-pwm13-m2.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm14-m0.dts => rockchip-rk3588-pwm14-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm14-m1.dts => rockchip-rk3588-pwm14-m1.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm14-m2.dts => rockchip-rk3588-pwm14-m2.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm15-m0.dts => rockchip-rk3588-pwm15-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm15-m1.dts => rockchip-rk3588-pwm15-m1.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm15-m2.dts => rockchip-rk3588-pwm15-m2.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm15-m3.dts => rockchip-rk3588-pwm15-m3.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm2-m1.dts => rockchip-rk3588-pwm2-m1.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm3-m0.dts => rockchip-rk3588-pwm3-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm3-m1.dts => rockchip-rk3588-pwm3-m1.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm3-m2.dts => rockchip-rk3588-pwm3-m2.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm3-m3.dts => rockchip-rk3588-pwm3-m3.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm5-m2.dts => rockchip-rk3588-pwm5-m2.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm6-m0.dts => rockchip-rk3588-pwm6-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm6-m2.dts => rockchip-rk3588-pwm6-m2.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm7-m0.dts => rockchip-rk3588-pwm7-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm7-m3.dts => rockchip-rk3588-pwm7-m3.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-pwm8-m0.dts => rockchip-rk3588-pwm8-m0.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-sata1.dts => rockchip-rk3588-sata1.dtso} (100%) rename patch/kernel/rockchip-rk3588-edge/overlay/{rockchip-rk3588-sata2.dts => rockchip-rk3588-sata2.dtso} (100%) diff --git a/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch b/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch index 2a8561451963..56595a9698bf 100644 --- a/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch +++ b/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch @@ -1,84 +1,76 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: zador-blood-stained -Date: Sat, 11 Feb 2017 20:32:53 +0300 -Subject: add overlay support +From 088e1cd9b9dd113f0a5e9e19a7f31c37532e002a Mon Sep 17 00:00:00 2001 +From: Paolo Sabatino +Date: Sun, 2 Jun 2024 21:53:01 +0200 +Subject: [PATCH] compile .scr and install overlays in right path -- rpardini: real overlays are now bare in "overlay" directory and are handled - directly by the patching scripts. No more null-patching of overlays. -- no readme, no fixups --- - scripts/Makefile.dtbinst | 6 +++- - scripts/Makefile.lib | 17 ++++++++++ - 2 files changed, 22 insertions(+), 1 deletion(-) + scripts/Makefile.dtbinst | 2 +- + scripts/Makefile.lib | 8 +++++++- + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst -index 4405d5b67578..9b8c57722947 100644 +index 67956f6496a5..151687728a60 100644 --- a/scripts/Makefile.dtbinst +++ b/scripts/Makefile.dtbinst -@@ -18,9 +18,10 @@ include $(srctree)/scripts/Kbuild.include - include $(kbuild-file) +@@ -33,7 +33,18 @@ endef - dtbs := $(addprefix $(dst)/, $(dtb-y) $(if $(CONFIG_OF_ALL_DTBS),$(dtb-))) -+dtbos := $(addprefix $(dst)/, $(dtbo-y)) - subdirs := $(addprefix $(obj)/, $(subdir-y) $(subdir-m)) + $(foreach d, $(sort $(dir $(dtbs))), $(eval $(call gen_install_rules,$(d)))) --__dtbs_install: $(dtbs) $(subdirs) -+__dtbs_install: $(dtbs) $(dtbos) $(subdirs) - @: +-dtbs := $(notdir $(dtbs)) ++# Very convoluted way to flatten all the device tree ++# directories, but keep the "/overlay/" directory ++ ++# topmost directory (ie: from rockchip/overlay/rk322x-emmc.dtbo extracts rockchip) ++topmost_dir = $(firstword $(subst /, ,$(dtbs))) ++# collect dtbs entries which starts with "$topmost_dir/overlay/", then remove "$topmost_dir" ++dtbs_overlays = $(subst $(topmost_dir)/,,$(filter $(topmost_dir)/overlay/%, $(dtbs))) ++# collect the non-overlay dtbs ++dtbs_regular = $(filter-out $(topmost_dir)/overlay/%, $(dtbs)) ++# compose the dtbs variable flattening all the non-overlays entries ++# and appending the overlays entries ++dtbs := $(notdir $(dtbs_regular)) $(dtbs_overlays) - quiet_cmd_dtb_install = INSTALL $@ -@@ -32,6 +33,9 @@ $(dst)/%.dtb: $(obj)/%.dtb - $(dst)/%.dtbo: $(obj)/%.dtbo - $(call cmd,dtb_install) + endif # CONFIG_ARCH_WANT_FLAT_DTB_INSTALL -+$(dst)/%.dtbo: $(obj)/%.dtbo -+ $(call cmd,dtb_install) -+ - PHONY += $(subdirs) - $(subdirs): - $(Q)$(MAKE) $(dtbinst)=$@ dst=$(if $(CONFIG_ARCH_WANT_FLAT_DTB_INSTALL),$(dst),$(patsubst $(obj)/%,$(dst)/%,$@)) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index cd5b181060f1..7e71f4935fbd 100644 +index 9f06f6aaf7fc..a8254bab1b96 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -88,6 +88,9 @@ base-dtb-y := $(filter %.dtb, $(call real-search, $(multi-dtb-y), .dtb, -dtbs)) +@@ -400,11 +400,11 @@ $(obj)/%.dtb.S: $(obj)/%.dtb FORCE + $(obj)/%.dtbo.S: $(obj)/%.dtbo FORCE + $(call if_changed,wrap_S_dtb) - always-y += $(dtb-y) - -+# Overlay targets -+extra-y += $(dtbo-y) -+ - # Add subdir path + quiet_cmd_dtc = DTC $@ + cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ +- $(DTC) -o $@ -b 0 \ ++ $(DTC) -@ -o $@ -b 0 \ + $(addprefix -i,$(dir $<) $(DTC_INCLUDE)) $(DTC_FLAGS) \ + -d $(depfile).dtc.tmp $(dtc-tmp) ; \ + cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) - ifneq ($(obj),.) -@@ -343,6 +346,9 @@ DTC ?= $(objtree)/scripts/dtc/dtc - DTC_FLAGS += -Wno-interrupt_provider \ - -Wno-unique_unit_address + quiet_cmd_fdtoverlay = DTOVL $@ +@@ -425,16 +425,22 @@ quiet_cmd_dtb = DTC_CHK $@ + else + quiet_cmd_dtb = $(quiet_cmd_dtc) + cmd_dtb = $(cmd_dtc) + endif -+# Overlay support -+DTC_FLAGS += -@ -Wno-unit_address_format -Wno-simple_bus_reg ++quiet_cmd_scr = MKIMAGE $@ ++cmd_scr = mkimage -C none -A $(ARCH) -T script -d $< $@ + - # Disable noisy checks by default - ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),) - DTC_FLAGS += -Wno-unit_address_vs_reg \ -@@ -421,6 +427,17 @@ $(obj)/%.dtb: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE + $(obj)/%.dtb: $(obj)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE + $(call if_changed_dep,dtb) + $(obj)/%.dtbo: $(src)/%.dtso $(DTC) 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) ++$(obj)/%.scr: $(src)/%.scr-cmd FORCE ++ $(call if_changed,scr) + dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) # Bzip2 + # --------------------------------------------------------------------------- + -- -Armbian - +Created with Armbian build tools https://github.com/armbian/build diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/Makefile b/patch/kernel/rockchip-rk3588-edge/overlay/Makefile index 573aed747464..af7f7a0b6f69 100644 --- a/patch/kernel/rockchip-rk3588-edge/overlay/Makefile +++ b/patch/kernel/rockchip-rk3588-edge/overlay/Makefile @@ -33,8 +33,6 @@ dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ rockchip-rk3588-pwm15-m2.dtbo \ rockchip-rk3588-pwm15-m3.dtbo -targets += $(dtbo-y) +dtb-y += $(dtbo-y) -always := $(dtbo-y) clean-files := *.dtbo - diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m1.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m1.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m2.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m2.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m1.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m1.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m2.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m2.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm10-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm10-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm10-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm10-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m1.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m1.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm12-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm12-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm12-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm12-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m2.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m2.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m1.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m1.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m2.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m2.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m1.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m1.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m2.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m2.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m3.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m3.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m3.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m3.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm2-m1.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm2-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm2-m1.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm2-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m1.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m1.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m2.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m2.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m3.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m3.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m3.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m3.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm5-m2.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm5-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm5-m2.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm5-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m2.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m2.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m3.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m3.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m3.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m3.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm8-m0.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm8-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm8-m0.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm8-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata1.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata1.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata2.dts b/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata2.dts rename to patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata2.dtso From afe733ced5336f60e9339f8daf99074eebf92803 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Wed, 5 Jun 2024 23:36:08 +0200 Subject: [PATCH 23/53] orangepi 5: Fix patch for 6.10 and convert from patch to .dts file This simplifies the process updating to newer kernel versions and makes it easier to see and edit the actual dts file being used. --- ...031-Add-missing-nodes-to-Orange-Pi-5.patch | 318 -------- .../dt/rk3588s-orangepi-5.dts | 767 ++++++++++++++++++ 2 files changed, 767 insertions(+), 318 deletions(-) delete mode 100644 patch/kernel/rockchip-rk3588-edge/1031-Add-missing-nodes-to-Orange-Pi-5.patch create mode 100644 patch/kernel/rockchip-rk3588-edge/dt/rk3588s-orangepi-5.dts diff --git a/patch/kernel/rockchip-rk3588-edge/1031-Add-missing-nodes-to-Orange-Pi-5.patch b/patch/kernel/rockchip-rk3588-edge/1031-Add-missing-nodes-to-Orange-Pi-5.patch deleted file mode 100644 index fd1b71203932..000000000000 --- a/patch/kernel/rockchip-rk3588-edge/1031-Add-missing-nodes-to-Orange-Pi-5.patch +++ /dev/null @@ -1,318 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Muhammed Efe Cetin -Date: Thu, 16 Nov 2023 18:09:07 +0300 -Subject: arm64: dts: Add missing nodes to Orange Pi 5 - ---- - arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts | 203 +++++++++- - 1 file changed, 201 insertions(+), 2 deletions(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts -index 25de4362af38..621049e1492b 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts -@@ -6,6 +6,8 @@ - #include - #include - #include -+#include -+#include - #include "rk3588s.dtsi" - - / { -@@ -47,6 +49,40 @@ led-1 { - }; - }; - -+ analog-sound { -+ compatible = "simple-audio-card"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&hp_detect>; -+ simple-audio-card,name = "Orange Pi 5 Audio"; -+ simple-audio-card,bitclock-master = <&masterdai>; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,frame-master = <&masterdai>; -+ simple-audio-card,hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>; -+ simple-audio-card,mclk-fs = <256>; -+ simple-audio-card,pin-switches = "Headphones", "Speaker"; -+ simple-audio-card,routing = -+ "Headphones", "LOUT1", -+ "Headphones", "ROUT1", -+ "LINPUT1", "Onboard Microphone", -+ "RINPUT1", "Onboard Microphone", -+ "LINPUT2", "Microphone Jack", -+ "RINPUT2", "Microphone Jack"; -+ simple-audio-card,widgets = -+ "Microphone", "Microphone Jack", -+ "Microphone", "Onboard Microphone", -+ "Headphone", "Headphones", -+ "Speaker", "Speaker"; -+ -+ simple-audio-card,cpu { -+ sound-dai = <&i2s1_8ch>; -+ }; -+ -+ masterdai: simple-audio-card,codec { -+ sound-dai = <&es8388>; -+ system-clock-frequency = <12288000>; -+ }; -+ }; -+ - vbus_typec: vbus-typec-regulator { - compatible = "regulator-fixed"; - enable-active-high; -@@ -102,34 +138,42 @@ &combphy2_psu { - - &cpu_b0 { - cpu-supply = <&vdd_cpu_big0_s0>; -+ mem-supply = <&vdd_cpu_big0_s0>; - }; - - &cpu_b1 { - cpu-supply = <&vdd_cpu_big0_s0>; -+ mem-supply = <&vdd_cpu_big0_s0>; - }; - - &cpu_b2 { - cpu-supply = <&vdd_cpu_big1_s0>; -+ mem-supply = <&vdd_cpu_big1_s0>; - }; - - &cpu_b3 { - cpu-supply = <&vdd_cpu_big1_s0>; -+ mem-supply = <&vdd_cpu_big1_s0>; - }; - - &cpu_l0 { - cpu-supply = <&vdd_cpu_lit_s0>; -+ mem-supply = <&vdd_cpu_lit_mem_s0>; - }; - - &cpu_l1 { - cpu-supply = <&vdd_cpu_lit_s0>; -+ mem-supply = <&vdd_cpu_lit_mem_s0>; - }; - - &cpu_l2 { - cpu-supply = <&vdd_cpu_lit_s0>; -+ mem-supply = <&vdd_cpu_lit_mem_s0>; - }; - - &cpu_l3 { - cpu-supply = <&vdd_cpu_lit_s0>; -+ mem-supply = <&vdd_cpu_lit_mem_s0>; - }; - - &gmac1 { -@@ -223,6 +267,80 @@ hym8563: rtc@51 { - interrupts = ; - wakeup-source; - }; -+ -+ es8388: audio-codec@10 { -+ compatible = "everest,es8388"; -+ reg = <0x10>; -+ clocks = <&cru I2S1_8CH_MCLKOUT>; -+ assigned-clocks = <&cru I2S1_8CH_MCLKOUT>; -+ assigned-clock-rates = <12288000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s1m0_mclk>; -+ #sound-dai-cells = <0>; -+ }; -+ -+ usbc0: usb-typec@22 { -+ compatible = "fcs,fusb302"; -+ reg = <0x22>; -+ interrupt-parent = <&gpio0>; -+ interrupts = ; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&usbc0_int>; -+ vbus-supply = <&vbus_typec>; -+ -+ usb_con: connector { -+ compatible = "usb-c-connector"; -+ label = "USB-C"; -+ data-role = "dual"; -+ power-role = "dual"; -+ try-power-role = "source"; -+ op-sink-microwatt = <1000000>; -+ sink-pdos = ; -+ source-pdos = ; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ port@0 { -+ reg = <0>; -+ usbc0_hs: endpoint { -+ remote-endpoint = <&usb_host0_xhci_drd_sw>; -+ }; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ usbc0_ss: endpoint { -+ remote-endpoint = <&usbdp_phy0_typec_ss>; -+ }; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ usbc0_sbu: endpoint { -+ remote-endpoint = <&usbdp_phy0_typec_sbu>; -+ }; -+ }; -+ }; -+ }; -+ }; -+}; -+ -+&i2s1_8ch { -+ rockchip,i2s-tx-route = <3 2 1 0>; -+ rockchip,i2s-rx-route = <1 3 2 0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s1m0_sclk -+ &i2s1m0_lrck -+ &i2s1m0_sdi1 -+ &i2s1m0_sdo3>; -+ status = "okay"; -+}; -+ -+&gpu { -+ mali-supply = <&vdd_gpu_s0>; -+ status = "okay"; - }; - - &mdio1 { -@@ -263,6 +381,12 @@ typec5v_pwren: typec5v-pwren { - rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; -+ -+ sound { -+ hp_detect: hp-detect { -+ rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; -+ }; -+ }; - }; - - &saradc { -@@ -336,7 +460,7 @@ pmic@0 { - #gpio-cells = <2>; - - rk806_dvs1_null: dvs1-null-pins { -- pins = "gpio_pwrctrl2"; -+ pins = "gpio_pwrctrl1"; - function = "pin_fun0"; - }; - -@@ -364,7 +488,7 @@ regulator-state-mem { - }; - }; - -- vdd_cpu_lit_s0: dcdc-reg2 { -+ vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { - regulator-name = "vdd_cpu_lit_s0"; - regulator-always-on; - regulator-boot-on; -@@ -625,6 +749,14 @@ &tsadc { - status = "okay"; - }; - -+&u2phy0 { -+ status = "okay"; -+}; -+ -+&u2phy0_otg { -+ status = "okay"; -+}; -+ - &u2phy2 { - status = "okay"; - }; -@@ -650,10 +782,48 @@ &usb_host0_ehci { - status = "okay"; - }; - -+&usbdp_phy0 { -+ orientation-switch; -+ mode-switch; -+ sbu1-dc-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; -+ sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; -+ status = "okay"; -+ -+ port { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ usbdp_phy0_typec_ss: endpoint@0 { -+ reg = <0>; -+ remote-endpoint = <&usbc0_ss>; -+ }; -+ -+ usbdp_phy0_typec_sbu: endpoint@1 { -+ reg = <1>; -+ remote-endpoint = <&usbc0_sbu>; -+ }; -+ }; -+}; -+ - &usb_host0_ohci { - status = "okay"; - }; - -+&usb_host0_xhci { -+ usb-role-switch; -+ role-switch-default-mode = "host"; -+ status = "okay"; -+ -+ port { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ usb_host0_xhci_drd_sw: endpoint { -+ remote-endpoint = <&usbc0_hs>; -+ }; -+ }; -+}; -+ - &usb_host1_ehci { - status = "okay"; - }; -@@ -665,3 +835,32 @@ &usb_host1_ohci { - &usb_host2_xhci { - status = "okay"; - }; -+ -+&hdptxphy_hdmi0 { -+ status = "okay"; -+}; -+ -+&hdmi0 { -+ status = "okay"; -+}; -+ -+&hdmi0_in { -+ hdmi0_in_vp0: endpoint { -+ remote-endpoint = <&vp0_out_hdmi0>; -+ }; -+}; -+ -+&vop_mmu { -+ status = "okay"; -+}; -+ -+&vop { -+ status = "okay"; -+}; -+ -+&vp0 { -+ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { -+ reg = ; -+ remote-endpoint = <&hdmi0_in_vp0>; -+ }; -+}; --- -Armbian - diff --git a/patch/kernel/rockchip-rk3588-edge/dt/rk3588s-orangepi-5.dts b/patch/kernel/rockchip-rk3588-edge/dt/rk3588s-orangepi-5.dts new file mode 100644 index 000000000000..6c950cd01582 --- /dev/null +++ b/patch/kernel/rockchip-rk3588-edge/dt/rk3588s-orangepi-5.dts @@ -0,0 +1,767 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include +#include +#include +#include +#include +#include +#include "rk3588s.dtsi" + +/ { + model = "Xunlong Orange Pi 5"; + compatible = "xunlong,orangepi-5", "rockchip,rk3588s"; + + aliases { + ethernet0 = &gmac1; + mmc0 = &sdmmc; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 1>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + + button-recovery { + label = "Recovery"; + linux,code = ; + press-threshold-microvolt = <1800>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&leds_gpio>; + + led-1 { + gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_HIGH>; + label = "status_led"; + linux,default-trigger = "heartbeat"; + }; + }; + + vbus_typec: vbus-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&typec5v_pwren>; + regulator-name = "vbus_typec"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator { + compatible = "regulator-fixed"; + enable-active-low; + gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_LOW>; + regulator-name = "vcc_3v3_sd_s0"; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc3v3_pcie20: vcc3v3-pcie20-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + regulator-name = "vcc3v3_pcie20"; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <50000>; + vin-supply = <&vcc5v0_sys>; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&gmac1 { + clock_in_out = "output"; + phy-handle = <&rgmii_phy1>; + phy-mode = "rgmii-rxid"; + pinctrl-0 = <&gmac1_miim + &gmac1_tx_bus2 + &gmac1_rx_bus2 + &gmac1_rgmii_clk + &gmac1_rgmii_bus>; + pinctrl-names = "default"; + tx_delay = <0x42>; + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + + vdd_cpu_big0_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + + vdd_npu_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_npu_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c6 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c6m3_xfer>; + status = "okay"; + + usbc0: usb-typec@22 { + compatible = "fcs,fusb302"; + reg = <0x22>; + interrupt-parent = <&gpio0>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&usbc0_int>; + vbus-supply = <&vbus_typec>; + status = "okay"; + + usb_con: connector { + compatible = "usb-c-connector"; + label = "USB-C"; + data-role = "dual"; + op-sink-microwatt = <1000000>; + power-role = "dual"; + sink-pdos = + ; + source-pdos = + ; + try-power-role = "source"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_hs: endpoint { + remote-endpoint = <&usb_host0_xhci_drd_sw>; + }; + }; + + port@1 { + reg = <1>; + usbc0_ss: endpoint { + remote-endpoint = <&usbdp_phy0_typec_ss>; + }; + }; + + port@2 { + reg = <2>; + usbc0_sbu: endpoint { + remote-endpoint = <&usbdp_phy0_typec_sbu>; + }; + }; + }; + }; + }; + + hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-output-names = "hym8563"; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + interrupt-parent = <&gpio0>; + interrupts = ; + wakeup-source; + }; +}; + +&mdio1 { + rgmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x1>; + reset-assert-us = <20000>; + reset-deassert-us = <100000>; + reset-gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; + }; +}; + +&pcie2x1l2 { + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie20>; + status = "okay"; +}; + +&pinctrl { + gpio-func { + leds_gpio: leds-gpio { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + typec5v_pwren: typec5v-pwren { + rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&saradc { + vref-supply = <&avcc_1v8_s0>; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-sd-highspeed; + disable-wp; + max-frequency = <150000000>; + no-mmc; + no-sdio; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_sd_s0>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&sfc { + pinctrl-names = "default"; + pinctrl-0 = <&fspim0_pins>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-max-frequency = <100000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + num-cs = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + + pmic@0 { + compatible = "rockchip,rk806"; + reg = <0x0>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + spi-max-frequency = <1000000>; + system-power-controller; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc5v0_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc5v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + gpio-controller; + #gpio-cells = <2>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl1"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: dcdc-reg1 { + regulator-name = "vdd_gpu_s0"; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <400>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: dcdc-reg2 { + regulator-name = "vdd_cpu_lit_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-name = "vdd_log_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: dcdc-reg4 { + regulator-name = "vdd_vdenc_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-name = "vdd_ddr_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vcc_1v1_nldo_s3: vdd2_ddr_s3: dcdc-reg6 { + regulator-name = "vdd2_ddr_s3"; + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <1100000>; + regulator-min-microvolt = <1100000>; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-name = "vdd_2v0_pldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-name = "vcc_3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-name = "vddq_ddr_s0"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-name = "vcc_1v8_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-name = "avcc_1v8_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s0: pldo-reg2 { + regulator-name = "vcc_1v8_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avdd_1v2_s0: pldo-reg3 { + regulator-name = "avdd_1v2_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-name = "vcc_3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-name = "vccio_sd_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + pldo6_s3: pldo-reg6 { + regulator-name = "pldo6_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-name = "vdd_0v75_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_ddr_pll_s0: nldo-reg2 { + regulator-name = "vdd_ddr_pll_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + avdd_0v75_s0: nldo-reg3 { + regulator-name = "avdd_0v75_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg4 { + regulator-name = "vdd_0v85_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v75_s0: nldo-reg5 { + regulator-name = "vdd_0v75_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy2_host { + status = "okay"; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy3_host { + status = "okay"; +}; + +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +&usbdp_phy0 { + mode-switch; + orientation-switch; + sbu1-dc-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; + sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + usbdp_phy0_typec_ss: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_ss>; + }; + + usbdp_phy0_typec_sbu: endpoint@1 { + reg = <1>; + remote-endpoint = <&usbc0_sbu>; + }; + }; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "otg"; + usb-role-switch; + status = "okay"; + + port { + usb_host0_xhci_drd_sw: endpoint { + remote-endpoint = <&usbc0_hs>; + }; + }; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host2_xhci { + status = "okay"; +}; From 408a0cbbc89a387405d46836ec3f6ba2bb5b286d Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Wed, 5 Jun 2024 23:38:06 +0200 Subject: [PATCH 24/53] khadas edge 2: Fix patch for 6.10 --- .../1041-board-khadas-edge2-mcu.patch | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch b/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch index 5c5c954aad80..129d3542aafe 100644 --- a/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch +++ b/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch @@ -9,10 +9,12 @@ Subject: mfd: khadas-mcu: add Edge2 registers 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c -index 61396d824f16..a1a63fb70aac 100644 +index ba981a788692..21c4cd46f41c 100644 --- a/drivers/mfd/khadas-mcu.c +++ b/drivers/mfd/khadas-mcu.c -@@ -26,6 +26,10 @@ static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg) +@@ -24,10 +24,14 @@ static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg) + case KHADAS_MCU_PASSWD_START_REG: + case KHADAS_MCU_CHECK_VEN_PASSWD_REG: case KHADAS_MCU_CHECK_USER_PASSWD_REG: case KHADAS_MCU_WOL_INIT_START_REG: case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG: @@ -23,15 +25,11 @@ index 61396d824f16..a1a63fb70aac 100644 return true; default: return false; -@@ -69,14 +73,14 @@ static const struct regmap_config khadas_mcu_regmap_config = { - .reg_bits = 8, - .reg_stride = 1, - .val_bits = 8, -- .max_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG, -+ .max_register = KHADAS_MCU_SYS_RST_REG, - .volatile_reg = khadas_mcu_reg_volatile, + } + } +@@ -74,11 +78,11 @@ static const struct regmap_config khadas_mcu_regmap_config = { .writeable_reg = khadas_mcu_reg_writeable, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, }; static struct mfd_cell khadas_mcu_fan_cells[] = { @@ -40,6 +38,9 @@ index 61396d824f16..a1a63fb70aac 100644 { .name = "khadas-mcu-fan-ctrl", }, }; + static struct mfd_cell khadas_mcu_cells[] = { + { .name = "khadas-mcu-user-mem", }, + diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h index a99ba2ed0e4e..63bc9bf76661 100644 --- a/include/linux/mfd/khadas-mcu.h From 031a85736be74e1f05aa115af3d210285f167b17 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Thu, 6 Jun 2024 00:44:57 +0200 Subject: [PATCH 25/53] rk3588: edge: Update thermal and cpufreq support patches Patches are from the Linux Rockchip Mailing List, submitted by Alexey Charkov. [1] Notable improvements from changelog: - Moved the TSADC enablement to per-board .dts/.dtsi files - Dropped extra "inefficient" OPPs (same voltage - lower frequencies) - Dropped second passive cooling trips altogether to keep things simple - Added a cooling map for passive GPU cooling (in a separate patch) - Added regulator coupling for EVB1 and QuartzPro64 Also enable automatic fan control on Rock 5B. [1] https://lore.kernel.org/linux-rockchip/20240506-rk-dts-additions-v4-0-271023ddfd40@gmail.com/ --- .../0022-RK3588-Add-Cpufreq-Support.patch | 626 --------------- ...3588-Add-Thermal-and-CpuFreq-Support.patch | 758 ++++++++++++++++++ ...5-board-rock5b-automatic-fan-control.patch | 67 ++ 3 files changed, 825 insertions(+), 626 deletions(-) delete mode 100644 patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Cpufreq-Support.patch create mode 100644 patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch create mode 100644 patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Cpufreq-Support.patch b/patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Cpufreq-Support.patch deleted file mode 100644 index be466f3fd410..000000000000 --- a/patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Cpufreq-Support.patch +++ /dev/null @@ -1,626 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alexey Charkov -Date: Thu, 29 Feb 2024 23:26:32 +0400 -Subject: arm64: dts: rockchip: enable built-in thermal monitoring on RK3588 - -Include thermal zones information in device tree for RK3588 variants. - -This also enables the TSADC controller unconditionally on all boards -to ensure that thermal protections are in place via throttling and -emergency reset, once OPPs are added to enable CPU DVFS. - -The default settings (using CRU as the emergency reset mechanism) -should work on all boards regardless of their wiring, as CRU resets -do not depend on any external components. Boards that have the TSHUT -signal wired to the reset line of the PMIC may opt to switch to GPIO -tshut mode instead (rockchip,hw-tshut-mode = <1>;) - -It seems though that downstream kernels don't use that, even for -those boards where the wiring allows for GPIO based tshut, such as -Radxa Rock 5B [1], [2], [3] - -[1] https://github.com/radxa/kernel/blob/stable-5.10-rock5/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts#L540 -[2] https://github.com/radxa/kernel/blob/stable-5.10-rock5/arch/arm64/boot/dts/rockchip/rk3588s.dtsi#L5433 -[3] https://dl.radxa.com/rock5/5b/docs/hw/radxa_rock_5b_v1423_sch.pdf page 11 (TSADC_SHUT_H) - -Signed-off-by: Alexey Charkov -Link: https://lore.kernel.org/r/20240229-rk-dts-additions-v3-1-6afe8473a631@gmail.com -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 176 +++++++++- - 1 file changed, 175 insertions(+), 1 deletion(-) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index ce39d3f9593c..f683ed234b65 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - / { - compatible = "rockchip,rk3588"; -@@ -2286,7 +2287,180 @@ tsadc: tsadc@fec00000 { - pinctrl-1 = <&tsadc_shut>; - pinctrl-names = "gpio", "otpout"; - #thermal-sensor-cells = <1>; -- status = "disabled"; -+ status = "okay"; -+ }; -+ -+ thermal_zones: thermal-zones { -+ /* sensor near the center of the SoC */ -+ package_thermal: package-thermal { -+ polling-delay-passive = <0>; -+ polling-delay = <0>; -+ thermal-sensors = <&tsadc 0>; -+ -+ trips { -+ package_crit: package-crit { -+ temperature = <115000>; -+ hysteresis = <0>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ /* sensor between A76 cores 0 and 1 */ -+ bigcore0_thermal: bigcore0-thermal { -+ polling-delay-passive = <100>; -+ polling-delay = <0>; -+ thermal-sensors = <&tsadc 1>; -+ -+ trips { -+ /* threshold to start collecting temperature -+ * statistics e.g. with the IPA governor -+ */ -+ bigcore0_alert0: bigcore0-alert0 { -+ temperature = <75000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ /* actual control temperature */ -+ bigcore0_alert1: bigcore0-alert1 { -+ temperature = <85000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ bigcore0_crit: bigcore0-crit { -+ temperature = <115000>; -+ hysteresis = <0>; -+ type = "critical"; -+ }; -+ }; -+ cooling-maps { -+ map0 { -+ trip = <&bigcore0_alert1>; -+ cooling-device = -+ <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, -+ <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; -+ }; -+ }; -+ }; -+ -+ /* sensor between A76 cores 2 and 3 */ -+ bigcore2_thermal: bigcore2-thermal { -+ polling-delay-passive = <100>; -+ polling-delay = <0>; -+ thermal-sensors = <&tsadc 2>; -+ -+ trips { -+ /* threshold to start collecting temperature -+ * statistics e.g. with the IPA governor -+ */ -+ bigcore2_alert0: bigcore2-alert0 { -+ temperature = <75000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ /* actual control temperature */ -+ bigcore2_alert1: bigcore2-alert1 { -+ temperature = <85000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ bigcore2_crit: bigcore2-crit { -+ temperature = <115000>; -+ hysteresis = <0>; -+ type = "critical"; -+ }; -+ }; -+ cooling-maps { -+ map0 { -+ trip = <&bigcore2_alert1>; -+ cooling-device = -+ <&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, -+ <&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; -+ }; -+ }; -+ }; -+ -+ /* sensor between the four A55 cores */ -+ little_core_thermal: littlecore-thermal { -+ polling-delay-passive = <100>; -+ polling-delay = <0>; -+ thermal-sensors = <&tsadc 3>; -+ -+ trips { -+ /* threshold to start collecting temperature -+ * statistics e.g. with the IPA governor -+ */ -+ littlecore_alert0: littlecore-alert0 { -+ temperature = <75000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ /* actual control temperature */ -+ littlecore_alert1: littlecore-alert1 { -+ temperature = <85000>; -+ hysteresis = <2000>; -+ type = "passive"; -+ }; -+ littlecore_crit: littlecore-crit { -+ temperature = <115000>; -+ hysteresis = <0>; -+ type = "critical"; -+ }; -+ }; -+ cooling-maps { -+ map0 { -+ trip = <&littlecore_alert1>; -+ cooling-device = -+ <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, -+ <&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, -+ <&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, -+ <&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; -+ }; -+ }; -+ }; -+ -+ /* sensor near the PD_CENTER power domain */ -+ center_thermal: center-thermal { -+ polling-delay-passive = <0>; -+ polling-delay = <0>; -+ thermal-sensors = <&tsadc 4>; -+ -+ trips { -+ center_crit: center-crit { -+ temperature = <115000>; -+ hysteresis = <0>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ gpu_thermal: gpu-thermal { -+ polling-delay-passive = <0>; -+ polling-delay = <0>; -+ thermal-sensors = <&tsadc 5>; -+ -+ trips { -+ gpu_crit: gpu-crit { -+ temperature = <115000>; -+ hysteresis = <0>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ npu_thermal: npu-thermal { -+ polling-delay-passive = <0>; -+ polling-delay = <0>; -+ thermal-sensors = <&tsadc 6>; -+ -+ trips { -+ npu_crit: npu-crit { -+ temperature = <115000>; -+ hysteresis = <0>; -+ type = "critical"; -+ }; -+ }; -+ }; - }; - - saradc: adc@fec10000 { --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alexey Charkov -Date: Thu, 29 Feb 2024 23:26:35 +0400 -Subject: arm64: dts: rockchip: Add OPP data for CPU cores on RK3588 - -By default the CPUs on RK3588 start up in a conservative performance -mode. Add frequency and voltage mappings to the device tree to enable -dynamic scaling via cpufreq. - -OPP values are adapted from Radxa's downstream kernel for Rock 5B [1], -stripping them down to the minimum frequency and voltage combinations -as expected by the generic upstream cpufreq-dt driver, and also dropping -those OPPs that don't differ in voltage but only in frequency (keeping -the top frequency OPP in each case). - -Note that this patch ignores voltage scaling for the CPU memory -interface which the downstream kernel does through a custom cpufreq -driver, and which is why the downstream version has two sets of voltage -values for each OPP (the second one being meant for the memory -interface supply regulator). This is done instead via regulator -coupling between CPU and memory interface supplies on affected boards. - -This has been tested on Rock 5B with u-boot 2023.11 compiled from -Collabora's integration tree [2] with binary bl31 and appears to be -stable both under active cooling and passive cooling (with throttling) - -[1] https://github.com/radxa/kernel/blob/stable-5.10-rock5/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -[2] https://gitlab.collabora.com/hardware-enablement/rockchip-3588/u-boot - -Signed-off-by: Alexey Charkov -Link: https://lore.kernel.org/r/20240229-rk-dts-additions-v3-4-6afe8473a631@gmail.com -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 122 ++++++++++ - 1 file changed, 122 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index f683ed234b65..611541f64d54 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -97,6 +97,7 @@ cpu_l0: cpu@0 { - clocks = <&scmi_clk SCMI_CLK_CPUL>; - assigned-clocks = <&scmi_clk SCMI_CLK_CPUL>; - assigned-clock-rates = <816000000>; -+ operating-points-v2 = <&cluster0_opp_table>; - cpu-idle-states = <&CPU_SLEEP>; - i-cache-size = <32768>; - i-cache-line-size = <64>; -@@ -116,6 +117,7 @@ cpu_l1: cpu@100 { - enable-method = "psci"; - capacity-dmips-mhz = <530>; - clocks = <&scmi_clk SCMI_CLK_CPUL>; -+ operating-points-v2 = <&cluster0_opp_table>; - cpu-idle-states = <&CPU_SLEEP>; - i-cache-size = <32768>; - i-cache-line-size = <64>; -@@ -135,6 +137,7 @@ cpu_l2: cpu@200 { - enable-method = "psci"; - capacity-dmips-mhz = <530>; - clocks = <&scmi_clk SCMI_CLK_CPUL>; -+ operating-points-v2 = <&cluster0_opp_table>; - cpu-idle-states = <&CPU_SLEEP>; - i-cache-size = <32768>; - i-cache-line-size = <64>; -@@ -154,6 +157,7 @@ cpu_l3: cpu@300 { - enable-method = "psci"; - capacity-dmips-mhz = <530>; - clocks = <&scmi_clk SCMI_CLK_CPUL>; -+ operating-points-v2 = <&cluster0_opp_table>; - cpu-idle-states = <&CPU_SLEEP>; - i-cache-size = <32768>; - i-cache-line-size = <64>; -@@ -175,6 +179,7 @@ cpu_b0: cpu@400 { - clocks = <&scmi_clk SCMI_CLK_CPUB01>; - assigned-clocks = <&scmi_clk SCMI_CLK_CPUB01>; - assigned-clock-rates = <816000000>; -+ operating-points-v2 = <&cluster1_opp_table>; - cpu-idle-states = <&CPU_SLEEP>; - i-cache-size = <65536>; - i-cache-line-size = <64>; -@@ -194,6 +199,7 @@ cpu_b1: cpu@500 { - enable-method = "psci"; - capacity-dmips-mhz = <1024>; - clocks = <&scmi_clk SCMI_CLK_CPUB01>; -+ operating-points-v2 = <&cluster1_opp_table>; - cpu-idle-states = <&CPU_SLEEP>; - i-cache-size = <65536>; - i-cache-line-size = <64>; -@@ -215,6 +221,7 @@ cpu_b2: cpu@600 { - clocks = <&scmi_clk SCMI_CLK_CPUB23>; - assigned-clocks = <&scmi_clk SCMI_CLK_CPUB23>; - assigned-clock-rates = <816000000>; -+ operating-points-v2 = <&cluster2_opp_table>; - cpu-idle-states = <&CPU_SLEEP>; - i-cache-size = <65536>; - i-cache-line-size = <64>; -@@ -234,6 +241,7 @@ cpu_b3: cpu@700 { - enable-method = "psci"; - capacity-dmips-mhz = <1024>; - clocks = <&scmi_clk SCMI_CLK_CPUB23>; -+ operating-points-v2 = <&cluster2_opp_table>; - cpu-idle-states = <&CPU_SLEEP>; - i-cache-size = <65536>; - i-cache-line-size = <64>; -@@ -348,6 +356,120 @@ l3_cache: l3-cache { - }; - }; - -+ cluster0_opp_table: opp-table-cluster0 { -+ compatible = "operating-points-v2"; -+ opp-shared; -+ -+ opp-1008000000 { -+ opp-hz = /bits/ 64 <1008000000>; -+ opp-microvolt = <675000 675000 950000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1200000000 { -+ opp-hz = /bits/ 64 <1200000000>; -+ opp-microvolt = <712500 712500 950000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1416000000 { -+ opp-hz = /bits/ 64 <1416000000>; -+ opp-microvolt = <762500 762500 950000>; -+ clock-latency-ns = <40000>; -+ opp-suspend; -+ }; -+ opp-1608000000 { -+ opp-hz = /bits/ 64 <1608000000>; -+ opp-microvolt = <850000 850000 950000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1800000000 { -+ opp-hz = /bits/ 64 <1800000000>; -+ opp-microvolt = <950000 950000 950000>; -+ clock-latency-ns = <40000>; -+ }; -+ }; -+ -+ cluster1_opp_table: opp-table-cluster1 { -+ compatible = "operating-points-v2"; -+ opp-shared; -+ -+ opp-1200000000 { -+ opp-hz = /bits/ 64 <1200000000>; -+ opp-microvolt = <675000 675000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1416000000 { -+ opp-hz = /bits/ 64 <1416000000>; -+ opp-microvolt = <725000 725000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1608000000 { -+ opp-hz = /bits/ 64 <1608000000>; -+ opp-microvolt = <762500 762500 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1800000000 { -+ opp-hz = /bits/ 64 <1800000000>; -+ opp-microvolt = <850000 850000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-2016000000 { -+ opp-hz = /bits/ 64 <2016000000>; -+ opp-microvolt = <925000 925000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-2208000000 { -+ opp-hz = /bits/ 64 <2208000000>; -+ opp-microvolt = <987500 987500 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-2400000000 { -+ opp-hz = /bits/ 64 <2400000000>; -+ opp-microvolt = <1000000 1000000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ }; -+ -+ cluster2_opp_table: opp-table-cluster2 { -+ compatible = "operating-points-v2"; -+ opp-shared; -+ -+ opp-1200000000 { -+ opp-hz = /bits/ 64 <1200000000>; -+ opp-microvolt = <675000 675000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1416000000 { -+ opp-hz = /bits/ 64 <1416000000>; -+ opp-microvolt = <725000 725000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1608000000 { -+ opp-hz = /bits/ 64 <1608000000>; -+ opp-microvolt = <762500 762500 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1800000000 { -+ opp-hz = /bits/ 64 <1800000000>; -+ opp-microvolt = <850000 850000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-2016000000 { -+ opp-hz = /bits/ 64 <2016000000>; -+ opp-microvolt = <925000 925000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-2208000000 { -+ opp-hz = /bits/ 64 <2208000000>; -+ opp-microvolt = <987500 987500 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-2400000000 { -+ opp-hz = /bits/ 64 <2400000000>; -+ opp-microvolt = <1000000 1000000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ }; -+ - firmware { - optee: optee { - compatible = "linaro,optee-tz"; --- -Armbian - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alexey Charkov -Date: Thu, 29 Feb 2024 23:26:36 +0400 -Subject: arm64: dts: rockchip: Add further granularity in RK3588 CPU OPPs - -This introduces additional OPPs that share the same voltage as -another OPP already present in the .dtsi but with lower frequency. - -The idea is to try and limit system throughput more gradually upon -reaching the throttling condition for workloads that are close to -sustainable power already, thus avoiding needless performance loss. - -My limited synthetic benchmarking [1] showed around 3.8% performance -benefit when these are in place, other things equal (not meant to -be comprehensive). Though dmesg complains about these OPPs being -'inefficient': - -[ 9.009561] cpu cpu0: EM: OPP:816000 is inefficient -[ 9.009580] cpu cpu0: EM: OPP:600000 is inefficient -[ 9.009591] cpu cpu0: EM: OPP:408000 is inefficient -[ 9.011370] cpu cpu4: EM: OPP:2352000 is inefficient -[ 9.011379] cpu cpu4: EM: OPP:2304000 is inefficient -[ 9.011384] cpu cpu4: EM: OPP:2256000 is inefficient -[ 9.011389] cpu cpu4: EM: OPP:600000 is inefficient -[ 9.011393] cpu cpu4: EM: OPP:408000 is inefficient -[ 9.012978] cpu cpu6: EM: OPP:2352000 is inefficient -[ 9.012987] cpu cpu6: EM: OPP:2304000 is inefficient -[ 9.012992] cpu cpu6: EM: OPP:2256000 is inefficient -[ 9.012996] cpu cpu6: EM: OPP:600000 is inefficient -[ 9.013000] cpu cpu6: EM: OPP:408000 is inefficient - -[1] https://lore.kernel.org/linux-rockchip/CABjd4YxqarUCbZ-a2XLe3TWJ-qjphGkyq=wDnctnEhdoSdPPpw@mail.gmail.com/T/#me92aa0ee25e6eeb1d1501ce85f5af4e58b3b13c5 - -Signed-off-by: Alexey Charkov -Link: https://lore.kernel.org/r/20240229-rk-dts-additions-v3-5-6afe8473a631@gmail.com -Signed-off-by: Sebastian Reichel ---- - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 87 ++++++++++ - 1 file changed, 87 insertions(+) - -diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 611541f64d54..baea5b31e18a 100644 ---- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -360,6 +360,21 @@ cluster0_opp_table: opp-table-cluster0 { - compatible = "operating-points-v2"; - opp-shared; - -+ opp-408000000 { -+ opp-hz = /bits/ 64 <408000000>; -+ opp-microvolt = <675000 675000 950000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-600000000 { -+ opp-hz = /bits/ 64 <600000000>; -+ opp-microvolt = <675000 675000 950000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-816000000 { -+ opp-hz = /bits/ 64 <816000000>; -+ opp-microvolt = <675000 675000 950000>; -+ clock-latency-ns = <40000>; -+ }; - opp-1008000000 { - opp-hz = /bits/ 64 <1008000000>; - opp-microvolt = <675000 675000 950000>; -@@ -392,6 +407,27 @@ cluster1_opp_table: opp-table-cluster1 { - compatible = "operating-points-v2"; - opp-shared; - -+ opp-408000000 { -+ opp-hz = /bits/ 64 <408000000>; -+ opp-microvolt = <675000 675000 1000000>; -+ clock-latency-ns = <40000>; -+ opp-suspend; -+ }; -+ opp-600000000 { -+ opp-hz = /bits/ 64 <600000000>; -+ opp-microvolt = <675000 675000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-816000000 { -+ opp-hz = /bits/ 64 <816000000>; -+ opp-microvolt = <675000 675000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1008000000 { -+ opp-hz = /bits/ 64 <1008000000>; -+ opp-microvolt = <675000 675000 1000000>; -+ clock-latency-ns = <40000>; -+ }; - opp-1200000000 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <675000 675000 1000000>; -@@ -422,6 +458,21 @@ opp-2208000000 { - opp-microvolt = <987500 987500 1000000>; - clock-latency-ns = <40000>; - }; -+ opp-2256000000 { -+ opp-hz = /bits/ 64 <2256000000>; -+ opp-microvolt = <1000000 1000000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-2304000000 { -+ opp-hz = /bits/ 64 <2304000000>; -+ opp-microvolt = <1000000 1000000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-2352000000 { -+ opp-hz = /bits/ 64 <2352000000>; -+ opp-microvolt = <1000000 1000000 1000000>; -+ clock-latency-ns = <40000>; -+ }; - opp-2400000000 { - opp-hz = /bits/ 64 <2400000000>; - opp-microvolt = <1000000 1000000 1000000>; -@@ -433,6 +484,27 @@ cluster2_opp_table: opp-table-cluster2 { - compatible = "operating-points-v2"; - opp-shared; - -+ opp-408000000 { -+ opp-hz = /bits/ 64 <408000000>; -+ opp-microvolt = <675000 675000 1000000>; -+ clock-latency-ns = <40000>; -+ opp-suspend; -+ }; -+ opp-600000000 { -+ opp-hz = /bits/ 64 <600000000>; -+ opp-microvolt = <675000 675000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-816000000 { -+ opp-hz = /bits/ 64 <816000000>; -+ opp-microvolt = <675000 675000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-1008000000 { -+ opp-hz = /bits/ 64 <1008000000>; -+ opp-microvolt = <675000 675000 1000000>; -+ clock-latency-ns = <40000>; -+ }; - opp-1200000000 { - opp-hz = /bits/ 64 <1200000000>; - opp-microvolt = <675000 675000 1000000>; -@@ -463,6 +535,21 @@ opp-2208000000 { - opp-microvolt = <987500 987500 1000000>; - clock-latency-ns = <40000>; - }; -+ opp-2256000000 { -+ opp-hz = /bits/ 64 <2256000000>; -+ opp-microvolt = <1000000 1000000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-2304000000 { -+ opp-hz = /bits/ 64 <2304000000>; -+ opp-microvolt = <1000000 1000000 1000000>; -+ clock-latency-ns = <40000>; -+ }; -+ opp-2352000000 { -+ opp-hz = /bits/ 64 <2352000000>; -+ opp-microvolt = <1000000 1000000 1000000>; -+ clock-latency-ns = <40000>; -+ }; - opp-2400000000 { - opp-hz = /bits/ 64 <2400000000>; - opp-microvolt = <1000000 1000000 1000000>; --- -Armbian - diff --git a/patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch b/patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch new file mode 100644 index 000000000000..5341704bdba5 --- /dev/null +++ b/patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch @@ -0,0 +1,758 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexey Charkov +Date: Mon, 6 May 2024 13:36:32 +0400 +Subject: arm64: dts: rockchip: add thermal zones information on RK3588 + +This includes the necessary device tree data to allow thermal +monitoring on RK3588(s) using the on-chip TSADC device, along with +trip points for automatic thermal management. + +Each of the CPU clusters (one for the little cores and two for +the big cores) get a passive cooling trip point at 85C, which +will trigger DVFS throttling of the respective cluster upon +reaching a high temperature condition. + +All zones also have a critical trip point at 115C, which will +trigger a reset. + +Signed-off-by: Alexey Charkov +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 147 ++++++++++ + 1 file changed, 147 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 6ac5ac8b48ab..ef06c1f742e8 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + / { + compatible = "rockchip,rk3588"; +@@ -2368,6 +2369,152 @@ pwm15: pwm@febf0030 { + status = "disabled"; + }; + ++ thermal_zones: thermal-zones { ++ /* sensor near the center of the SoC */ ++ package_thermal: package-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 0>; ++ ++ trips { ++ package_crit: package-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ /* sensor between A76 cores 0 and 1 */ ++ bigcore0_thermal: bigcore0-thermal { ++ polling-delay-passive = <100>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 1>; ++ ++ trips { ++ bigcore0_alert: bigcore0-alert { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ bigcore0_crit: bigcore0-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ cooling-maps { ++ map0 { ++ trip = <&bigcore0_alert>; ++ cooling-device = ++ <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ ++ /* sensor between A76 cores 2 and 3 */ ++ bigcore2_thermal: bigcore2-thermal { ++ polling-delay-passive = <100>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 2>; ++ ++ trips { ++ bigcore2_alert: bigcore2-alert { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ bigcore2_crit: bigcore2-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ cooling-maps { ++ map0 { ++ trip = <&bigcore2_alert>; ++ cooling-device = ++ <&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ ++ /* sensor between the four A55 cores */ ++ little_core_thermal: littlecore-thermal { ++ polling-delay-passive = <100>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 3>; ++ ++ trips { ++ littlecore_alert: littlecore-alert { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ littlecore_crit: littlecore-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ cooling-maps { ++ map0 { ++ trip = <&littlecore_alert>; ++ cooling-device = ++ <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ ++ /* sensor near the PD_CENTER power domain */ ++ center_thermal: center-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 4>; ++ ++ trips { ++ center_crit: center-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ gpu_thermal: gpu-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 5>; ++ ++ trips { ++ gpu_crit: gpu-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ npu_thermal: npu-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 6>; ++ ++ trips { ++ npu_crit: npu-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ }; ++ + tsadc: tsadc@fec00000 { + compatible = "rockchip,rk3588-tsadc"; + reg = <0x0 0xfec00000 0x0 0x400>; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexey Charkov +Date: Mon, 6 May 2024 13:36:33 +0400 +Subject: arm64: dts: rockchip: enable thermal management on all RK3588 boards + +This enables the on-chip thermal monitoring sensor (TSADC) on all +RK3588(s) boards that don't have it enabled yet. It provides temperature +monitoring for the SoC and emergency thermal shutdowns, and is thus +important to have in place before CPU DVFS is enabled, as high CPU +operating performance points can overheat the chip quickly in the +absence of thermal management. + +Signed-off-by: Alexey Charkov +--- + arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts | 4 ++++ + arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi | 4 ++++ + arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts | 4 ++++ + arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts | 4 ++++ + arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 4 ++++ + arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts | 4 ++++ + arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi | 4 ++++ + arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 4 ++++ + 8 files changed, 32 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts +index 98c622b27647..c667704ba985 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts +@@ -673,6 +673,10 @@ regulator-state-mem { + }; + }; + ++&tsadc { ++ status = "okay"; ++}; ++ + &u2phy0 { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi +index 709d348cf06b..03fd193be253 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi +@@ -466,3 +466,7 @@ regulator-state-mem { + }; + }; + }; ++ ++&tsadc { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +index 7be2190244ba..7c3696a3ad3a 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +@@ -1131,6 +1131,10 @@ &sata0 { + status = "okay"; + }; + ++&tsadc { ++ status = "okay"; ++}; ++ + &u2phy0 { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts b/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts +index 009566d881f3..230e630820b4 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts +@@ -376,6 +376,10 @@ &sdmmc { + status = "okay"; + }; + ++&tsadc { ++ status = "okay"; ++}; ++ + &u2phy2 { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +index b8e15b76a8a6..21e96c212dd8 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -742,6 +742,10 @@ regulator-state-mem { + }; + }; + ++&tsadc { ++ status = "okay"; ++}; ++ + &uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts +index 9090c5c99f2a..d0021524e7f9 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts +@@ -648,6 +648,10 @@ regulator-state-mem { + }; + }; + ++&tsadc { ++ status = "okay"; ++}; ++ + &u2phy2 { + status = "okay"; + }; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi +index 6b9206ce4a03..77bcf0f6b028 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi +@@ -601,6 +601,10 @@ regulator-state-mem { + }; + }; + ++&tsadc { ++ status = "okay"; ++}; ++ + &uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +index 8e2a07612d17..c671a61d3aef 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +@@ -697,6 +697,10 @@ regulator-state-mem { + }; + }; + ++&tsadc { ++ status = "okay"; ++}; ++ + &u2phy0 { + status = "okay"; + }; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexey Charkov +Date: Mon, 6 May 2024 13:36:34 +0400 +Subject: arm64: dts: rockchip: add passive GPU cooling on RK3588 + +As the GPU support on RK3588 has been merged upstream, along with OPP +values, add a corresponding cooling map for passive cooling using the GPU. + +Signed-off-by: Alexey Charkov +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 14 +++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index ef06c1f742e8..57c2d998ae75 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -2487,17 +2487,29 @@ center_crit: center-crit { + }; + + gpu_thermal: gpu-thermal { +- polling-delay-passive = <0>; ++ polling-delay-passive = <100>; + polling-delay = <0>; + thermal-sensors = <&tsadc 5>; + + trips { ++ gpu_alert: gpu-alert { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; + gpu_crit: gpu-crit { + temperature = <115000>; + hysteresis = <0>; + type = "critical"; + }; + }; ++ cooling-maps { ++ map0 { ++ trip = <&gpu_alert>; ++ cooling-device = ++ <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; + }; + + npu_thermal: npu-thermal { +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexey Charkov +Date: Mon, 6 May 2024 13:36:36 +0400 +Subject: arm64: dts: rockchip: Add CPU/memory regulator coupling for RK3588 + +RK3588 chips allow for their CPU cores to be powered by a different +supply vs. their corresponding memory interfaces, and two of the +boards currently upstream do that (EVB1 and QuartzPro64). + +The voltage of the memory interface though has to match that of the +CPU cores that use it, which downstream kernels achieve by the means +of a custom cpufreq driver which adjusts both at the same time. + +It seems that regulator coupling is a more appropriate generic +interface for it, so this patch introduces coupling to affected +device trees to ensure that memory interface voltage is also updated +whenever cpufreq switches between CPU OPPs. + +Note that other boards, such as Radxa Rock 5B, define both the CPU +and memory interface regulators as aliases to the same DT node, so +this doesn't apply there. + +Signed-off-by: Alexey Charkov +--- + arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts | 12 ++++++++++ + arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts | 12 ++++++++++ + 2 files changed, 24 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +index 7c3696a3ad3a..00f660d50127 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +@@ -878,6 +878,8 @@ regulators { + vdd_cpu_big1_s0: dcdc-reg1 { + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_big1_mem_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; +@@ -890,6 +892,8 @@ regulator-state-mem { + vdd_cpu_big0_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_big0_mem_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; +@@ -902,6 +906,8 @@ regulator-state-mem { + vdd_cpu_lit_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_lit_mem_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; +@@ -926,6 +932,8 @@ regulator-state-mem { + vdd_cpu_big1_mem_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_big1_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; +@@ -939,6 +947,8 @@ regulator-state-mem { + vdd_cpu_big0_mem_s0: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_big0_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; +@@ -963,6 +973,8 @@ regulator-state-mem { + vdd_cpu_lit_mem_s0: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_lit_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts +index b4f22d95ac0e..baeb08d665c7 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts +@@ -832,6 +832,8 @@ vdd_cpu_big1_s0: dcdc-reg1 { + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_big1_mem_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; +@@ -845,6 +847,8 @@ vdd_cpu_big0_s0: dcdc-reg2 { + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_big0_mem_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; +@@ -858,6 +862,8 @@ vdd_cpu_lit_s0: dcdc-reg3 { + regulator-name = "vdd_cpu_lit_s0"; + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_lit_mem_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; +@@ -884,6 +890,8 @@ vdd_cpu_big1_mem_s0: dcdc-reg5 { + regulator-name = "vdd_cpu_big1_mem_s0"; + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_big1_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; +@@ -898,6 +906,8 @@ vdd_cpu_big0_mem_s0: dcdc-reg6 { + regulator-name = "vdd_cpu_big0_mem_s0"; + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_big0_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <12500>; +@@ -924,6 +934,8 @@ vdd_cpu_lit_mem_s0: dcdc-reg8 { + regulator-name = "vdd_cpu_lit_mem_s0"; + regulator-always-on; + regulator-boot-on; ++ regulator-coupled-with = <&vdd_cpu_lit_s0>; ++ regulator-coupled-max-spread = <10000>; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexey Charkov +Date: Mon, 6 May 2024 13:36:37 +0400 +Subject: arm64: dts: rockchip: Add OPP data for CPU cores on RK3588 + +By default the CPUs on RK3588 start up in a conservative performance +mode. Add frequency and voltage mappings to the device tree to enable +dynamic scaling via cpufreq. + +OPP values are adapted from Radxa's downstream kernel for Rock 5B [1], +stripping them down to the minimum frequency and voltage combinations +as expected by the generic upstream cpufreq-dt driver, and also dropping +those OPPs that don't differ in voltage but only in frequency (keeping +the top frequency OPP in each case). + +Note that this patch ignores voltage scaling for the CPU memory +interface which the downstream kernel does through a custom cpufreq +driver, and which is why the downstream version has two sets of voltage +values for each OPP (the second one being meant for the memory +interface supply regulator). This is done instead via regulator +coupling between CPU and memory interface supplies on affected boards. + +This has been tested on Rock 5B with u-boot 2023.11 compiled from +Collabora's integration tree [2] with binary bl31 and appears to be +stable both under active cooling and passive cooling (with throttling) + +[1] https://github.com/radxa/kernel/blob/stable-5.10-rock5/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +[2] https://gitlab.collabora.com/hardware-enablement/rockchip-3588/u-boot + +Signed-off-by: Alexey Charkov +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 122 ++++++++++ + 1 file changed, 122 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 57c2d998ae75..85c25d5efdad 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -97,6 +97,7 @@ cpu_l0: cpu@0 { + clocks = <&scmi_clk SCMI_CLK_CPUL>; + assigned-clocks = <&scmi_clk SCMI_CLK_CPUL>; + assigned-clock-rates = <816000000>; ++ operating-points-v2 = <&cluster0_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <32768>; + i-cache-line-size = <64>; +@@ -116,6 +117,7 @@ cpu_l1: cpu@100 { + enable-method = "psci"; + capacity-dmips-mhz = <530>; + clocks = <&scmi_clk SCMI_CLK_CPUL>; ++ operating-points-v2 = <&cluster0_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <32768>; + i-cache-line-size = <64>; +@@ -135,6 +137,7 @@ cpu_l2: cpu@200 { + enable-method = "psci"; + capacity-dmips-mhz = <530>; + clocks = <&scmi_clk SCMI_CLK_CPUL>; ++ operating-points-v2 = <&cluster0_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <32768>; + i-cache-line-size = <64>; +@@ -154,6 +157,7 @@ cpu_l3: cpu@300 { + enable-method = "psci"; + capacity-dmips-mhz = <530>; + clocks = <&scmi_clk SCMI_CLK_CPUL>; ++ operating-points-v2 = <&cluster0_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <32768>; + i-cache-line-size = <64>; +@@ -175,6 +179,7 @@ cpu_b0: cpu@400 { + clocks = <&scmi_clk SCMI_CLK_CPUB01>; + assigned-clocks = <&scmi_clk SCMI_CLK_CPUB01>; + assigned-clock-rates = <816000000>; ++ operating-points-v2 = <&cluster1_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <65536>; + i-cache-line-size = <64>; +@@ -194,6 +199,7 @@ cpu_b1: cpu@500 { + enable-method = "psci"; + capacity-dmips-mhz = <1024>; + clocks = <&scmi_clk SCMI_CLK_CPUB01>; ++ operating-points-v2 = <&cluster1_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <65536>; + i-cache-line-size = <64>; +@@ -215,6 +221,7 @@ cpu_b2: cpu@600 { + clocks = <&scmi_clk SCMI_CLK_CPUB23>; + assigned-clocks = <&scmi_clk SCMI_CLK_CPUB23>; + assigned-clock-rates = <816000000>; ++ operating-points-v2 = <&cluster2_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <65536>; + i-cache-line-size = <64>; +@@ -234,6 +241,7 @@ cpu_b3: cpu@700 { + enable-method = "psci"; + capacity-dmips-mhz = <1024>; + clocks = <&scmi_clk SCMI_CLK_CPUB23>; ++ operating-points-v2 = <&cluster2_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <65536>; + i-cache-line-size = <64>; +@@ -348,6 +356,120 @@ l3_cache: l3-cache { + }; + }; + ++ cluster0_opp_table: opp-table-cluster0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1008000000 { ++ opp-hz = /bits/ 64 <1008000000>; ++ opp-microvolt = <675000 675000 950000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <712500 712500 950000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1416000000 { ++ opp-hz = /bits/ 64 <1416000000>; ++ opp-microvolt = <762500 762500 950000>; ++ clock-latency-ns = <40000>; ++ opp-suspend; ++ }; ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <850000 850000 950000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <950000 950000 950000>; ++ clock-latency-ns = <40000>; ++ }; ++ }; ++ ++ cluster1_opp_table: opp-table-cluster1 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1416000000 { ++ opp-hz = /bits/ 64 <1416000000>; ++ opp-microvolt = <725000 725000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <762500 762500 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <850000 850000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <925000 925000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <987500 987500 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2400000000 { ++ opp-hz = /bits/ 64 <2400000000>; ++ opp-microvolt = <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ }; ++ ++ cluster2_opp_table: opp-table-cluster2 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1416000000 { ++ opp-hz = /bits/ 64 <1416000000>; ++ opp-microvolt = <725000 725000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <762500 762500 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <850000 850000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <925000 925000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <987500 987500 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2400000000 { ++ opp-hz = /bits/ 64 <2400000000>; ++ opp-microvolt = <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ }; ++ + display_subsystem: display-subsystem { + compatible = "rockchip,display-subsystem"; + ports = <&vop_out>; +-- +Armbian + diff --git a/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch b/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch new file mode 100644 index 000000000000..ae96de16a2ed --- /dev/null +++ b/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexey Charkov +Date: Mon, 6 May 2024 13:36:35 +0400 +Subject: arm64: dts: rockchip: enable automatic fan control on Rock 5B + +This links the PWM fan on Radxa Rock 5B as an active cooling device +managed automatically by the thermal subsystem, with a target SoC +temperature of 65C and a minimum-spin interval from 55C to 65C to +ensure airflow when the system gets warm + +Helped-by: Dragan Simic +Reviewed-by: Dragan Simic +Signed-off-by: Alexey Charkov +--- + arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 30 +++++++++- + 1 file changed, 29 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +index 21e96c212dd8..b70313643af8 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -52,7 +52,7 @@ led_rgb_b { + + fan: pwm-fan { + compatible = "pwm-fan"; +- cooling-levels = <0 95 145 195 255>; ++ cooling-levels = <0 120 150 180 210 240 255>; + fan-supply = <&vcc5v0_sys>; + pwms = <&pwm1 0 50000 0>; + #cooling-cells = <2>; +@@ -279,6 +279,34 @@ i2s0_8ch_p0_0: endpoint { + }; + }; + ++&package_thermal { ++ polling-delay = <1000>; ++ ++ trips { ++ package_fan0: package-fan0 { ++ temperature = <55000>; ++ hysteresis = <2000>; ++ type = "active"; ++ }; ++ package_fan1: package-fan1 { ++ temperature = <65000>; ++ hysteresis = <2000>; ++ type = "active"; ++ }; ++ }; ++ ++ cooling-maps { ++ map1 { ++ trip = <&package_fan0>; ++ cooling-device = <&fan THERMAL_NO_LIMIT 1>; ++ }; ++ map2 { ++ trip = <&package_fan1>; ++ cooling-device = <&fan 2 THERMAL_NO_LIMIT>; ++ }; ++ }; ++}; ++ + &pcie2x1l0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_0_rst>; +-- +Armbian \ No newline at end of file From 8c31cca7ba551c36cdb71e3146f5de2014803636 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:07:29 +0200 Subject: [PATCH 26/53] rk3588: edge: Rewrite kernel patches to 6.10-rc2 --- .../0001-general-add-overlay-support.patch | 25 +++++--------- .../0011-irqchip-fix-its-timeout-issue.patch | 34 +++++++++---------- .../0024-RK3588-Add-Crypto-Support.patch | 27 ++++++++------- .../0025-RK3588-Add-HW-RNG-Support.patch | 4 +-- ...-rockchip-Add-HDMI0-bridge-to-rk3588.patch | 4 +-- ...ip-Enable-HDMI0-PHY-clk-provider-on-.patch | 4 +-- ...2-Improve-display-modes-handling-on-.patch | 22 ++++++------ ...kchip-rk3588-add-VDPU-and-RGA2-nodes.patch | 12 +++---- .../0801-wireless-add-bcm43752.patch | 6 ++-- .../0802-wireless-add-clk-property.patch | 6 ++-- ...b-Slow-down-emmc-to-hs200-and-add-ts.patch | 6 ++-- ...d-rock-5b-arm64-dts-enable-spi-flash.patch | 4 +-- ...dts-rockchip-Enable-HDMI0-on-rock-5b.patch | 8 ++--- ...-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch | 4 +-- ...5-board-rock5b-automatic-fan-control.patch | 9 ++--- .../1020-Add-HDMI-and-VOP2-to-Rock-5A.patch | 4 +-- ...rm64-dts-enable-gpu-node-for-rock-5a.patch | 4 +-- ...dd-missing-nodes-to-Orange-Pi-5-Plus.patch | 10 +++--- ...rockchip-support-poweroff-on-rock-5a.patch | 4 +-- ...ip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch | 2 +- .../1041-board-khadas-edge2-mcu.patch | 27 +++++---------- 21 files changed, 106 insertions(+), 120 deletions(-) diff --git a/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch b/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch index 56595a9698bf..064c6e3b9eab 100644 --- a/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch +++ b/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch @@ -1,12 +1,12 @@ -From 088e1cd9b9dd113f0a5e9e19a7f31c37532e002a Mon Sep 17 00:00:00 2001 +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Paolo Sabatino Date: Sun, 2 Jun 2024 21:53:01 +0200 -Subject: [PATCH] compile .scr and install overlays in right path +Subject: compile .scr and install overlays in right path --- - scripts/Makefile.dtbinst | 2 +- - scripts/Makefile.lib | 8 +++++++- - 2 files changed, 8 insertions(+), 2 deletions(-) + scripts/Makefile.dtbinst | 13 +++++++++- + scripts/Makefile.lib | 8 +++++- + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst index 67956f6496a5..151687728a60 100644 @@ -36,9 +36,7 @@ diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 9f06f6aaf7fc..a8254bab1b96 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -400,11 +400,11 @@ $(obj)/%.dtb.S: $(obj)/%.dtb FORCE - $(obj)/%.dtbo.S: $(obj)/%.dtbo FORCE - $(call if_changed,wrap_S_dtb) +@@ -402,7 +402,7 @@ $(obj)/%.dtbo.S: $(obj)/%.dtbo FORCE quiet_cmd_dtc = DTC $@ cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ @@ -47,11 +45,7 @@ index 9f06f6aaf7fc..a8254bab1b96 100644 $(addprefix -i,$(dir $<) $(DTC_INCLUDE)) $(DTC_FLAGS) \ -d $(depfile).dtc.tmp $(dtc-tmp) ; \ cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) - - quiet_cmd_fdtoverlay = DTOVL $@ -@@ -425,16 +425,22 @@ quiet_cmd_dtb = DTC_CHK $@ - else - quiet_cmd_dtb = $(quiet_cmd_dtc) +@@ -427,12 +427,18 @@ quiet_cmd_dtb = $(quiet_cmd_dtc) cmd_dtb = $(cmd_dtc) endif @@ -70,7 +64,6 @@ index 9f06f6aaf7fc..a8254bab1b96 100644 dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) # Bzip2 - # --------------------------------------------------------------------------- - -- -Created with Armbian build tools https://github.com/armbian/build +Armbian + diff --git a/patch/kernel/rockchip-rk3588-edge/0011-irqchip-fix-its-timeout-issue.patch b/patch/kernel/rockchip-rk3588-edge/0011-irqchip-fix-its-timeout-issue.patch index dcfff8459818..a387abc5e430 100644 --- a/patch/kernel/rockchip-rk3588-edge/0011-irqchip-fix-its-timeout-issue.patch +++ b/patch/kernel/rockchip-rk3588-edge/0011-irqchip-fix-its-timeout-issue.patch @@ -8,7 +8,7 @@ Subject: irqchip/irq-gic-v3-its: fix its timeout issue for rk35xx boards 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c -index 6b386511cd1f..6874b32622fe 100644 +index 40ebf1726393..eb6ca4504a27 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -163,6 +163,7 @@ struct its_device { @@ -19,7 +19,7 @@ index 6b386511cd1f..6874b32622fe 100644 u32 nr_ites; u32 device_id; bool shared; -@@ -2205,6 +2206,9 @@ static void gic_reset_prop_table(void *va) +@@ -2211,6 +2212,9 @@ static void gic_reset_prop_table(void *va) static struct page *its_allocate_prop_table(gfp_t gfp_flags) { struct page *prop_page; @@ -29,7 +29,7 @@ index 6b386511cd1f..6874b32622fe 100644 prop_page = alloc_pages(gfp_flags, get_order(LPI_PROPBASE_SZ)); if (!prop_page) -@@ -2329,6 +2333,7 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, +@@ -2335,6 +2339,7 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, u32 alloc_pages, psz; struct page *page; void *base; @@ -37,7 +37,7 @@ index 6b386511cd1f..6874b32622fe 100644 psz = baser->psz; alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz); -@@ -2340,7 +2345,11 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, +@@ -2346,7 +2351,11 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, order = get_order(GITS_BASER_PAGES_MAX * psz); } @@ -50,7 +50,7 @@ index 6b386511cd1f..6874b32622fe 100644 if (!page) return -ENOMEM; -@@ -2390,6 +2399,15 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, +@@ -2396,6 +2405,15 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, its_write_baser(its, baser, val); tmp = baser->val; @@ -66,7 +66,7 @@ index 6b386511cd1f..6874b32622fe 100644 if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) { /* * Shareability didn't stick. Just use -@@ -2979,7 +2997,9 @@ static int its_alloc_collections(struct its_node *its) +@@ -2985,7 +3003,9 @@ static int its_alloc_collections(struct its_node *its) static struct page *its_allocate_pending_table(gfp_t gfp_flags) { struct page *pend_page; @@ -77,7 +77,7 @@ index 6b386511cd1f..6874b32622fe 100644 pend_page = alloc_pages(gfp_flags | __GFP_ZERO, get_order(LPI_PENDBASE_SZ)); if (!pend_page) -@@ -3138,6 +3158,11 @@ static void its_cpu_init_lpis(void) +@@ -3144,6 +3164,11 @@ static void its_cpu_init_lpis(void) if (!rdists_support_shareable()) tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK; @@ -89,7 +89,7 @@ index 6b386511cd1f..6874b32622fe 100644 if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) { if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) { /* -@@ -3165,6 +3190,11 @@ static void its_cpu_init_lpis(void) +@@ -3171,6 +3196,11 @@ static void its_cpu_init_lpis(void) if (!rdists_support_shareable()) tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK; @@ -101,7 +101,7 @@ index 6b386511cd1f..6874b32622fe 100644 if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) { /* * The HW reports non-shareable, we must remove the -@@ -3328,7 +3358,11 @@ static bool its_alloc_table_entry(struct its_node *its, +@@ -3334,7 +3364,11 @@ static bool its_alloc_table_entry(struct its_node *its, /* Allocate memory for 2nd level table */ if (!table[idx]) { @@ -114,7 +114,7 @@ index 6b386511cd1f..6874b32622fe 100644 get_order(baser->psz)); if (!page) return false; -@@ -3417,6 +3451,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, +@@ -3423,6 +3457,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, int nr_lpis; int nr_ites; int sz; @@ -122,7 +122,7 @@ index 6b386511cd1f..6874b32622fe 100644 if (!its_alloc_device_table(its, dev_id)) return NULL; -@@ -3432,7 +3467,15 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, +@@ -3438,7 +3473,15 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, nr_ites = max(2, nvecs); sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1); sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; @@ -139,7 +139,7 @@ index 6b386511cd1f..6874b32622fe 100644 if (alloc_lpis) { lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis); if (lpi_map) -@@ -3446,7 +3489,13 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, +@@ -3452,7 +3495,13 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) { kfree(dev); @@ -154,7 +154,7 @@ index 6b386511cd1f..6874b32622fe 100644 bitmap_free(lpi_map); kfree(col_map); return NULL; -@@ -3456,6 +3505,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, +@@ -3462,6 +3511,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, dev->its = its; dev->itt = itt; @@ -162,7 +162,7 @@ index 6b386511cd1f..6874b32622fe 100644 dev->nr_ites = nr_ites; dev->event_map.lpi_map = lpi_map; dev->event_map.col_map = col_map; -@@ -3483,7 +3533,13 @@ static void its_free_device(struct its_device *its_dev) +@@ -3489,7 +3539,13 @@ static void its_free_device(struct its_device *its_dev) list_del(&its_dev->entry); raw_spin_unlock_irqrestore(&its_dev->its->lock, flags); kfree(its_dev->event_map.col_map); @@ -177,7 +177,7 @@ index 6b386511cd1f..6874b32622fe 100644 kfree(its_dev); } -@@ -5089,6 +5145,7 @@ static int __init its_probe_one(struct its_node *its) +@@ -5098,6 +5154,7 @@ static int __init its_probe_one(struct its_node *its) struct page *page; u32 ctlr; int err; @@ -185,7 +185,7 @@ index 6b386511cd1f..6874b32622fe 100644 its_enable_quirks(its); -@@ -5122,7 +5179,10 @@ static int __init its_probe_one(struct its_node *its) +@@ -5131,7 +5188,10 @@ static int __init its_probe_one(struct its_node *its) } } @@ -197,7 +197,7 @@ index 6b386511cd1f..6874b32622fe 100644 get_order(ITS_CMD_QUEUE_SZ)); if (!page) { err = -ENOMEM; -@@ -5151,6 +5211,11 @@ static int __init its_probe_one(struct its_node *its) +@@ -5160,6 +5220,11 @@ static int __init its_probe_one(struct its_node *its) if (its->flags & ITS_FLAGS_FORCE_NON_SHAREABLE) tmp &= ~GITS_CBASER_SHAREABILITY_MASK; diff --git a/patch/kernel/rockchip-rk3588-edge/0024-RK3588-Add-Crypto-Support.patch b/patch/kernel/rockchip-rk3588-edge/0024-RK3588-Add-Crypto-Support.patch index 7e929055f7ad..665f6ef9da98 100644 --- a/patch/kernel/rockchip-rk3588-edge/0024-RK3588-Add-Crypto-Support.patch +++ b/patch/kernel/rockchip-rk3588-edge/0024-RK3588-Add-Crypto-Support.patch @@ -99,10 +99,10 @@ Signed-off-by: Corentin Labbe 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index baea5b31e18a..97d8de940a4f 100644 +index 85c25d5efdad..8a2eb9013fe0 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -1911,6 +1911,18 @@ sdhci: mmc@fe2e0000 { +@@ -1923,6 +1923,18 @@ sdhci: mmc@fe2e0000 { status = "disabled"; }; @@ -139,10 +139,10 @@ Signed-off-by: Corentin Labbe 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi -index 92f96ec01385..78329ba02b77 100644 +index d8543b5557ee..5ec449aebc12 100644 --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi -@@ -1071,6 +1071,18 @@ sdhci: mmc@fe310000 { +@@ -1112,6 +1112,18 @@ sdhci: mmc@fe310000 { status = "disabled"; }; @@ -182,7 +182,7 @@ Signed-off-by: Corentin Labbe 2 files changed, 34 insertions(+), 76 deletions(-) diff --git a/drivers/clk/rockchip/rst-rk3588.c b/drivers/clk/rockchip/rst-rk3588.c -index e855bb8d5413..6556d9d3c7ab 100644 +index c4ebc01f1c9c..7a856de64d9e 100644 --- a/drivers/clk/rockchip/rst-rk3588.c +++ b/drivers/clk/rockchip/rst-rk3588.c @@ -16,9 +16,6 @@ @@ -195,7 +195,7 @@ index e855bb8d5413..6556d9d3c7ab 100644 /* 0xFD7F0000 + 0x0A00 */ #define RK3588_PMU1CRU_RESET_OFFSET(id, reg, bit) [id] = (0x30000*4 + reg * 16 + bit) -@@ -806,45 +803,6 @@ static const int rk3588_register_offset[] = { +@@ -807,45 +804,6 @@ static const int rk3588_register_offset[] = { RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU0IOC, 5, 4), RK3588_PMU1CRU_RESET_OFFSET(SRST_P_GPIO0, 5, 5), RK3588_PMU1CRU_RESET_OFFSET(SRST_GPIO0, 5, 6), @@ -242,10 +242,10 @@ index e855bb8d5413..6556d9d3c7ab 100644 void rk3588_rst_init(struct device_node *np, void __iomem *reg_base) diff --git a/include/dt-bindings/reset/rockchip,rk3588-cru.h b/include/dt-bindings/reset/rockchip,rk3588-cru.h -index d4264db2a07f..c0d08ae78cd5 100644 +index e2fe4bd5f7f0..b74f1046f5a5 100644 --- a/include/dt-bindings/reset/rockchip,rk3588-cru.h +++ b/include/dt-bindings/reset/rockchip,rk3588-cru.h -@@ -716,39 +716,39 @@ +@@ -716,40 +716,40 @@ #define SRST_P_GPIO0 627 #define SRST_GPIO0 628 @@ -318,7 +318,8 @@ index d4264db2a07f..c0d08ae78cd5 100644 +#define SRST_P_TRNG_CHK 53 +#define SRST_TRNG_S 54 - #endif + #define SRST_A_HDMIRX_BIU 660 + -- Armbian @@ -341,12 +342,12 @@ Signed-off-by: Corentin Labbe 6 files changed, 1939 insertions(+) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig -index 0991f026cb07..09edba08fbb6 100644 +index 94f23c6fc93b..95d700c88161 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig -@@ -661,6 +661,35 @@ config CRYPTO_DEV_ROCKCHIP_DEBUG - the number of requests per algorithm and other internal stats. - +@@ -653,6 +653,35 @@ config CRYPTO_DEV_TEGRA + Select this to enable Tegra Security Engine which accelerates various + AES encryption/decryption and HASH algorithms. +config CRYPTO_DEV_ROCKCHIP2 + tristate "Rockchip's cryptographic offloader V2" diff --git a/patch/kernel/rockchip-rk3588-edge/0025-RK3588-Add-HW-RNG-Support.patch b/patch/kernel/rockchip-rk3588-edge/0025-RK3588-Add-HW-RNG-Support.patch index 0ca36c2662eb..437820b73940 100644 --- a/patch/kernel/rockchip-rk3588-edge/0025-RK3588-Add-HW-RNG-Support.patch +++ b/patch/kernel/rockchip-rk3588-edge/0025-RK3588-Add-HW-RNG-Support.patch @@ -638,10 +638,10 @@ Subject: arm64: dts: Add HW RNG support to RK3588S 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 97d8de940a4f..c7a912617b79 100644 +index 8a2eb9013fe0..dab4a518227d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -1923,6 +1923,16 @@ crypto: crypto@fe370000 { +@@ -1935,6 +1935,16 @@ crypto: crypto@fe370000 { status = "okay"; }; diff --git a/patch/kernel/rockchip-rk3588-edge/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch b/patch/kernel/rockchip-rk3588-edge/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch index 76be370a9910..23adfbafe052 100644 --- a/patch/kernel/rockchip-rk3588-edge/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch +++ b/patch/kernel/rockchip-rk3588-edge/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch @@ -11,10 +11,10 @@ Signed-off-by: Cristian Ciocaltea 1 file changed, 55 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index ca34e95b8008..24a365e34180 100644 +index dab4a518227d..3df7724d1ca6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -1407,6 +1407,61 @@ i2s9_8ch: i2s@fddfc000 { +@@ -1414,6 +1414,61 @@ i2s9_8ch: i2s@fddfc000 { status = "disabled"; }; diff --git a/patch/kernel/rockchip-rk3588-edge/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch b/patch/kernel/rockchip-rk3588-edge/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch index b5ad0ad15050..3baf12b4906a 100644 --- a/patch/kernel/rockchip-rk3588-edge/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch +++ b/patch/kernel/rockchip-rk3588-edge/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch @@ -10,10 +10,10 @@ missing #clock-cells property. 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 24a365e34180..58f7740b0e3c 100644 +index 3df7724d1ca6..81bcdc31a70b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -2913,6 +2913,7 @@ hdptxphy_hdmi0: phy@fed60000 { +@@ -2883,6 +2883,7 @@ hdptxphy_hdmi0: phy@fed60000 { reg = <0x0 0xfed60000 0x0 0x2000>; clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>; clock-names = "ref", "apb"; diff --git a/patch/kernel/rockchip-rk3588-edge/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch b/patch/kernel/rockchip-rk3588-edge/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch index bfc7c9d3b206..515472482cd8 100644 --- a/patch/kernel/rockchip-rk3588-edge/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch +++ b/patch/kernel/rockchip-rk3588-edge/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch @@ -19,7 +19,7 @@ Signed-off-by: Cristian Ciocaltea 1 file changed, 552 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c -index fdd768bbd487..c1361ceaec41 100644 +index 62ebbdb16253..86d2c15af39f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -5,6 +5,8 @@ @@ -62,7 +62,7 @@ index fdd768bbd487..c1361ceaec41 100644 #define vop2_output_if_is_hdmi(x) ((x) == ROCKCHIP_VOP2_EP_HDMI0 || \ (x) == ROCKCHIP_VOP2_EP_HDMI1) -@@ -1474,9 +1493,30 @@ static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc, +@@ -1476,9 +1495,30 @@ static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adj_mode) { @@ -93,7 +93,7 @@ index fdd768bbd487..c1361ceaec41 100644 return true; } -@@ -1661,6 +1701,31 @@ static unsigned long rk3588_calc_dclk(unsigned long child_clk, unsigned long max +@@ -1663,6 +1703,31 @@ static unsigned long rk3588_calc_dclk(unsigned long child_clk, unsigned long max return 0; } @@ -125,7 +125,7 @@ index fdd768bbd487..c1361ceaec41 100644 /* * 4 pixclk/cycle on rk3588 * RGB/eDP/HDMI: if_pixclk >= dclk_core -@@ -1684,6 +1749,72 @@ static unsigned long rk3588_calc_cru_cfg(struct vop2_video_port *vp, int id, +@@ -1686,6 +1751,72 @@ static unsigned long rk3588_calc_cru_cfg(struct vop2_video_port *vp, int id, int K = 1; if (vop2_output_if_is_hdmi(id)) { @@ -198,7 +198,7 @@ index fdd768bbd487..c1361ceaec41 100644 /* * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate -@@ -1915,6 +2046,22 @@ static int us_to_vertical_line(struct drm_display_mode *mode, int us) +@@ -1917,6 +2048,22 @@ static int us_to_vertical_line(struct drm_display_mode *mode, int us) return us * mode->clock / mode->htotal / 1000; } @@ -221,7 +221,7 @@ index fdd768bbd487..c1361ceaec41 100644 static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) { -@@ -1942,6 +2089,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, +@@ -1944,6 +2091,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, u32 val, polflags; int ret; struct drm_encoder *encoder; @@ -230,7 +230,7 @@ index fdd768bbd487..c1361ceaec41 100644 drm_dbg(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d\n", hdisplay, vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", -@@ -2042,11 +2191,38 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, +@@ -2044,11 +2193,38 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, if (mode->flags & DRM_MODE_FLAG_DBLCLK) { dsp_ctrl |= RK3568_VP_DSP_CTRL__CORE_DCLK_DIV; @@ -270,7 +270,7 @@ index fdd768bbd487..c1361ceaec41 100644 clk_set_rate(vp->dclk, clock); vop2_post_config(crtc); -@@ -2502,7 +2678,43 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, +@@ -2504,7 +2680,43 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, spin_unlock_irq(&crtc->dev->event_lock); } @@ -314,7 +314,7 @@ index fdd768bbd487..c1361ceaec41 100644 .mode_fixup = vop2_crtc_mode_fixup, .atomic_check = vop2_crtc_atomic_check, .atomic_begin = vop2_crtc_atomic_begin, -@@ -3072,6 +3284,336 @@ static const struct regmap_config vop2_regmap_config = { +@@ -3074,6 +3286,336 @@ static const struct regmap_config vop2_regmap_config = { .cache_type = REGCACHE_MAPLE, }; @@ -651,7 +651,7 @@ index fdd768bbd487..c1361ceaec41 100644 static int vop2_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); -@@ -3165,6 +3707,12 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) +@@ -3167,6 +3709,12 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) return PTR_ERR(vop2->pclk); } @@ -664,7 +664,7 @@ index fdd768bbd487..c1361ceaec41 100644 vop2->irq = platform_get_irq(pdev, 0); if (vop2->irq < 0) { drm_err(vop2->drm, "cannot find irq for vop2\n"); -@@ -3181,6 +3729,9 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) +@@ -3183,6 +3731,9 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) if (ret) return ret; diff --git a/patch/kernel/rockchip-rk3588-edge/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch b/patch/kernel/rockchip-rk3588-edge/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch index 98388d016e01..54d40a76714c 100644 --- a/patch/kernel/rockchip-rk3588-edge/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch +++ b/patch/kernel/rockchip-rk3588-edge/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch @@ -1,17 +1,17 @@ -From 54b308f31f637004f3e0f3e13a3d08e1c62c8ae3 Mon Sep 17 00:00:00 2001 +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Muhammed Efe Cetin Date: Mon, 13 May 2024 20:29:49 +0300 -Subject: [PATCH] arm64: dts: rockchip: rk3588: add VDPU and RGA2 nodes +Subject: arm64: dts: rockchip: rk3588: add VDPU and RGA2 nodes --- - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 32 +++++++++++++++++++++++ + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 32 ++++++++++ 1 file changed, 32 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 387cfc7ee261..1ca59486b61c 100644 +index 81bcdc31a70b..e7d36a0a2347 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -848,6 +848,38 @@ gpu: gpu@fb000000 { +@@ -726,6 +726,38 @@ mmu600_php: iommu@fcb00000 { status = "disabled"; }; @@ -51,5 +51,5 @@ index 387cfc7ee261..1ca59486b61c 100644 compatible = "rockchip,rk3588-pmugrf", "syscon", "simple-mfd"; reg = <0x0 0xfd58a000 0x0 0x10000>; -- -2.44.0 +Armbian diff --git a/patch/kernel/rockchip-rk3588-edge/0801-wireless-add-bcm43752.patch b/patch/kernel/rockchip-rk3588-edge/0801-wireless-add-bcm43752.patch index 84b8d0f87194..ab51f8846d53 100644 --- a/patch/kernel/rockchip-rk3588-edge/0801-wireless-add-bcm43752.patch +++ b/patch/kernel/rockchip-rk3588-edge/0801-wireless-add-bcm43752.patch @@ -13,7 +13,7 @@ Signed-off-by: Ondrej Jirman 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c -index d7fb88bb6ae1..89b9f25f56d4 100644 +index 06698a714b52..0ecd19c655e3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -70,6 +70,7 @@ BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie"); @@ -32,7 +32,7 @@ index d7fb88bb6ae1..89b9f25f56d4 100644 BRCMF_FW_ENTRY(BRCM_CC_4377_CHIP_ID, 0xFFFFFFFF, 4377B3), /* revision ID 4 */ BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0x0000000F, 4378B1), /* revision ID 3 */ BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFE0, 4378B3), /* revision ID 5 */ -@@ -1711,7 +1713,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, +@@ -1720,7 +1722,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, memcpy_toio(devinfo->tcm + address, nvram, nvram_len); brcmf_fw_nvram_free(nvram); @@ -41,7 +41,7 @@ index d7fb88bb6ae1..89b9f25f56d4 100644 size_t rand_len = BRCMF_RANDOM_SEED_LENGTH; struct brcmf_random_seed_footer footer = { .length = cpu_to_le32(rand_len), -@@ -2695,6 +2697,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { +@@ -2700,6 +2702,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID, BCA), BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID, WCC), BRCMF_PCIE_DEVICE(BRCM_PCIE_43596_DEVICE_ID, CYW), diff --git a/patch/kernel/rockchip-rk3588-edge/0802-wireless-add-clk-property.patch b/patch/kernel/rockchip-rk3588-edge/0802-wireless-add-clk-property.patch index 1ae551857d77..1aba98f99dcb 100644 --- a/patch/kernel/rockchip-rk3588-edge/0802-wireless-add-clk-property.patch +++ b/patch/kernel/rockchip-rk3588-edge/0802-wireless-add-clk-property.patch @@ -12,7 +12,7 @@ Signed-off-by: Ondrej Jirman 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c -index 89b9f25f56d4..b2e0b5f0512e 100644 +index 0ecd19c655e3..add317731126 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -3,6 +3,7 @@ @@ -23,7 +23,7 @@ index 89b9f25f56d4..b2e0b5f0512e 100644 #include #include #include -@@ -2408,6 +2409,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) +@@ -2413,6 +2414,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct brcmf_pciedev *pcie_bus_dev; struct brcmf_core *core; struct brcmf_bus *bus; @@ -31,7 +31,7 @@ index 89b9f25f56d4..b2e0b5f0512e 100644 if (!id) { id = pci_match_id(brcmf_pcie_devid_table, pdev); -@@ -2419,6 +2421,14 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) +@@ -2424,6 +2426,14 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device); diff --git a/patch/kernel/rockchip-rk3588-edge/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch b/patch/kernel/rockchip-rk3588-edge/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch index d862da277c3a..5b049aec57df 100644 --- a/patch/kernel/rockchip-rk3588-edge/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch +++ b/patch/kernel/rockchip-rk3588-edge/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch @@ -8,10 +8,10 @@ Subject: arm64: dts: rock-5b: Slow down emmc to hs200 and add tsadc node 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index 149bd44ffd1c..4c66108b24e2 100644 +index 21e96c212dd8..fccd71c37749 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -@@ -359,8 +359,7 @@ &sdhci { +@@ -371,8 +371,7 @@ &sdhci { no-sdio; no-sd; non-removable; @@ -21,7 +21,7 @@ index 149bd44ffd1c..4c66108b24e2 100644 status = "okay"; }; -@@ -400,6 +399,10 @@ &sdio { +@@ -411,6 +410,10 @@ &sdio { status = "okay"; }; diff --git a/patch/kernel/rockchip-rk3588-edge/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch b/patch/kernel/rockchip-rk3588-edge/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch index a66317092247..2908da69fd25 100644 --- a/patch/kernel/rockchip-rk3588-edge/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch +++ b/patch/kernel/rockchip-rk3588-edge/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch @@ -10,10 +10,10 @@ Signed-off-by: lanefu 1 file changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index 4c66108b24e2..7264195d5551 100644 +index fccd71c37749..c02a6b41f071 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -@@ -409,6 +409,33 @@ &uart6 { +@@ -420,6 +420,33 @@ &uart6 { status = "okay"; }; diff --git a/patch/kernel/rockchip-rk3588-edge/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch b/patch/kernel/rockchip-rk3588-edge/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch index ce44eb2fce48..503a51bec0a0 100644 --- a/patch/kernel/rockchip-rk3588-edge/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch +++ b/patch/kernel/rockchip-rk3588-edge/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch @@ -11,7 +11,7 @@ Signed-off-by: Cristian Ciocaltea 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index 7264195d5551..b697c707f3f3 100644 +index c02a6b41f071..745ed06e9bb1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts @@ -4,6 +4,7 @@ @@ -22,8 +22,8 @@ index 7264195d5551..b697c707f3f3 100644 #include "rk3588.dtsi" / { -@@ -173,6 +174,20 @@ &cpu_l3 { - cpu-supply = <&vdd_cpu_lit_s0>; +@@ -185,6 +186,20 @@ &gpu { + status = "okay"; }; +&hdmi0 { @@ -43,7 +43,7 @@ index 7264195d5551..b697c707f3f3 100644 &i2c0 { pinctrl-names = "default"; pinctrl-0 = <&i2c0m2_xfer>; -@@ -821,3 +836,18 @@ &usb_host1_xhci { +@@ -836,3 +851,18 @@ &usb_host1_xhci { &usb_host2_xhci { status = "okay"; }; diff --git a/patch/kernel/rockchip-rk3588-edge/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch b/patch/kernel/rockchip-rk3588-edge/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch index 2567e3eb4c42..ddd40972524d 100644 --- a/patch/kernel/rockchip-rk3588-edge/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch +++ b/patch/kernel/rockchip-rk3588-edge/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch @@ -21,10 +21,10 @@ Signed-off-by: Cristian Ciocaltea 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index 7aefcb5498c0..19708c998bd6 100644 +index 745ed06e9bb1..726da087fc4a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -@@ -179,6 +179,11 @@ &gpu { +@@ -186,6 +186,11 @@ &gpu { status = "okay"; }; diff --git a/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch b/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch index ae96de16a2ed..9b4da1b0fa5f 100644 --- a/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch +++ b/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch @@ -16,10 +16,10 @@ Signed-off-by: Alexey Charkov 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index 21e96c212dd8..b70313643af8 100644 +index 726da087fc4a..f7dc7572e3ea 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -@@ -52,7 +52,7 @@ led_rgb_b { +@@ -53,7 +53,7 @@ led_rgb_b { fan: pwm-fan { compatible = "pwm-fan"; @@ -28,7 +28,7 @@ index 21e96c212dd8..b70313643af8 100644 fan-supply = <&vcc5v0_sys>; pwms = <&pwm1 0 50000 0>; #cooling-cells = <2>; -@@ -279,6 +279,34 @@ i2s0_8ch_p0_0: endpoint { +@@ -299,6 +299,34 @@ i2s0_8ch_p0_0: endpoint { }; }; @@ -64,4 +64,5 @@ index 21e96c212dd8..b70313643af8 100644 pinctrl-names = "default"; pinctrl-0 = <&pcie2_0_rst>; -- -Armbian \ No newline at end of file +Armbian + diff --git a/patch/kernel/rockchip-rk3588-edge/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch b/patch/kernel/rockchip-rk3588-edge/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch index bf3e2071aa83..49b9268a3311 100644 --- a/patch/kernel/rockchip-rk3588-edge/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch +++ b/patch/kernel/rockchip-rk3588-edge/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch @@ -8,7 +8,7 @@ Subject: Add HDMI and VOP2 to Rock 5A 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -index 149058352f4e..81377dc4b583 100644 +index c671a61d3aef..56f385d31f21 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts @@ -5,6 +5,7 @@ @@ -19,7 +19,7 @@ index 149058352f4e..81377dc4b583 100644 #include "rk3588s.dtsi" / { -@@ -760,3 +761,32 @@ &usb_host1_ohci { +@@ -763,3 +764,32 @@ &usb_host1_ohci { &usb_host2_xhci { status = "okay"; }; diff --git a/patch/kernel/rockchip-rk3588-edge/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch b/patch/kernel/rockchip-rk3588-edge/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch index bae296bad291..dabd54888c3f 100644 --- a/patch/kernel/rockchip-rk3588-edge/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch +++ b/patch/kernel/rockchip-rk3588-edge/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch @@ -8,7 +8,7 @@ Subject: arch: arm64: dts: enable gpu node for rock-5a 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -index 81377dc4b583..8d34c616e672 100644 +index 56f385d31f21..4f8e7a16d349 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts @@ -281,6 +281,11 @@ &gmac1_rgmii_clk @@ -23,7 +23,7 @@ index 81377dc4b583..8d34c616e672 100644 &mdio1 { rgmii_phy1: ethernet-phy@1 { /* RTL8211F */ -@@ -433,6 +438,7 @@ rk806_dvs3_null: dvs3-null-pins { +@@ -432,6 +437,7 @@ rk806_dvs3_null: dvs3-null-pins { regulators { vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { regulator-name = "vdd_gpu_s0"; diff --git a/patch/kernel/rockchip-rk3588-edge/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch b/patch/kernel/rockchip-rk3588-edge/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch index b872d595127e..92d736198339 100644 --- a/patch/kernel/rockchip-rk3588-edge/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch +++ b/patch/kernel/rockchip-rk3588-edge/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch @@ -8,7 +8,7 @@ Subject: arm64: dts: Add missing nodes to Orange Pi 5 Plus 1 file changed, 181 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts -index e74871491ef5..4ab8892f47ca 100644 +index 1a604429fb26..939179c5b93b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts @@ -10,6 +10,7 @@ @@ -137,7 +137,7 @@ index e74871491ef5..4ab8892f47ca 100644 vcc5v0_usb20_en: vcc5v0-usb20-en { rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; }; -@@ -803,6 +885,22 @@ &tsadc { +@@ -802,6 +884,22 @@ &tsadc { status = "okay"; }; @@ -160,7 +160,7 @@ index e74871491ef5..4ab8892f47ca 100644 &u2phy2 { status = "okay"; }; -@@ -831,6 +929,35 @@ &uart9 { +@@ -830,6 +928,35 @@ &uart9 { status = "okay"; }; @@ -196,7 +196,7 @@ index e74871491ef5..4ab8892f47ca 100644 &usb_host0_ehci { status = "okay"; }; -@@ -839,6 +966,20 @@ &usb_host0_ohci { +@@ -838,6 +965,20 @@ &usb_host0_ohci { status = "okay"; }; @@ -217,7 +217,7 @@ index e74871491ef5..4ab8892f47ca 100644 &usb_host1_ehci { status = "okay"; }; -@@ -846,3 +987,42 @@ &usb_host1_ehci { +@@ -845,3 +986,42 @@ &usb_host1_ehci { &usb_host1_ohci { status = "okay"; }; diff --git a/patch/kernel/rockchip-rk3588-edge/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch b/patch/kernel/rockchip-rk3588-edge/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch index 03ef2e1a68d0..f993a486b42f 100644 --- a/patch/kernel/rockchip-rk3588-edge/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch +++ b/patch/kernel/rockchip-rk3588-edge/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch @@ -8,10 +8,10 @@ Subject: arm64: dts: rockchip: support poweroff on rock-5a 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -index 8d34c616e672..1bc5b6a4e9b8 100644 +index 4f8e7a16d349..23a9a160bb52 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -@@ -401,6 +401,8 @@ pmic@0 { +@@ -400,6 +400,8 @@ pmic@0 { <&rk806_dvs2_null>, <&rk806_dvs3_null>; spi-max-frequency = <1000000>; diff --git a/patch/kernel/rockchip-rk3588-edge/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch b/patch/kernel/rockchip-rk3588-edge/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch index a3d5cb90a723..a4ba348c31f8 100644 --- a/patch/kernel/rockchip-rk3588-edge/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch +++ b/patch/kernel/rockchip-rk3588-edge/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch @@ -8,7 +8,7 @@ Subject: arm64: dts: rockchip: add PCIe for M.2 E-Key to rock-5a 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -index 1bc5b6a4e9b8..63824af7f281 100644 +index 23a9a160bb52..daefce00446d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts @@ -115,6 +115,10 @@ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { diff --git a/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch b/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch index 129d3542aafe..24e0d0f8bca4 100644 --- a/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch +++ b/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch @@ -4,17 +4,15 @@ Date: Wed, 6 Mar 2024 00:09:25 +0300 Subject: mfd: khadas-mcu: add Edge2 registers --- - drivers/mfd/khadas-mcu.c | 8 +++- + drivers/mfd/khadas-mcu.c | 6 ++- include/linux/mfd/khadas-mcu.h | 24 ++++++++++ - 2 files changed, 30 insertions(+), 2 deletions(-) + 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c index ba981a788692..21c4cd46f41c 100644 --- a/drivers/mfd/khadas-mcu.c +++ b/drivers/mfd/khadas-mcu.c -@@ -24,10 +24,14 @@ static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg) - case KHADAS_MCU_PASSWD_START_REG: - case KHADAS_MCU_CHECK_VEN_PASSWD_REG: +@@ -26,6 +26,10 @@ static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg) case KHADAS_MCU_CHECK_USER_PASSWD_REG: case KHADAS_MCU_WOL_INIT_START_REG: case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG: @@ -25,11 +23,7 @@ index ba981a788692..21c4cd46f41c 100644 return true; default: return false; - } - } -@@ -74,11 +78,11 @@ static const struct regmap_config khadas_mcu_regmap_config = { - .writeable_reg = khadas_mcu_reg_writeable, - .cache_type = REGCACHE_MAPLE, +@@ -76,7 +80,7 @@ static const struct regmap_config khadas_mcu_regmap_config = { }; static struct mfd_cell khadas_mcu_fan_cells[] = { @@ -38,9 +32,6 @@ index ba981a788692..21c4cd46f41c 100644 { .name = "khadas-mcu-fan-ctrl", }, }; - static struct mfd_cell khadas_mcu_cells[] = { - { .name = "khadas-mcu-user-mem", }, - diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h index a99ba2ed0e4e..63bc9bf76661 100644 --- a/include/linux/mfd/khadas-mcu.h @@ -123,7 +114,7 @@ Subject: mfd: khadas-mcu: drop unused code 1 file changed, 11 deletions(-) diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c -index a1a63fb70aac..805fb9eb4a2f 100644 +index 21c4cd46f41c..91da966dedf4 100644 --- a/drivers/mfd/khadas-mcu.c +++ b/drivers/mfd/khadas-mcu.c @@ -84,10 +84,6 @@ static struct mfd_cell khadas_mcu_fan_cells[] = { @@ -341,10 +332,10 @@ Subject: arm64: dts: rockchip: Add MCU to Khadas Edge 2 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index cf29563736ea..a292d1fd7eca 100644 +index dbddfc3bb464..4c1fa21ee8e7 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -307,6 +307,13 @@ hym8563: rtc@51 { +@@ -231,6 +231,13 @@ hym8563: rtc@51 { clock-output-names = "hym8563"; wakeup-source; }; @@ -371,10 +362,10 @@ Subject: arm64: dts: rockchip: Add automatic fan control to Khadas Edge 2 1 file changed, 56 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index a292d1fd7eca..803907ba4037 100644 +index 4c1fa21ee8e7..dcd9a81cc39e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -316,6 +316,62 @@ khadas_mcu: system-controller@18 { +@@ -240,6 +240,62 @@ khadas_mcu: system-controller@18 { }; }; From 5de4cd02fd1e1509e707ff43916f30dd7e9914c5 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:08:38 +0200 Subject: [PATCH 27/53] rk3588: edge: Fix HDMI controller driver The old driver didn't build on 6.10, so the kernel build couldn't finish. Fix this driver. --- ...tial-support-for-DW-HDMI-Controller.patch} | 1 - ...-bridge-synopsys-Fix-HDMI-Controller.patch | 29 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) rename patch/kernel/rockchip-rk3588-edge/{0137-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-.patch => 0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch} (99%) create mode 100644 patch/kernel/rockchip-rk3588-edge/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0137-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-.patch b/patch/kernel/rockchip-rk3588-edge/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch similarity index 99% rename from patch/kernel/rockchip-rk3588-edge/0137-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-.patch rename to patch/kernel/rockchip-rk3588-edge/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch index 3c61589a89ad..1e80d2615bf6 100644 --- a/patch/kernel/rockchip-rk3588-edge/0137-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-.patch +++ b/patch/kernel/rockchip-rk3588-edge/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch @@ -6613,4 +6613,3 @@ index 6a46baa0737c..ac4e418c1c4e 100644 -- Armbian - diff --git a/patch/kernel/rockchip-rk3588-edge/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch b/patch/kernel/rockchip-rk3588-edge/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch new file mode 100644 index 000000000000..86e442b47a45 --- /dev/null +++ b/patch/kernel/rockchip-rk3588-edge/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: ColorfulRhino +Date: Wed, 12 Jun 2024 12:17:18 +0200 +Subject: Fix HDMI controller patch at + drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +index 8817ef9a9de9..324dee775651 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +@@ -3,10 +3,11 @@ + * Copyright (C) Rockchip Electronics Co.Ltd + * Author: + * Algea Cao + */ + #include ++#include + #include + #include + #include + #include + #include +-- +Created with Armbian build tools https://github.com/armbian/build + From b9183f56a479c5aa05a4bd3189ca2d54eeef5528 Mon Sep 17 00:00:00 2001 From: amazingfate Date: Fri, 7 Jun 2024 09:48:55 +0800 Subject: [PATCH 28/53] rk3588: edge: armsom-sige7: Use dts patch instead of bare dts --- ...hip-Add-HDMI-support-to-ArmSoM-Sige7.patch | 64 ++ ...ip-Add-ap6275p-wireless-support-to-A.patch | 39 + .../dt/rk3588-armsom-sige7.dts | 767 ------------------ 3 files changed, 103 insertions(+), 767 deletions(-) create mode 100644 patch/kernel/rockchip-rk3588-edge/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch create mode 100644 patch/kernel/rockchip-rk3588-edge/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch delete mode 100644 patch/kernel/rockchip-rk3588-edge/dt/rk3588-armsom-sige7.dts diff --git a/patch/kernel/rockchip-rk3588-edge/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch b/patch/kernel/rockchip-rk3588-edge/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch new file mode 100644 index 000000000000..95a4aecb9a78 --- /dev/null +++ b/patch/kernel/rockchip-rk3588-edge/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianfeng Liu +Date: Thu, 6 Jun 2024 23:28:01 +0800 +Subject: arm64: dts: rockchip: Add HDMI support to ArmSoM Sige7 + +--- + arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts | 30 ++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts +index c667704ba985..fdd0cdb389d7 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts +@@ -4,6 +4,7 @@ + + #include + #include ++#include + #include "rk3588.dtsi" + + / { +@@ -164,6 +165,20 @@ &gpu { + status = "okay"; + }; + ++&hdmi0 { ++ status = "okay"; ++}; ++ ++&hdmi0_in { ++ hdmi0_in_vp0: endpoint { ++ remote-endpoint = <&vp0_out_hdmi0>; ++ }; ++}; ++ ++&hdptxphy_hdmi0 { ++ status = "okay"; ++}; ++ + &i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; +@@ -723,3 +738,18 @@ &usb_host1_xhci { + dr_mode = "host"; + status = "okay"; + }; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vp0 { ++ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { ++ reg = ; ++ remote-endpoint = <&hdmi0_in_vp0>; ++ }; ++}; +-- +Armbian + diff --git a/patch/kernel/rockchip-rk3588-edge/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch b/patch/kernel/rockchip-rk3588-edge/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch new file mode 100644 index 000000000000..3ec6f2d5d414 --- /dev/null +++ b/patch/kernel/rockchip-rk3588-edge/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jianfeng Liu +Date: Thu, 6 Jun 2024 23:29:39 +0800 +Subject: arm64: dts: rockchip: Add ap6275p wireless support to ArmSoM Sige7 + +--- + arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts | 16 ++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts +index fdd0cdb389d7..698120e224fe 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts +@@ -283,6 +283,22 @@ &pcie2x1l0 { + &pcie2x1l1 { + reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0x300000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ranges; ++ device_type = "pci"; ++ bus-range = <0x30 0x3f>; ++ ++ wifi: wifi@0,0 { ++ compatible = "pci14e4,449d"; ++ reg = <0x310000 0 0 0 0>; ++ clocks = <&hym8563>; ++ clock-names = "32k"; ++ }; ++ }; + }; + + /* phy0 - left ethernet port */ +-- +Armbian + diff --git a/patch/kernel/rockchip-rk3588-edge/dt/rk3588-armsom-sige7.dts b/patch/kernel/rockchip-rk3588-edge/dt/rk3588-armsom-sige7.dts deleted file mode 100644 index bee75afd5fa6..000000000000 --- a/patch/kernel/rockchip-rk3588-edge/dt/rk3588-armsom-sige7.dts +++ /dev/null @@ -1,767 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) - -/dts-v1/; - -#include -#include -#include -#include "rk3588.dtsi" - -/ { - model = "ArmSoM Sige7"; - compatible = "armsom,sige7", "rockchip,rk3588"; - - aliases { - mmc0 = &sdhci; - mmc1 = &sdmmc; - }; - - chosen { - stdout-path = "serial2:1500000n8"; - }; - - analog-sound { - compatible = "audio-graph-card"; - dais = <&i2s0_8ch_p0>; - label = "rk3588-es8316"; - hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&hp_detect>; - routing = "MIC2", "Mic Jack", - "Headphones", "HPOL", - "Headphones", "HPOR"; - widgets = "Microphone", "Mic Jack", - "Headphone", "Headphones"; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_rgb_g>; - - led_green: led-0 { - color = ; - function = LED_FUNCTION_STATUS; - gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "heartbeat"; - }; - - led_red: led-1 { - color = ; - function = LED_FUNCTION_STATUS; - gpios = <&gpio4 RK_PC5 GPIO_ACTIVE_HIGH>; - linux,default-trigger = "none"; - }; - }; - - fan: pwm-fan { - compatible = "pwm-fan"; - cooling-levels = <0 95 145 195 255>; - fan-supply = <&vcc5v0_sys>; - pwms = <&pwm1 0 50000 0>; - #cooling-cells = <2>; - }; - - vcc3v3_pcie2x1l2: vcc3v3-pcie2x1l2-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc3v3_pcie2x1l2"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - startup-delay-us = <5000>; - vin-supply = <&vcc_3v3_s3>; - }; - - vcc3v3_pcie30: vcc3v3-pcie30-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>; - regulator-name = "vcc3v3_pcie30"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - startup-delay-us = <5000>; - vin-supply = <&vcc5v0_sys>; - }; - - vcc5v0_host: vcc5v0-host-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_host"; - regulator-boot-on; - regulator-always-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&vcc5v0_host_en>; - vin-supply = <&vcc5v0_sys>; - }; - - vcc5v0_sys: vcc5v0-sys-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - }; - - vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { - compatible = "regulator-fixed"; - regulator-name = "vcc_1v1_nldo_s3"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <1100000>; - vin-supply = <&vcc5v0_sys>; - }; -}; - -&combphy0_ps { - status = "okay"; -}; - -&combphy1_ps { - status = "okay"; -}; - -&combphy2_psu { - status = "okay"; -}; - -&cpu_b0 { - cpu-supply = <&vdd_cpu_big0_s0>; -}; - -&cpu_b1 { - cpu-supply = <&vdd_cpu_big0_s0>; -}; - -&cpu_b2 { - cpu-supply = <&vdd_cpu_big1_s0>; -}; - -&cpu_b3 { - cpu-supply = <&vdd_cpu_big1_s0>; -}; - -&cpu_l0 { - cpu-supply = <&vdd_cpu_lit_s0>; -}; - -&cpu_l1 { - cpu-supply = <&vdd_cpu_lit_s0>; -}; - -&cpu_l2 { - cpu-supply = <&vdd_cpu_lit_s0>; -}; - -&cpu_l3 { - cpu-supply = <&vdd_cpu_lit_s0>; -}; - -&gpu { - mali-supply = <&vdd_gpu_s0>; - status = "okay"; -}; - -&hdmi0 { - status = "okay"; -}; - -&hdmi0_in { - hdmi0_in_vp0: endpoint { - remote-endpoint = <&vp0_out_hdmi0>; - }; -}; - -&hdptxphy_hdmi0 { - status = "okay"; -}; - -&i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c0m2_xfer>; - status = "okay"; - - vdd_cpu_big0_s0: regulator@42 { - compatible = "rockchip,rk8602"; - reg = <0x42>; - fcs,suspend-voltage-selector = <1>; - regulator-name = "vdd_cpu_big0_s0"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <1050000>; - regulator-ramp-delay = <2300>; - vin-supply = <&vcc5v0_sys>; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_cpu_big1_s0: regulator@43 { - compatible = "rockchip,rk8603", "rockchip,rk8602"; - reg = <0x43>; - fcs,suspend-voltage-selector = <1>; - regulator-name = "vdd_cpu_big1_s0"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <1050000>; - regulator-ramp-delay = <2300>; - vin-supply = <&vcc5v0_sys>; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; -}; - -&i2c6 { - status = "okay"; - - hym8563: rtc@51 { - compatible = "haoyu,hym8563"; - reg = <0x51>; - interrupt-parent = <&gpio0>; - interrupts = ; - #clock-cells = <0>; - clock-output-names = "hym8563"; - pinctrl-names = "default"; - pinctrl-0 = <&hym8563_int>; - wakeup-source; - }; -}; - -&i2c7 { - status = "okay"; - - es8316: audio-codec@11 { - compatible = "everest,es8316"; - reg = <0x11>; - assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; - assigned-clock-rates = <12288000>; - clocks = <&cru I2S0_8CH_MCLKOUT>; - clock-names = "mclk"; - #sound-dai-cells = <0>; - - port { - es8316_p0_0: endpoint { - remote-endpoint = <&i2s0_8ch_p0_0>; - }; - }; - }; -}; - -&i2s0_8ch { - pinctrl-names = "default"; - pinctrl-0 = <&i2s0_lrck - &i2s0_mclk - &i2s0_sclk - &i2s0_sdi0 - &i2s0_sdo0>; - status = "okay"; - - i2s0_8ch_p0: port { - i2s0_8ch_p0_0: endpoint { - dai-format = "i2s"; - mclk-fs = <256>; - remote-endpoint = <&es8316_p0_0>; - }; - }; -}; - -/* phy1 - right ethernet port */ -&pcie2x1l0 { - reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; - status = "okay"; -}; - -/* phy2 - WiFi */ -&pcie2x1l1 { - reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>; - status = "okay"; - - pcie@0,0 { - reg = <0x300000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - ranges; - device_type = "pci"; - bus-range = <0x30 0x3f>; - - wifi: wifi@0,0 { - compatible = "pci14e4,449d"; - reg = <0x310000 0 0 0 0>; - clocks = <&hym8563>; - clock-names = "32k"; - }; - }; -}; - -/* phy0 - left ethernet port */ -&pcie2x1l2 { - reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>; - status = "okay"; -}; - -&pcie30phy { - status = "okay"; -}; - -&pcie3x4 { - reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; - vpcie3v3-supply = <&vcc3v3_pcie30>; - status = "okay"; -}; - -&pinctrl { - hym8563 { - hym8563_int: hym8563-int { - rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - leds { - led_rgb_g: led-rgb-g { - rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; - }; - led_rgb_r: led-rgb-r { - rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - sound { - hp_detect: hp-detect { - rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - usb { - vcc5v0_host_en: vcc5v0-host-en { - rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; -}; - -&pwm1 { - status = "okay"; -}; - -&saradc { - vref-supply = <&avcc_1v8_s0>; - status = "okay"; -}; - -&sdhci { - bus-width = <8>; - no-sdio; - no-sd; - non-removable; - mmc-hs200-1_8v; - status = "okay"; -}; - -&sdmmc { - bus-width = <4>; - cap-mmc-highspeed; - cap-sd-highspeed; - disable-wp; - max-frequency = <200000000>; - no-sdio; - no-mmc; - sd-uhs-sdr104; - vmmc-supply = <&vcc_3v3_s3>; - vqmmc-supply = <&vccio_sd_s0>; - status = "okay"; -}; - -&spi2 { - assigned-clocks = <&cru CLK_SPI2>; - assigned-clock-rates = <200000000>; - num-cs = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; - status = "okay"; - - pmic@0 { - compatible = "rockchip,rk806"; - spi-max-frequency = <1000000>; - reg = <0x0>; - - interrupt-parent = <&gpio0>; - interrupts = <7 IRQ_TYPE_LEVEL_LOW>; - - gpio-controller; - #gpio-cells = <2>; - - pinctrl-names = "default"; - pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, - <&rk806_dvs2_null>, <&rk806_dvs3_null>; - - system-power-controller; - - vcc1-supply = <&vcc5v0_sys>; - vcc2-supply = <&vcc5v0_sys>; - vcc3-supply = <&vcc5v0_sys>; - vcc4-supply = <&vcc5v0_sys>; - vcc5-supply = <&vcc5v0_sys>; - vcc6-supply = <&vcc5v0_sys>; - vcc7-supply = <&vcc5v0_sys>; - vcc8-supply = <&vcc5v0_sys>; - vcc9-supply = <&vcc5v0_sys>; - vcc10-supply = <&vcc5v0_sys>; - vcc11-supply = <&vcc_2v0_pldo_s3>; - vcc12-supply = <&vcc5v0_sys>; - vcc13-supply = <&vcc_1v1_nldo_s3>; - vcc14-supply = <&vcc_1v1_nldo_s3>; - vcca-supply = <&vcc5v0_sys>; - - rk806_dvs1_null: dvs1-null-pins { - pins = "gpio_pwrctrl1"; - function = "pin_fun0"; - }; - - rk806_dvs2_null: dvs2-null-pins { - pins = "gpio_pwrctrl2"; - function = "pin_fun0"; - }; - - rk806_dvs3_null: dvs3-null-pins { - pins = "gpio_pwrctrl3"; - function = "pin_fun0"; - }; - - regulators { - vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <950000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_gpu_s0"; - regulator-enable-ramp-delay = <400>; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <950000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_cpu_lit_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_log_s0: dcdc-reg3 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <675000>; - regulator-max-microvolt = <750000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_log_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <750000>; - }; - }; - - vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <950000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_vdenc_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_ddr_s0: dcdc-reg5 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <675000>; - regulator-max-microvolt = <900000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_ddr_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <850000>; - }; - }; - - vdd2_ddr_s3: dcdc-reg6 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vdd2_ddr_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc_2v0_pldo_s3: dcdc-reg7 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <2000000>; - regulator-max-microvolt = <2000000>; - regulator-ramp-delay = <12500>; - regulator-name = "vdd_2v0_pldo_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <2000000>; - }; - }; - - vcc_3v3_s3: dcdc-reg8 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-name = "vcc_3v3_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3300000>; - }; - }; - - vddq_ddr_s0: dcdc-reg9 { - regulator-always-on; - regulator-boot-on; - regulator-name = "vddq_ddr_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc_1v8_s3: dcdc-reg10 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc_1v8_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - avcc_1v8_s0: pldo-reg1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "avcc_1v8_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc_1v8_s0: pldo-reg2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "vcc_1v8_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - avdd_1v2_s0: pldo-reg3 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - regulator-name = "avdd_1v2_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc_3v3_s0: pldo-reg4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-ramp-delay = <12500>; - regulator-name = "vcc_3v3_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vccio_sd_s0: pldo-reg5 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-ramp-delay = <12500>; - regulator-name = "vccio_sd_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - pldo6_s3: pldo-reg6 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-name = "pldo6_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vdd_0v75_s3: nldo-reg1 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <750000>; - regulator-name = "vdd_0v75_s3"; - - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <750000>; - }; - }; - - vdd_ddr_pll_s0: nldo-reg2 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <850000>; - regulator-name = "vdd_ddr_pll_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - regulator-suspend-microvolt = <850000>; - }; - }; - - avdd_0v75_s0: nldo-reg3 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <750000>; - regulator-name = "avdd_0v75_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_0v85_s0: nldo-reg4 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <850000>; - regulator-max-microvolt = <850000>; - regulator-name = "vdd_0v85_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_0v75_s0: nldo-reg5 { - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <750000>; - regulator-name = "vdd_0v75_s0"; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - }; - }; -}; - -&u2phy0 { - status = "okay"; -}; - -&u2phy0_otg { - status = "okay"; -}; - -&u2phy1 { - status = "okay"; -}; - -&u2phy1_otg { - status = "okay"; -}; - -&u2phy3 { - status = "okay"; -}; - -&u2phy3_host { - phy-supply = <&vcc5v0_host>; - status = "okay"; -}; - -&uart2 { - pinctrl-0 = <&uart2m0_xfer>; - status = "okay"; -}; - -&usbdp_phy1 { - status = "okay"; -}; - -&usb_host1_ehci { - status = "okay"; -}; - -&usb_host1_ohci { - status = "okay"; -}; - -&usb_host1_xhci { - dr_mode = "host"; - status = "okay"; -}; - -&vop { - status = "okay"; -}; - -&vop_mmu { - status = "okay"; -}; - -&vp0 { - vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { - reg = ; - remote-endpoint = <&hdmi0_in_vp0>; - }; -}; From 16102a5ead99ded216c554d5791b2017a939033f Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:46:43 +0200 Subject: [PATCH 29/53] kernel: mainline: Bump 6.10-rc2 to 6.10-rc3 --- config/sources/mainline-kernel.conf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/sources/mainline-kernel.conf.sh b/config/sources/mainline-kernel.conf.sh index d8c2a62200c0..0bc3ab768739 100644 --- a/config/sources/mainline-kernel.conf.sh +++ b/config/sources/mainline-kernel.conf.sh @@ -8,7 +8,7 @@ function mainline_kernel_decide_version__upstream_release_candidate_number() { [[ -n "${KERNELBRANCH}" ]] && return 0 # if already set, don't touch it; that way other hooks can run in any order if [[ "${KERNEL_MAJOR_MINOR}" == "6.10" ]]; then # @TODO: roll over to next MAJOR.MINOR and MAJOR.MINOR-rc1 when it is released - declare -g KERNELBRANCH="tag:v6.10-rc2" + declare -g KERNELBRANCH="tag:v6.10-rc3" display_alert "mainline-kernel: upstream release candidate" "Using KERNELBRANCH='${KERNELBRANCH}' for KERNEL_MAJOR_MINOR='${KERNEL_MAJOR_MINOR}'" "info" fi } From 71fe1bde517f5f88bdf03e0820e7c8d6a130d8da Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Wed, 12 Jun 2024 12:52:04 +0200 Subject: [PATCH 30/53] rk3588: edge: Rewrite kernel config to 6.10-rc3 --- config/kernel/linux-rockchip-rk3588-edge.config | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config/kernel/linux-rockchip-rk3588-edge.config b/config/kernel/linux-rockchip-rk3588-edge.config index bd394fa65291..95e11dbbd85a 100644 --- a/config/kernel/linux-rockchip-rk3588-edge.config +++ b/config/kernel/linux-rockchip-rk3588-edge.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 6.10.0-rc2 Kernel Configuration +# Linux/arm64 6.10.0-rc3 Kernel Configuration # CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0" CONFIG_CC_IS_GCC=y @@ -1045,7 +1045,6 @@ CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y CONFIG_USE_PERCPU_NUMA_NODE_ID=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y CONFIG_CMA=y -# CONFIG_CMA_DEBUG is not set # CONFIG_CMA_DEBUGFS is not set # CONFIG_CMA_SYSFS is not set CONFIG_CMA_AREAS=7 From eef5c7046bebf7a5141d15c80c1250a6e57935c9 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Wed, 12 Jun 2024 12:55:57 +0200 Subject: [PATCH 31/53] rk3588: edge: Set kernel config CONFIG_INPUT_RK805_PWRKEY=m This enables powerkey functionality for the PrangePi 5 Plus and other devices using the RK805 --- config/kernel/linux-rockchip-rk3588-edge.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/kernel/linux-rockchip-rk3588-edge.config b/config/kernel/linux-rockchip-rk3588-edge.config index 95e11dbbd85a..89f6423ad1f8 100644 --- a/config/kernel/linux-rockchip-rk3588-edge.config +++ b/config/kernel/linux-rockchip-rk3588-edge.config @@ -4225,7 +4225,7 @@ CONFIG_INPUT_UINPUT=m # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_PWM_BEEPER is not set # CONFIG_INPUT_PWM_VIBRA is not set -# CONFIG_INPUT_RK805_PWRKEY is not set +CONFIG_INPUT_RK805_PWRKEY=m # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set CONFIG_INPUT_DA7280_HAPTICS=m # CONFIG_INPUT_ADXL34X is not set From 6dec7db8a20b1e90cd36ffd0407a02f82294a244 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Wed, 12 Jun 2024 12:56:24 +0200 Subject: [PATCH 32/53] rk3588: edge: Rewrite kernel patches --- .../0001-general-add-overlay-support.patch | 4 +-- .../0010-fix-clk-divisions.patch | 6 ++-- .../0011-irqchip-fix-its-timeout-issue.patch | 34 +++++++++---------- .../0012-fix-initial-PERST-GPIO-value.patch | 2 +- ...3588-Add-Thermal-and-CpuFreq-Support.patch | 26 +++++++------- .../0024-RK3588-Add-Crypto-Support.patch | 22 ++++++------ .../0025-RK3588-Add-HW-RNG-Support.patch | 8 ++--- ...-rockchip-Add-HDMI0-bridge-to-rk3588.patch | 2 +- ...ip-Enable-HDMI0-PHY-clk-provider-on-.patch | 2 +- ...p-samsung-hdptx-Add-FRL-EARC-support.patch | 2 +- ...hip-samsung-hdptx-Add-clock-provider.patch | 2 +- ...2-Improve-display-modes-handling-on-.patch | 2 +- ...kchip-rk3588-add-VDPU-and-RGA2-nodes.patch | 2 +- ...itial-support-for-DW-HDMI-Controller.patch | 23 +++++++------ ...-bridge-synopsys-Fix-HDMI-Controller.patch | 12 +++---- .../0801-wireless-add-bcm43752.patch | 4 +-- .../0802-wireless-add-clk-property.patch | 2 +- ...b-Slow-down-emmc-to-hs200-and-add-ts.patch | 2 +- ...d-rock-5b-arm64-dts-enable-spi-flash.patch | 2 +- ...dts-rockchip-Enable-HDMI0-on-rock-5b.patch | 2 +- ...-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch | 2 +- ...5-board-rock5b-automatic-fan-control.patch | 2 +- .../1020-Add-HDMI-and-VOP2-to-Rock-5A.patch | 2 +- ...rm64-dts-enable-gpu-node-for-rock-5a.patch | 2 +- ...dd-missing-nodes-to-Orange-Pi-5-Plus.patch | 2 +- ...rockchip-support-poweroff-on-rock-5a.patch | 2 +- ...ip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch | 2 +- ...hip-Add-HDMI-support-to-ArmSoM-Sige7.patch | 2 +- ...ip-Add-ap6275p-wireless-support-to-A.patch | 2 +- .../1041-board-khadas-edge2-mcu.patch | 14 ++++---- 30 files changed, 95 insertions(+), 98 deletions(-) diff --git a/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch b/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch index 064c6e3b9eab..e7d57680c83f 100644 --- a/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch +++ b/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch @@ -9,7 +9,7 @@ Subject: compile .scr and install overlays in right path 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst -index 67956f6496a5..151687728a60 100644 +index 111111111111..222222222222 100644 --- a/scripts/Makefile.dtbinst +++ b/scripts/Makefile.dtbinst @@ -33,7 +33,18 @@ endef @@ -33,7 +33,7 @@ index 67956f6496a5..151687728a60 100644 endif # CONFIG_ARCH_WANT_FLAT_DTB_INSTALL diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index 9f06f6aaf7fc..a8254bab1b96 100644 +index 111111111111..222222222222 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -402,7 +402,7 @@ $(obj)/%.dtbo.S: $(obj)/%.dtbo FORCE diff --git a/patch/kernel/rockchip-rk3588-edge/0010-fix-clk-divisions.patch b/patch/kernel/rockchip-rk3588-edge/0010-fix-clk-divisions.patch index d16187ede1f8..25c4a67db09b 100644 --- a/patch/kernel/rockchip-rk3588-edge/0010-fix-clk-divisions.patch +++ b/patch/kernel/rockchip-rk3588-edge/0010-fix-clk-divisions.patch @@ -12,7 +12,7 @@ Signed-off-by: Sebastian Reichel 1 file changed, 11 insertions(+) diff --git a/include/linux/math.h b/include/linux/math.h -index dd4152711de7..f80bfb375ab9 100644 +index 111111111111..222222222222 100644 --- a/include/linux/math.h +++ b/include/linux/math.h @@ -36,6 +36,17 @@ @@ -67,7 +67,7 @@ Signed-off-by: Sebastian Reichel 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c -index a2c2b5203b0a..94b4fb66a60f 100644 +index 111111111111..222222222222 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -220,7 +220,7 @@ static int _div_round_up(const struct clk_div_table *table, @@ -114,7 +114,7 @@ Signed-off-by: Sebastian Reichel 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c -index 66759fe28fad..478a4e594336 100644 +index 111111111111..222222222222 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -6,6 +6,7 @@ diff --git a/patch/kernel/rockchip-rk3588-edge/0011-irqchip-fix-its-timeout-issue.patch b/patch/kernel/rockchip-rk3588-edge/0011-irqchip-fix-its-timeout-issue.patch index a387abc5e430..afbe3796fb8d 100644 --- a/patch/kernel/rockchip-rk3588-edge/0011-irqchip-fix-its-timeout-issue.patch +++ b/patch/kernel/rockchip-rk3588-edge/0011-irqchip-fix-its-timeout-issue.patch @@ -8,7 +8,7 @@ Subject: irqchip/irq-gic-v3-its: fix its timeout issue for rk35xx boards 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c -index 40ebf1726393..eb6ca4504a27 100644 +index 111111111111..222222222222 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -163,6 +163,7 @@ struct its_device { @@ -19,7 +19,7 @@ index 40ebf1726393..eb6ca4504a27 100644 u32 nr_ites; u32 device_id; bool shared; -@@ -2211,6 +2212,9 @@ static void gic_reset_prop_table(void *va) +@@ -2191,6 +2192,9 @@ static void gic_reset_prop_table(void *va) static struct page *its_allocate_prop_table(gfp_t gfp_flags) { struct page *prop_page; @@ -29,7 +29,7 @@ index 40ebf1726393..eb6ca4504a27 100644 prop_page = alloc_pages(gfp_flags, get_order(LPI_PROPBASE_SZ)); if (!prop_page) -@@ -2335,6 +2339,7 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, +@@ -2315,6 +2319,7 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, u32 alloc_pages, psz; struct page *page; void *base; @@ -37,7 +37,7 @@ index 40ebf1726393..eb6ca4504a27 100644 psz = baser->psz; alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz); -@@ -2346,7 +2351,11 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, +@@ -2326,7 +2331,11 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, order = get_order(GITS_BASER_PAGES_MAX * psz); } @@ -50,7 +50,7 @@ index 40ebf1726393..eb6ca4504a27 100644 if (!page) return -ENOMEM; -@@ -2396,6 +2405,15 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, +@@ -2376,6 +2385,15 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, its_write_baser(its, baser, val); tmp = baser->val; @@ -66,7 +66,7 @@ index 40ebf1726393..eb6ca4504a27 100644 if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) { /* * Shareability didn't stick. Just use -@@ -2985,7 +3003,9 @@ static int its_alloc_collections(struct its_node *its) +@@ -2965,7 +2983,9 @@ static int its_alloc_collections(struct its_node *its) static struct page *its_allocate_pending_table(gfp_t gfp_flags) { struct page *pend_page; @@ -77,7 +77,7 @@ index 40ebf1726393..eb6ca4504a27 100644 pend_page = alloc_pages(gfp_flags | __GFP_ZERO, get_order(LPI_PENDBASE_SZ)); if (!pend_page) -@@ -3144,6 +3164,11 @@ static void its_cpu_init_lpis(void) +@@ -3124,6 +3144,11 @@ static void its_cpu_init_lpis(void) if (!rdists_support_shareable()) tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK; @@ -89,7 +89,7 @@ index 40ebf1726393..eb6ca4504a27 100644 if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) { if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) { /* -@@ -3171,6 +3196,11 @@ static void its_cpu_init_lpis(void) +@@ -3151,6 +3176,11 @@ static void its_cpu_init_lpis(void) if (!rdists_support_shareable()) tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK; @@ -101,7 +101,7 @@ index 40ebf1726393..eb6ca4504a27 100644 if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) { /* * The HW reports non-shareable, we must remove the -@@ -3334,7 +3364,11 @@ static bool its_alloc_table_entry(struct its_node *its, +@@ -3314,7 +3344,11 @@ static bool its_alloc_table_entry(struct its_node *its, /* Allocate memory for 2nd level table */ if (!table[idx]) { @@ -114,7 +114,7 @@ index 40ebf1726393..eb6ca4504a27 100644 get_order(baser->psz)); if (!page) return false; -@@ -3423,6 +3457,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, +@@ -3403,6 +3437,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, int nr_lpis; int nr_ites; int sz; @@ -122,7 +122,7 @@ index 40ebf1726393..eb6ca4504a27 100644 if (!its_alloc_device_table(its, dev_id)) return NULL; -@@ -3438,7 +3473,15 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, +@@ -3418,7 +3453,15 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, nr_ites = max(2, nvecs); sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1); sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; @@ -139,7 +139,7 @@ index 40ebf1726393..eb6ca4504a27 100644 if (alloc_lpis) { lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis); if (lpi_map) -@@ -3452,7 +3495,13 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, +@@ -3432,7 +3475,13 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) { kfree(dev); @@ -154,7 +154,7 @@ index 40ebf1726393..eb6ca4504a27 100644 bitmap_free(lpi_map); kfree(col_map); return NULL; -@@ -3462,6 +3511,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, +@@ -3442,6 +3491,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, dev->its = its; dev->itt = itt; @@ -162,7 +162,7 @@ index 40ebf1726393..eb6ca4504a27 100644 dev->nr_ites = nr_ites; dev->event_map.lpi_map = lpi_map; dev->event_map.col_map = col_map; -@@ -3489,7 +3539,13 @@ static void its_free_device(struct its_device *its_dev) +@@ -3469,7 +3519,13 @@ static void its_free_device(struct its_device *its_dev) list_del(&its_dev->entry); raw_spin_unlock_irqrestore(&its_dev->its->lock, flags); kfree(its_dev->event_map.col_map); @@ -177,7 +177,7 @@ index 40ebf1726393..eb6ca4504a27 100644 kfree(its_dev); } -@@ -5098,6 +5154,7 @@ static int __init its_probe_one(struct its_node *its) +@@ -5078,6 +5134,7 @@ static int __init its_probe_one(struct its_node *its) struct page *page; u32 ctlr; int err; @@ -185,7 +185,7 @@ index 40ebf1726393..eb6ca4504a27 100644 its_enable_quirks(its); -@@ -5131,7 +5188,10 @@ static int __init its_probe_one(struct its_node *its) +@@ -5111,7 +5168,10 @@ static int __init its_probe_one(struct its_node *its) } } @@ -197,7 +197,7 @@ index 40ebf1726393..eb6ca4504a27 100644 get_order(ITS_CMD_QUEUE_SZ)); if (!page) { err = -ENOMEM; -@@ -5160,6 +5220,11 @@ static int __init its_probe_one(struct its_node *its) +@@ -5140,6 +5200,11 @@ static int __init its_probe_one(struct its_node *its) if (its->flags & ITS_FLAGS_FORCE_NON_SHAREABLE) tmp &= ~GITS_CBASER_SHAREABILITY_MASK; diff --git a/patch/kernel/rockchip-rk3588-edge/0012-fix-initial-PERST-GPIO-value.patch b/patch/kernel/rockchip-rk3588-edge/0012-fix-initial-PERST-GPIO-value.patch index 68750e1ba7ff..8212b6261b87 100644 --- a/patch/kernel/rockchip-rk3588-edge/0012-fix-initial-PERST-GPIO-value.patch +++ b/patch/kernel/rockchip-rk3588-edge/0012-fix-initial-PERST-GPIO-value.patch @@ -13,7 +13,7 @@ Subject: [ARCHEOLOGY] Fix PCIe for RK35xx+Fix ROCK5A PCIe device tree 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c -index d6842141d384..a909e42b4273 100644 +index 111111111111..222222222222 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -240,7 +240,7 @@ static int rockchip_pcie_resource_get(struct platform_device *pdev, diff --git a/patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch b/patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch index 5341704bdba5..cd61b6a9354d 100644 --- a/patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch +++ b/patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch @@ -21,7 +21,7 @@ Signed-off-by: Alexey Charkov 1 file changed, 147 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 6ac5ac8b48ab..ef06c1f742e8 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -10,6 +10,7 @@ @@ -213,7 +213,7 @@ Signed-off-by: Alexey Charkov 8 files changed, 32 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts -index 98c622b27647..c667704ba985 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts @@ -673,6 +673,10 @@ regulator-state-mem { @@ -228,7 +228,7 @@ index 98c622b27647..c667704ba985 100644 status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi -index 709d348cf06b..03fd193be253 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-edgeble-neu6a-common.dtsi @@ -466,3 +466,7 @@ regulator-state-mem { @@ -240,7 +240,7 @@ index 709d348cf06b..03fd193be253 100644 + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts -index 7be2190244ba..7c3696a3ad3a 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts @@ -1131,6 +1131,10 @@ &sata0 { @@ -255,7 +255,7 @@ index 7be2190244ba..7c3696a3ad3a 100644 status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts b/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts -index 009566d881f3..230e630820b4 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-ok3588-c.dts @@ -376,6 +376,10 @@ &sdmmc { @@ -270,7 +270,7 @@ index 009566d881f3..230e630820b4 100644 status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index b8e15b76a8a6..21e96c212dd8 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts @@ -742,6 +742,10 @@ regulator-state-mem { @@ -285,7 +285,7 @@ index b8e15b76a8a6..21e96c212dd8 100644 pinctrl-0 = <&uart2m0_xfer>; status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts -index 9090c5c99f2a..d0021524e7f9 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dts @@ -648,6 +648,10 @@ regulator-state-mem { @@ -300,7 +300,7 @@ index 9090c5c99f2a..d0021524e7f9 100644 status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi -index 6b9206ce4a03..77bcf0f6b028 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi @@ -601,6 +601,10 @@ regulator-state-mem { @@ -315,7 +315,7 @@ index 6b9206ce4a03..77bcf0f6b028 100644 pinctrl-0 = <&uart2m0_xfer>; status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -index 8e2a07612d17..c671a61d3aef 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts @@ -697,6 +697,10 @@ regulator-state-mem { @@ -346,7 +346,7 @@ Signed-off-by: Alexey Charkov 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index ef06c1f742e8..57c2d998ae75 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -2487,17 +2487,29 @@ center_crit: center-crit { @@ -412,7 +412,7 @@ Signed-off-by: Alexey Charkov 2 files changed, 24 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts -index 7c3696a3ad3a..00f660d50127 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts @@ -878,6 +878,8 @@ regulators { @@ -470,7 +470,7 @@ index 7c3696a3ad3a..00f660d50127 100644 regulator-max-microvolt = <950000>; regulator-ramp-delay = <12500>; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts -index b4f22d95ac0e..baeb08d665c7 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts @@ -832,6 +832,8 @@ vdd_cpu_big1_s0: dcdc-reg1 { @@ -565,7 +565,7 @@ Signed-off-by: Alexey Charkov 1 file changed, 122 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 57c2d998ae75..85c25d5efdad 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -97,6 +97,7 @@ cpu_l0: cpu@0 { diff --git a/patch/kernel/rockchip-rk3588-edge/0024-RK3588-Add-Crypto-Support.patch b/patch/kernel/rockchip-rk3588-edge/0024-RK3588-Add-Crypto-Support.patch index 665f6ef9da98..e11ce51920bc 100644 --- a/patch/kernel/rockchip-rk3588-edge/0024-RK3588-Add-Crypto-Support.patch +++ b/patch/kernel/rockchip-rk3588-edge/0024-RK3588-Add-Crypto-Support.patch @@ -13,7 +13,7 @@ Signed-off-by: Corentin Labbe diff --git a/Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml b/Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml new file mode 100644 -index 000000000000..c01963413260 +index 000000000000..111111111111 --- /dev/null +++ b/Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml @@ -0,0 +1,65 @@ @@ -99,7 +99,7 @@ Signed-off-by: Corentin Labbe 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 85c25d5efdad..8a2eb9013fe0 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -1923,6 +1923,18 @@ sdhci: mmc@fe2e0000 { @@ -139,7 +139,7 @@ Signed-off-by: Corentin Labbe 1 file changed, 12 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi -index d8543b5557ee..5ec449aebc12 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi @@ -1112,6 +1112,18 @@ sdhci: mmc@fe310000 { @@ -182,7 +182,7 @@ Signed-off-by: Corentin Labbe 2 files changed, 34 insertions(+), 76 deletions(-) diff --git a/drivers/clk/rockchip/rst-rk3588.c b/drivers/clk/rockchip/rst-rk3588.c -index c4ebc01f1c9c..7a856de64d9e 100644 +index 111111111111..222222222222 100644 --- a/drivers/clk/rockchip/rst-rk3588.c +++ b/drivers/clk/rockchip/rst-rk3588.c @@ -16,9 +16,6 @@ @@ -242,7 +242,7 @@ index c4ebc01f1c9c..7a856de64d9e 100644 void rk3588_rst_init(struct device_node *np, void __iomem *reg_base) diff --git a/include/dt-bindings/reset/rockchip,rk3588-cru.h b/include/dt-bindings/reset/rockchip,rk3588-cru.h -index e2fe4bd5f7f0..b74f1046f5a5 100644 +index 111111111111..222222222222 100644 --- a/include/dt-bindings/reset/rockchip,rk3588-cru.h +++ b/include/dt-bindings/reset/rockchip,rk3588-cru.h @@ -716,40 +716,40 @@ @@ -342,7 +342,7 @@ Signed-off-by: Corentin Labbe 6 files changed, 1939 insertions(+) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig -index 94f23c6fc93b..95d700c88161 100644 +index 111111111111..222222222222 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -653,6 +653,35 @@ config CRYPTO_DEV_TEGRA @@ -382,7 +382,7 @@ index 94f23c6fc93b..95d700c88161 100644 tristate "Support for Xilinx ZynqMP AES hw accelerator" depends on ZYNQMP_FIRMWARE || COMPILE_TEST diff --git a/drivers/crypto/rockchip/Makefile b/drivers/crypto/rockchip/Makefile -index 785277aca71e..452a12ff6538 100644 +index 111111111111..222222222222 100644 --- a/drivers/crypto/rockchip/Makefile +++ b/drivers/crypto/rockchip/Makefile @@ -3,3 +3,8 @@ obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rk_crypto.o @@ -396,7 +396,7 @@ index 785277aca71e..452a12ff6538 100644 + rk2_crypto_ahash.o diff --git a/drivers/crypto/rockchip/rk2_crypto.c b/drivers/crypto/rockchip/rk2_crypto.c new file mode 100644 -index 000000000000..79ed697d8ec5 +index 000000000000..111111111111 --- /dev/null +++ b/drivers/crypto/rockchip/rk2_crypto.c @@ -0,0 +1,739 @@ @@ -1141,7 +1141,7 @@ index 000000000000..79ed697d8ec5 +MODULE_AUTHOR("Corentin Labbe "); diff --git a/drivers/crypto/rockchip/rk2_crypto.h b/drivers/crypto/rockchip/rk2_crypto.h new file mode 100644 -index 000000000000..59cd8be59f70 +index 000000000000..111111111111 --- /dev/null +++ b/drivers/crypto/rockchip/rk2_crypto.h @@ -0,0 +1,246 @@ @@ -1393,7 +1393,7 @@ index 000000000000..59cd8be59f70 +void rk2_hash_exit_tfm(struct crypto_ahash *tfm); diff --git a/drivers/crypto/rockchip/rk2_crypto_ahash.c b/drivers/crypto/rockchip/rk2_crypto_ahash.c new file mode 100644 -index 000000000000..75b8d9893447 +index 000000000000..111111111111 --- /dev/null +++ b/drivers/crypto/rockchip/rk2_crypto_ahash.c @@ -0,0 +1,344 @@ @@ -1743,7 +1743,7 @@ index 000000000000..75b8d9893447 +} diff --git a/drivers/crypto/rockchip/rk2_crypto_skcipher.c b/drivers/crypto/rockchip/rk2_crypto_skcipher.c new file mode 100644 -index 000000000000..3e8e44d84b47 +index 000000000000..111111111111 --- /dev/null +++ b/drivers/crypto/rockchip/rk2_crypto_skcipher.c @@ -0,0 +1,576 @@ diff --git a/patch/kernel/rockchip-rk3588-edge/0025-RK3588-Add-HW-RNG-Support.patch b/patch/kernel/rockchip-rk3588-edge/0025-RK3588-Add-HW-RNG-Support.patch index 437820b73940..92a0d755f3dd 100644 --- a/patch/kernel/rockchip-rk3588-edge/0025-RK3588-Add-HW-RNG-Support.patch +++ b/patch/kernel/rockchip-rk3588-edge/0025-RK3588-Add-HW-RNG-Support.patch @@ -10,7 +10,7 @@ Subject: hwrng: rockchip: Add support for Rockchip HW RNG 3 files changed, 588 insertions(+) diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index 442c40efb200..11063cac5b36 100644 +index 111111111111..222222222222 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -538,6 +538,19 @@ config HW_RANDOM_XIPHERA @@ -34,7 +34,7 @@ index 442c40efb200..11063cac5b36 100644 tristate "Arm SMCCC TRNG firmware interface support" depends on HAVE_ARM_SMCCC_DISCOVERY diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile -index 32549a1186dc..fd3bbf6e08e1 100644 +index 111111111111..222222222222 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o @@ -47,7 +47,7 @@ index 32549a1186dc..fd3bbf6e08e1 100644 obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o diff --git a/drivers/char/hw_random/rockchip-rng.c b/drivers/char/hw_random/rockchip-rng.c new file mode 100644 -index 000000000000..f7a3a7f52cca +index 000000000000..111111111111 --- /dev/null +++ b/drivers/char/hw_random/rockchip-rng.c @@ -0,0 +1,574 @@ @@ -638,7 +638,7 @@ Subject: arm64: dts: Add HW RNG support to RK3588S 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 8a2eb9013fe0..dab4a518227d 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -1935,6 +1935,16 @@ crypto: crypto@fe370000 { diff --git a/patch/kernel/rockchip-rk3588-edge/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch b/patch/kernel/rockchip-rk3588-edge/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch index 23adfbafe052..b8a394db537d 100644 --- a/patch/kernel/rockchip-rk3588-edge/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch +++ b/patch/kernel/rockchip-rk3588-edge/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch @@ -11,7 +11,7 @@ Signed-off-by: Cristian Ciocaltea 1 file changed, 55 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index dab4a518227d..3df7724d1ca6 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -1414,6 +1414,61 @@ i2s9_8ch: i2s@fddfc000 { diff --git a/patch/kernel/rockchip-rk3588-edge/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch b/patch/kernel/rockchip-rk3588-edge/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch index 3baf12b4906a..a8e80fae127f 100644 --- a/patch/kernel/rockchip-rk3588-edge/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch +++ b/patch/kernel/rockchip-rk3588-edge/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch @@ -10,7 +10,7 @@ missing #clock-cells property. 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 3df7724d1ca6..81bcdc31a70b 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -2883,6 +2883,7 @@ hdptxphy_hdmi0: phy@fed60000 { diff --git a/patch/kernel/rockchip-rk3588-edge/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch b/patch/kernel/rockchip-rk3588-edge/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch index b8aacb1acae6..edcf535b204f 100644 --- a/patch/kernel/rockchip-rk3588-edge/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch +++ b/patch/kernel/rockchip-rk3588-edge/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch @@ -18,7 +18,7 @@ Signed-off-by: Cristian Ciocaltea 1 file changed, 431 insertions(+), 3 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c -index 946c01210ac8..44acea3f86af 100644 +index 111111111111..222222222222 100644 --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c @@ -190,6 +190,12 @@ diff --git a/patch/kernel/rockchip-rk3588-edge/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch b/patch/kernel/rockchip-rk3588-edge/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch index 45e9c4ee5865..43173de65136 100644 --- a/patch/kernel/rockchip-rk3588-edge/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch +++ b/patch/kernel/rockchip-rk3588-edge/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch @@ -16,7 +16,7 @@ Signed-off-by: Cristian Ciocaltea 1 file changed, 143 insertions(+), 5 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c -index 44acea3f86af..a3ac4f3835bc 100644 +index 111111111111..222222222222 100644 --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c @@ -8,6 +8,7 @@ diff --git a/patch/kernel/rockchip-rk3588-edge/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch b/patch/kernel/rockchip-rk3588-edge/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch index 515472482cd8..ca6f5d4b6ffc 100644 --- a/patch/kernel/rockchip-rk3588-edge/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch +++ b/patch/kernel/rockchip-rk3588-edge/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch @@ -19,7 +19,7 @@ Signed-off-by: Cristian Ciocaltea 1 file changed, 552 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c -index 62ebbdb16253..86d2c15af39f 100644 +index 111111111111..222222222222 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -5,6 +5,8 @@ diff --git a/patch/kernel/rockchip-rk3588-edge/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch b/patch/kernel/rockchip-rk3588-edge/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch index 54d40a76714c..7174475bea6d 100644 --- a/patch/kernel/rockchip-rk3588-edge/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch +++ b/patch/kernel/rockchip-rk3588-edge/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch @@ -8,7 +8,7 @@ Subject: arm64: dts: rockchip: rk3588: add VDPU and RGA2 nodes 1 file changed, 32 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -index 81bcdc31a70b..e7d36a0a2347 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi @@ -726,6 +726,38 @@ mmu600_php: iommu@fcb00000 { diff --git a/patch/kernel/rockchip-rk3588-edge/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch b/patch/kernel/rockchip-rk3588-edge/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch index 1e80d2615bf6..c4994f7d9164 100644 --- a/patch/kernel/rockchip-rk3588-edge/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch +++ b/patch/kernel/rockchip-rk3588-edge/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch @@ -18,7 +18,7 @@ Signed-off-by: Cristian Ciocaltea 7 files changed, 6102 insertions(+), 66 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile -index ce715562e9e5..8354e4879f70 100644 +index 111111111111..222222222222 100644 --- a/drivers/gpu/drm/bridge/synopsys/Makefile +++ b/drivers/gpu/drm/bridge/synopsys/Makefile @@ -1,5 +1,5 @@ @@ -30,7 +30,7 @@ index ce715562e9e5..8354e4879f70 100644 obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c new file mode 100644 -index 000000000000..8817ef9a9de9 +index 000000000000..111111111111 --- /dev/null +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -0,0 +1,2401 @@ @@ -2437,7 +2437,7 @@ index 000000000000..8817ef9a9de9 +MODULE_ALIAS("platform:dw-hdmi-qp"); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h new file mode 100644 -index 000000000000..4cac70f2d11d +index 000000000000..111111111111 --- /dev/null +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h @@ -0,0 +1,831 @@ @@ -3273,10 +3273,10 @@ index 000000000000..4cac70f2d11d + +#endif /* __DW_HDMI_QP_H__ */ diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index aca5bb0866f8..b2338e567290 100644 +index 111111111111..222222222222 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -162,6 +162,8 @@ struct dw_hdmi { +@@ -163,6 +163,8 @@ struct dw_hdmi { void __iomem *regs; bool sink_is_hdmi; bool sink_has_audio; @@ -3285,7 +3285,7 @@ index aca5bb0866f8..b2338e567290 100644 struct pinctrl *pinctrl; struct pinctrl_state *default_state; -@@ -254,6 +256,25 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, +@@ -255,6 +257,25 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, hdmi_modb(hdmi, data << shift, mask, reg); } @@ -3311,7 +3311,7 @@ index aca5bb0866f8..b2338e567290 100644 static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi) { hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL, -@@ -2531,6 +2552,45 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, +@@ -2539,6 +2560,45 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, return 0; } @@ -3357,7 +3357,7 @@ index aca5bb0866f8..b2338e567290 100644 static void dw_hdmi_connector_force(struct drm_connector *connector) { struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, -@@ -3682,6 +3742,35 @@ void dw_hdmi_unbind(struct dw_hdmi *hdmi) +@@ -3668,6 +3728,35 @@ void dw_hdmi_unbind(struct dw_hdmi *hdmi) } EXPORT_SYMBOL_GPL(dw_hdmi_unbind); @@ -3394,7 +3394,7 @@ index aca5bb0866f8..b2338e567290 100644 { dw_hdmi_init_hw(hdmi); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h -index af43a0414b78..8ebdec7254f2 100644 +index 111111111111..222222222222 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h @@ -851,6 +851,10 @@ enum { @@ -3409,7 +3409,7 @@ index af43a0414b78..8ebdec7254f2 100644 HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10, HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1, diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c -index fe33092abbe7..a5d1a70d9b98 100644 +index 111111111111..222222222222 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -4,21 +4,32 @@ @@ -6425,7 +6425,7 @@ index fe33092abbe7..a5d1a70d9b98 100644 .name = "dwhdmi-rockchip", .pm = &dw_hdmi_rockchip_pm, diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h -index 6a46baa0737c..ac4e418c1c4e 100644 +index 111111111111..222222222222 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -6,12 +6,14 @@ @@ -6613,3 +6613,4 @@ index 6a46baa0737c..ac4e418c1c4e 100644 -- Armbian + diff --git a/patch/kernel/rockchip-rk3588-edge/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch b/patch/kernel/rockchip-rk3588-edge/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch index 86e442b47a45..4c0ad9def237 100644 --- a/patch/kernel/rockchip-rk3588-edge/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch +++ b/patch/kernel/rockchip-rk3588-edge/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ColorfulRhino +From: ColorfulRhino Date: Wed, 12 Jun 2024 12:17:18 +0200 Subject: Fix HDMI controller patch at drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -9,12 +9,10 @@ Subject: Fix HDMI controller patch at 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c -index 8817ef9a9de9..324dee775651 100644 +index 111111111111..222222222222 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c -@@ -3,10 +3,11 @@ - * Copyright (C) Rockchip Electronics Co.Ltd - * Author: +@@ -5,6 +5,7 @@ * Algea Cao */ #include @@ -22,8 +20,6 @@ index 8817ef9a9de9..324dee775651 100644 #include #include #include - #include - #include -- -Created with Armbian build tools https://github.com/armbian/build +Armbian diff --git a/patch/kernel/rockchip-rk3588-edge/0801-wireless-add-bcm43752.patch b/patch/kernel/rockchip-rk3588-edge/0801-wireless-add-bcm43752.patch index ab51f8846d53..0085fdff2805 100644 --- a/patch/kernel/rockchip-rk3588-edge/0801-wireless-add-bcm43752.patch +++ b/patch/kernel/rockchip-rk3588-edge/0801-wireless-add-bcm43752.patch @@ -13,7 +13,7 @@ Signed-off-by: Ondrej Jirman 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c -index 06698a714b52..0ecd19c655e3 100644 +index 111111111111..222222222222 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -70,6 +70,7 @@ BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie"); @@ -50,7 +50,7 @@ index 06698a714b52..0ecd19c655e3 100644 BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC), BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC), diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -index 44684bf1b9ac..c1e22c589d85 100644 +index 111111111111..222222222222 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h @@ -52,6 +52,7 @@ diff --git a/patch/kernel/rockchip-rk3588-edge/0802-wireless-add-clk-property.patch b/patch/kernel/rockchip-rk3588-edge/0802-wireless-add-clk-property.patch index 1aba98f99dcb..193f9892bbe2 100644 --- a/patch/kernel/rockchip-rk3588-edge/0802-wireless-add-clk-property.patch +++ b/patch/kernel/rockchip-rk3588-edge/0802-wireless-add-clk-property.patch @@ -12,7 +12,7 @@ Signed-off-by: Ondrej Jirman 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c -index 0ecd19c655e3..add317731126 100644 +index 111111111111..222222222222 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -3,6 +3,7 @@ diff --git a/patch/kernel/rockchip-rk3588-edge/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch b/patch/kernel/rockchip-rk3588-edge/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch index 5b049aec57df..ed7d4f3f3e4a 100644 --- a/patch/kernel/rockchip-rk3588-edge/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch +++ b/patch/kernel/rockchip-rk3588-edge/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch @@ -8,7 +8,7 @@ Subject: arm64: dts: rock-5b: Slow down emmc to hs200 and add tsadc node 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index 21e96c212dd8..fccd71c37749 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts @@ -371,8 +371,7 @@ &sdhci { diff --git a/patch/kernel/rockchip-rk3588-edge/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch b/patch/kernel/rockchip-rk3588-edge/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch index 2908da69fd25..22a681873e76 100644 --- a/patch/kernel/rockchip-rk3588-edge/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch +++ b/patch/kernel/rockchip-rk3588-edge/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch @@ -10,7 +10,7 @@ Signed-off-by: lanefu 1 file changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index fccd71c37749..c02a6b41f071 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts @@ -420,6 +420,33 @@ &uart6 { diff --git a/patch/kernel/rockchip-rk3588-edge/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch b/patch/kernel/rockchip-rk3588-edge/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch index 503a51bec0a0..da741a15b666 100644 --- a/patch/kernel/rockchip-rk3588-edge/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch +++ b/patch/kernel/rockchip-rk3588-edge/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch @@ -11,7 +11,7 @@ Signed-off-by: Cristian Ciocaltea 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index c02a6b41f071..745ed06e9bb1 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts @@ -4,6 +4,7 @@ diff --git a/patch/kernel/rockchip-rk3588-edge/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch b/patch/kernel/rockchip-rk3588-edge/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch index ddd40972524d..3361d1475e07 100644 --- a/patch/kernel/rockchip-rk3588-edge/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch +++ b/patch/kernel/rockchip-rk3588-edge/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch @@ -21,7 +21,7 @@ Signed-off-by: Cristian Ciocaltea 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index 745ed06e9bb1..726da087fc4a 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts @@ -186,6 +186,11 @@ &gpu { diff --git a/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch b/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch index 9b4da1b0fa5f..994755002207 100644 --- a/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch +++ b/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch @@ -16,7 +16,7 @@ Signed-off-by: Alexey Charkov 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts -index 726da087fc4a..f7dc7572e3ea 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts @@ -53,7 +53,7 @@ led_rgb_b { diff --git a/patch/kernel/rockchip-rk3588-edge/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch b/patch/kernel/rockchip-rk3588-edge/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch index 49b9268a3311..6933509af3d1 100644 --- a/patch/kernel/rockchip-rk3588-edge/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch +++ b/patch/kernel/rockchip-rk3588-edge/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch @@ -8,7 +8,7 @@ Subject: Add HDMI and VOP2 to Rock 5A 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -index c671a61d3aef..56f385d31f21 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts @@ -5,6 +5,7 @@ diff --git a/patch/kernel/rockchip-rk3588-edge/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch b/patch/kernel/rockchip-rk3588-edge/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch index dabd54888c3f..7c4e2fc30660 100644 --- a/patch/kernel/rockchip-rk3588-edge/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch +++ b/patch/kernel/rockchip-rk3588-edge/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch @@ -8,7 +8,7 @@ Subject: arch: arm64: dts: enable gpu node for rock-5a 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -index 56f385d31f21..4f8e7a16d349 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts @@ -281,6 +281,11 @@ &gmac1_rgmii_clk diff --git a/patch/kernel/rockchip-rk3588-edge/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch b/patch/kernel/rockchip-rk3588-edge/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch index 92d736198339..1a45203a1890 100644 --- a/patch/kernel/rockchip-rk3588-edge/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch +++ b/patch/kernel/rockchip-rk3588-edge/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch @@ -8,7 +8,7 @@ Subject: arm64: dts: Add missing nodes to Orange Pi 5 Plus 1 file changed, 181 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts -index 1a604429fb26..939179c5b93b 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts @@ -10,6 +10,7 @@ diff --git a/patch/kernel/rockchip-rk3588-edge/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch b/patch/kernel/rockchip-rk3588-edge/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch index f993a486b42f..c68459f6cd76 100644 --- a/patch/kernel/rockchip-rk3588-edge/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch +++ b/patch/kernel/rockchip-rk3588-edge/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch @@ -8,7 +8,7 @@ Subject: arm64: dts: rockchip: support poweroff on rock-5a 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -index 4f8e7a16d349..23a9a160bb52 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts @@ -400,6 +400,8 @@ pmic@0 { diff --git a/patch/kernel/rockchip-rk3588-edge/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch b/patch/kernel/rockchip-rk3588-edge/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch index a4ba348c31f8..bd33b5976c41 100644 --- a/patch/kernel/rockchip-rk3588-edge/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch +++ b/patch/kernel/rockchip-rk3588-edge/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch @@ -8,7 +8,7 @@ Subject: arm64: dts: rockchip: add PCIe for M.2 E-Key to rock-5a 1 file changed, 9 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts -index 23a9a160bb52..daefce00446d 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts @@ -115,6 +115,10 @@ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { diff --git a/patch/kernel/rockchip-rk3588-edge/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch b/patch/kernel/rockchip-rk3588-edge/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch index 95a4aecb9a78..8ee172545f55 100644 --- a/patch/kernel/rockchip-rk3588-edge/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch +++ b/patch/kernel/rockchip-rk3588-edge/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch @@ -8,7 +8,7 @@ Subject: arm64: dts: rockchip: Add HDMI support to ArmSoM Sige7 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts -index c667704ba985..fdd0cdb389d7 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts @@ -4,6 +4,7 @@ diff --git a/patch/kernel/rockchip-rk3588-edge/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch b/patch/kernel/rockchip-rk3588-edge/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch index 3ec6f2d5d414..a57707485c0e 100644 --- a/patch/kernel/rockchip-rk3588-edge/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch +++ b/patch/kernel/rockchip-rk3588-edge/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch @@ -8,7 +8,7 @@ Subject: arm64: dts: rockchip: Add ap6275p wireless support to ArmSoM Sige7 1 file changed, 16 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts -index fdd0cdb389d7..698120e224fe 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-armsom-sige7.dts @@ -283,6 +283,22 @@ &pcie2x1l0 { diff --git a/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch b/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch index 24e0d0f8bca4..feb3f1838c84 100644 --- a/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch +++ b/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch @@ -9,7 +9,7 @@ Subject: mfd: khadas-mcu: add Edge2 registers 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c -index ba981a788692..21c4cd46f41c 100644 +index 111111111111..222222222222 100644 --- a/drivers/mfd/khadas-mcu.c +++ b/drivers/mfd/khadas-mcu.c @@ -26,6 +26,10 @@ static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg) @@ -33,7 +33,7 @@ index ba981a788692..21c4cd46f41c 100644 }; diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h -index a99ba2ed0e4e..63bc9bf76661 100644 +index 111111111111..222222222222 100644 --- a/include/linux/mfd/khadas-mcu.h +++ b/include/linux/mfd/khadas-mcu.h @@ -35,26 +35,45 @@ @@ -114,7 +114,7 @@ Subject: mfd: khadas-mcu: drop unused code 1 file changed, 11 deletions(-) diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c -index 21c4cd46f41c..91da966dedf4 100644 +index 111111111111..222222222222 100644 --- a/drivers/mfd/khadas-mcu.c +++ b/drivers/mfd/khadas-mcu.c @@ -84,10 +84,6 @@ static struct mfd_cell khadas_mcu_fan_cells[] = { @@ -155,7 +155,7 @@ Subject: thermal: khadas_mcu_fan: add support for Khadas Edge 2 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c -index d35e5313bea4..e495e562c346 100644 +index 111111111111..222222222222 100644 --- a/drivers/thermal/khadas_mcu_fan.c +++ b/drivers/thermal/khadas_mcu_fan.c @@ -15,10 +15,16 @@ @@ -295,7 +295,7 @@ Subject: dt-bindings: mfd: khadas-mcu: add cooling-levels property 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml -index 084960fd5a1f..cf46b690010f 100644 +index 111111111111..222222222222 100644 --- a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml +++ b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml @@ -11,7 +11,7 @@ maintainers: @@ -332,7 +332,7 @@ Subject: arm64: dts: rockchip: Add MCU to Khadas Edge 2 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index dbddfc3bb464..4c1fa21ee8e7 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts @@ -231,6 +231,13 @@ hym8563: rtc@51 { @@ -362,7 +362,7 @@ Subject: arm64: dts: rockchip: Add automatic fan control to Khadas Edge 2 1 file changed, 56 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -index 4c1fa21ee8e7..dcd9a81cc39e 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts @@ -240,6 +240,62 @@ khadas_mcu: system-controller@18 { From 117b6fe997c307f28d6bbd9cbf04292361ff7c84 Mon Sep 17 00:00:00 2001 From: Ricardo Pardini Date: Thu, 6 Jun 2024 23:02:54 +0200 Subject: [PATCH 33/53] rockchip-rk3588/edge: nanopct6: Add NanoPC T6 SPI Flash (6.10-rc2 version) --- ...dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 patch/kernel/rockchip-rk3588-edge/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch b/patch/kernel/rockchip-rk3588-edge/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch new file mode 100644 index 000000000000..71955ebcdd19 --- /dev/null +++ b/patch/kernel/rockchip-rk3588-edge/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ricardo Pardini +Date: Thu, 6 Jun 2024 23:00:05 +0200 +Subject: arm64: dts: rockchip: Add NanoPC T6 SPI Flash + +Signed-off-by: Ricardo Pardini +--- + arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts | 14 ++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts +index ad8e36a339dc4..2085e73a44642 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts +@@ -569,20 +569,34 @@ &sdmmc { + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + no-mmc; + no-sdio; + sd-uhs-sdr104; + vmmc-supply = <&vcc3v3_sd_s0>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; + }; + ++&sfc { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&fspim1_pins>; ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0x0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ spi-tx-bus-width = <1>; ++ }; ++}; ++ + &spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + num-cs = <1>; + + pmic@0 { + compatible = "rockchip,rk806"; +-- +Armbian + From a6b5ea7950092175927ad94e95e97a1be4c815fa Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Wed, 12 Jun 2024 13:22:15 +0200 Subject: [PATCH 34/53] rk3588: Introduce `current` kernel branch Since the `edge` kernel branch often uses RC kernels, introduce a more stable `current` branch. This branch should not be RC kernels and it also should move to an LTS kernel once released. --- .../kernel/linux-rockchip-rk3588-6.8.config | 10893 +++++++++++ config/sources/families/rockchip-rk3588.conf | 11 +- .../0000.patching_config.yaml | 46 + .../0001-general-add-overlay-support.patch | 84 + ...Makefile-delete-missing-cgroup_clean.patch | 34 + .../0010-fix-clk-divisions.patch | 142 + .../0011-irqchip-fix-its-timeout-issue.patch | 214 + .../0021-RK3588-Add-USB3-DRD-Support.patch | 2602 +++ .../0022-RK3588-Add-Cpufreq-Support.patch | 626 + .../0024-RK3588-Add-Crypto-Support.patch | 2327 +++ .../0025-RK3588-Add-HW-RNG-Support.patch | 663 + ...dd-Samsung-HDMI-eDP-Combo-PHY-driver.patch | 1091 ++ ...dts-rockchip-Add-HDMI0-PHY-to-rk3588.patch | 54 + ...sys-Add-initial-support-for-DW-HDMI-.patch | 6616 +++++++ ...-rockchip-Add-HDMI0-bridge-to-rk3588.patch | 81 + ...ip-Enable-HDMI0-PHY-clk-provider-on-.patch | 26 + .../rockchip-rk3588-6.8/0141-panthor-v6.patch | 14855 ++++++++++++++++ ...64-dts-rockchip-rk3588-Add-GPU-nodes.patch | 151 + ...p-samsung-hdptx-Add-FRL-EARC-support.patch | 549 + ...hip-samsung-hdptx-Add-clock-provider.patch | 222 + ...2-Improve-display-modes-handling-on-.patch | 679 + ...kchip-rk3588-add-VDPU-and-RGA2-nodes.patch | 55 + .../0801-wireless-add-bcm43752.patch | 74 + .../0802-wireless-add-clk-property.patch | 51 + ...b-Slow-down-emmc-to-hs200-and-add-ts.patch | 37 + ...d-rock-5b-arm64-dts-enable-spi-flash.patch | 52 + ...dts-rockchip-Enable-HDMI0-on-rock-5b.patch | 67 + ...-rockchip-rk3588-rock5b-Add-GPU-node.patch | 38 + ...-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch | 41 + .../1020-Add-HDMI-and-VOP2-to-Rock-5A.patch | 57 + ...rm64-dts-enable-gpu-node-for-rock-5a.patch | 36 + ...dd-missing-nodes-to-Orange-Pi-5-Plus.patch | 265 + ...rockchip-support-poweroff-on-rock-5a.patch | 25 + ...ip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch | 39 + ...031-Add-missing-nodes-to-Orange-Pi-5.patch | 318 + .../1040-board-khadas-edge2-add-nodes.patch | 1464 ++ .../1041-board-khadas-edge2-mcu.patch | 441 + .../1047-fix-initial-PERST#-GPIO-value.patch | 30 + .../dt/rk3588-armsom-sige7.dts | 767 + .../dt/rk3588-bananapi-m7.dts | 10 + .../dt/rk3588-hinlink-h88k.dts | 858 + .../dt/rk3588-mixtile-blade3.dts | 712 + .../dt/rk3588-nanopc-cm3588-nas.dts | 1436 ++ .../dt/rk3588s-nanopi-r6c.dts | 19 + .../dt/rk3588s-nanopi-r6s.dts | 863 + .../dt/rk3588s-orangepi-5b.dts | 48 + .../dt/rk3588s-rock-5c.dts | 825 + .../rockchip-rk3588-6.8/overlay/Makefile | 40 + .../overlay/rockchip-rk3588-pwm0-m0.dts | 14 + .../overlay/rockchip-rk3588-pwm0-m1.dts | 13 + .../overlay/rockchip-rk3588-pwm0-m2.dts | 13 + .../overlay/rockchip-rk3588-pwm1-m0.dts | 14 + .../overlay/rockchip-rk3588-pwm1-m1.dts | 13 + .../overlay/rockchip-rk3588-pwm1-m2.dts | 13 + .../overlay/rockchip-rk3588-pwm10-m0.dts | 13 + .../overlay/rockchip-rk3588-pwm11-m0.dts | 13 + .../overlay/rockchip-rk3588-pwm11-m1.dts | 21 + .../overlay/rockchip-rk3588-pwm12-m0.dts | 13 + .../overlay/rockchip-rk3588-pwm13-m0.dts | 13 + .../overlay/rockchip-rk3588-pwm13-m2.dts | 13 + .../overlay/rockchip-rk3588-pwm14-m0.dts | 14 + .../overlay/rockchip-rk3588-pwm14-m1.dts | 14 + .../overlay/rockchip-rk3588-pwm14-m2.dts | 13 + .../overlay/rockchip-rk3588-pwm15-m0.dts | 21 + .../overlay/rockchip-rk3588-pwm15-m1.dts | 13 + .../overlay/rockchip-rk3588-pwm15-m2.dts | 13 + .../overlay/rockchip-rk3588-pwm15-m3.dts | 21 + .../overlay/rockchip-rk3588-pwm2-m1.dts | 21 + .../overlay/rockchip-rk3588-pwm3-m0.dts | 13 + .../overlay/rockchip-rk3588-pwm3-m1.dts | 21 + .../overlay/rockchip-rk3588-pwm3-m2.dts | 13 + .../overlay/rockchip-rk3588-pwm3-m3.dts | 13 + .../overlay/rockchip-rk3588-pwm5-m2.dts | 21 + .../overlay/rockchip-rk3588-pwm6-m0.dts | 21 + .../overlay/rockchip-rk3588-pwm6-m2.dts | 21 + .../overlay/rockchip-rk3588-pwm7-m0.dts | 21 + .../overlay/rockchip-rk3588-pwm7-m3.dts | 21 + .../overlay/rockchip-rk3588-pwm8-m0.dts | 21 + .../overlay/rockchip-rk3588-sata1.dts | 20 + .../overlay/rockchip-rk3588-sata2.dts | 20 + 80 files changed, 51155 insertions(+), 1 deletion(-) create mode 100644 config/kernel/linux-rockchip-rk3588-6.8.config create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0000.patching_config.yaml create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0001-general-add-overlay-support.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0005-tools-Makefile-delete-missing-cgroup_clean.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0010-fix-clk-divisions.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0011-irqchip-fix-its-timeout-issue.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0021-RK3588-Add-USB3-DRD-Support.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0022-RK3588-Add-Cpufreq-Support.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0024-RK3588-Add-Crypto-Support.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0025-RK3588-Add-HW-RNG-Support.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0135-phy-rockchip-Add-Samsung-HDMI-eDP-Combo-PHY-driver.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0136-arm64-dts-rockchip-Add-HDMI0-PHY-to-rk3588.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0137-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0141-panthor-v6.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0142-arm64-dts-rockchip-rk3588-Add-GPU-nodes.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0801-wireless-add-bcm43752.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/0802-wireless-add-clk-property.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1013-arm64-dts-rockchip-rk3588-rock5b-Add-GPU-node.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1031-Add-missing-nodes-to-Orange-Pi-5.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1040-board-khadas-edge2-add-nodes.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1041-board-khadas-edge2-mcu.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1047-fix-initial-PERST#-GPIO-value.patch create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-armsom-sige7.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-bananapi-m7.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-hinlink-h88k.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-mixtile-blade3.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-nanopc-cm3588-nas.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-nanopi-r6c.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-nanopi-r6s.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-orangepi-5b.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-rock-5c.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/Makefile create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m1.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m2.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m1.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m2.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm10-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm11-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm11-m1.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm12-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm13-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm13-m2.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m1.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m2.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m1.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m2.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m3.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm2-m1.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m1.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m2.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m3.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm5-m2.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm6-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm6-m2.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm7-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm7-m3.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm8-m0.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-sata1.dts create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-sata2.dts diff --git a/config/kernel/linux-rockchip-rk3588-6.8.config b/config/kernel/linux-rockchip-rk3588-6.8.config new file mode 100644 index 000000000000..c00a3e1ec484 --- /dev/null +++ b/config/kernel/linux-rockchip-rk3588-6.8.config @@ -0,0 +1,10893 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 6.8.12 Kernel Configuration +# +CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0" +CONFIG_CC_IS_GCC=y +CONFIG_GCC_VERSION=130200 +CONFIG_CLANG_VERSION=0 +CONFIG_AS_IS_GNU=y +CONFIG_AS_VERSION=24200 +CONFIG_LD_IS_BFD=y +CONFIG_LD_VERSION=24200 +CONFIG_LLD_VERSION=0 +CONFIG_CC_CAN_LINK=y +CONFIG_CC_CAN_LINK_STATIC=y +CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y +CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y +CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y +CONFIG_CC_HAS_ASM_INLINE=y +CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y +CONFIG_PAHOLE_VERSION=125 +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_TABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +# CONFIG_COMPILE_TEST is not set +# CONFIG_WERROR is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_BUILD_SALT="" +CONFIG_DEFAULT_INIT="" +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_WATCH_QUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_USELIB=y +CONFIG_AUDIT=y +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +CONFIG_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_INJECTION=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_SIM=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_GENERIC_IRQ_IPI=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_IRQ_MSI_IOMMU=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +# end of IRQ subsystem + +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_TIME_KUNIT_TEST=m +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +# end of Timers subsystem + +CONFIG_BPF=y +CONFIG_HAVE_EBPF_JIT=y +CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y + +# +# BPF subsystem +# +CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT=y +# CONFIG_BPF_JIT_ALWAYS_ON is not set +CONFIG_BPF_JIT_DEFAULT_ON=y +# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set +# CONFIG_BPF_PRELOAD is not set +CONFIG_BPF_LSM=y +# end of BPF subsystem + +CONFIG_PREEMPT_BUILD=y +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_PREEMPTION=y +# CONFIG_PREEMPT_DYNAMIC is not set +CONFIG_SCHED_CORE=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_SCHED_AVG_IRQ=y +CONFIG_SCHED_THERMAL_PRESSURE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +# CONFIG_PSI is not set +# end of CPU/Task time and stats accounting + +CONFIG_CPU_ISOLATION=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +CONFIG_PREEMPT_RCU=y +# CONFIG_RCU_EXPERT is not set +CONFIG_TREE_SRCU=y +CONFIG_TASKS_RCU_GENERIC=y +CONFIG_TASKS_RCU=y +CONFIG_TASKS_TRACE_RCU=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_RCU_NEED_SEGCBLIST=y +# end of RCU Subsystem + +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=m +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +# CONFIG_PRINTK_INDEX is not set +CONFIG_GENERIC_SCHED_CLOCK=y + +# +# Scheduler features +# +# CONFIG_UCLAMP_TASK is not set +# end of Scheduler features + +CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y +CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y +CONFIG_CC_HAS_INT128=y +CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" +CONFIG_GCC10_NO_ARRAY_BOUNDS=y +CONFIG_CC_NO_ARRAY_BOUNDS=y +CONFIG_GCC_NO_STRINGOP_OVERFLOW=y +CONFIG_CC_NO_STRINGOP_OVERFLOW=y +CONFIG_ARCH_SUPPORTS_INT128=y +CONFIG_NUMA_BALANCING=y +CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y +CONFIG_CGROUPS=y +CONFIG_PAGE_COUNTER=y +# CONFIG_CGROUP_FAVOR_DYNMODS is not set +CONFIG_MEMCG=y +CONFIG_MEMCG_KMEM=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_WRITEBACK=y +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_SCHED_MM_CID=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_RDMA=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_HUGETLB=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_BPF=y +CONFIG_CGROUP_MISC=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_SOCK_CGROUP_DATA=y +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_TIME_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_SCHED_AUTOGROUP=y +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_XZ=y +CONFIG_RD_LZO=y +CONFIG_RD_LZ4=y +CONFIG_RD_ZSTD=y +CONFIG_BOOT_CONFIG=y +# CONFIG_BOOT_CONFIG_FORCE is not set +# CONFIG_BOOT_CONFIG_EMBED is not set +CONFIG_INITRAMFS_PRESERVE_MTIME=y +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_LD_ORPHAN_WARN=y +CONFIG_LD_ORPHAN_WARN_LEVEL="warn" +CONFIG_SYSCTL=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +CONFIG_FHANDLE=y +CONFIG_POSIX_TIMERS=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_FUTEX_PI=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_IO_URING=y +CONFIG_ADVISE_SYSCALLS=y +CONFIG_MEMBARRIER=y +CONFIG_KCMP=y +CONFIG_RSEQ=y +# CONFIG_DEBUG_RSEQ is not set +CONFIG_CACHESTAT_SYSCALL=y +# CONFIG_PC104 is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_SELFTEST is not set +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_BASE_RELATIVE=y +CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_GUEST_PERF_EVENTS=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +# end of Kernel Performance Events And Counters + +CONFIG_SYSTEM_DATA_VERIFICATION=y +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y + +# +# Kexec and crash features +# +CONFIG_CRASH_CORE=y +CONFIG_KEXEC_CORE=y +CONFIG_HAVE_IMA_KEXEC=y +CONFIG_KEXEC=y +CONFIG_KEXEC_FILE=y +# CONFIG_KEXEC_SIG is not set +# CONFIG_CRASH_DUMP is not set +# end of Kexec and crash features +# end of General setup + +CONFIG_ARM64=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_CONT_PTE_SHIFT=4 +CONFIG_ARM64_CONT_PMD_SHIFT=4 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=33 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_SMP=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=4 +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y + +# +# Platform selection +# +# CONFIG_ARCH_ACTIONS is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_APPLE is not set +# CONFIG_ARCH_BCM is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_BITMAIN is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SPARX5 is not set +# CONFIG_ARCH_K3 is not set +# CONFIG_ARCH_LG1K is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_KEEMBAY is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MVEBU is not set +# CONFIG_ARCH_NXP is not set +# CONFIG_ARCH_MA35 is not set +# CONFIG_ARCH_NPCM is not set +# CONFIG_ARCH_PENSANDO is not set +# CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_REALTEK is not set +# CONFIG_ARCH_RENESAS is not set +CONFIG_ARCH_ROCKCHIP=y +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_INTEL_SOCFPGA is not set +# CONFIG_ARCH_STM32 is not set +# CONFIG_ARCH_SYNQUACER is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_THUNDER2 is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_VISCONTI is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set +# end of Platform selection + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +CONFIG_AMPERE_ERRATUM_AC03_CPU_38=y +CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y +CONFIG_ARM64_ERRATUM_826319=y +CONFIG_ARM64_ERRATUM_827319=y +CONFIG_ARM64_ERRATUM_824069=y +CONFIG_ARM64_ERRATUM_819472=y +CONFIG_ARM64_ERRATUM_832075=y +CONFIG_ARM64_ERRATUM_834220=y +CONFIG_ARM64_ERRATUM_1742098=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_ERRATUM_1024718=y +CONFIG_ARM64_ERRATUM_1418040=y +CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y +CONFIG_ARM64_ERRATUM_1165522=y +CONFIG_ARM64_ERRATUM_1319367=y +CONFIG_ARM64_ERRATUM_1530923=y +CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y +CONFIG_ARM64_ERRATUM_2441007=y +CONFIG_ARM64_ERRATUM_1286807=y +CONFIG_ARM64_ERRATUM_1463225=y +CONFIG_ARM64_ERRATUM_1542419=y +CONFIG_ARM64_ERRATUM_1508412=y +CONFIG_ARM64_ERRATUM_2051678=y +CONFIG_ARM64_ERRATUM_2077057=y +CONFIG_ARM64_ERRATUM_2658417=y +CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE=y +CONFIG_ARM64_ERRATUM_2054223=y +CONFIG_ARM64_ERRATUM_2067961=y +CONFIG_ARM64_ERRATUM_2441009=y +CONFIG_ARM64_ERRATUM_2457168=y +CONFIG_ARM64_ERRATUM_2645198=y +CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD=y +CONFIG_ARM64_ERRATUM_2966298=y +CONFIG_ARM64_ERRATUM_3117295=y +CONFIG_CAVIUM_ERRATUM_22375=y +CONFIG_CAVIUM_ERRATUM_23144=y +CONFIG_CAVIUM_ERRATUM_23154=y +CONFIG_CAVIUM_ERRATUM_27456=y +CONFIG_CAVIUM_ERRATUM_30115=y +CONFIG_CAVIUM_TX2_ERRATUM_219=y +CONFIG_FUJITSU_ERRATUM_010001=y +CONFIG_HISILICON_ERRATUM_161600802=y +CONFIG_QCOM_FALKOR_ERRATUM_1003=y +CONFIG_QCOM_FALKOR_ERRATUM_1009=y +CONFIG_QCOM_QDF2400_ERRATUM_0065=y +CONFIG_QCOM_FALKOR_ERRATUM_E1041=y +CONFIG_NVIDIA_CARMEL_CNP_ERRATUM=y +CONFIG_ROCKCHIP_ERRATUM_3588001=y +CONFIG_SOCIONEXT_SYNQUACER_PREITS=y +# end of ARM errata workarounds via the alternatives framework + +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_16K_PAGES is not set +# CONFIG_ARM64_64K_PAGES is not set +# CONFIG_ARM64_VA_BITS_39 is not set +CONFIG_ARM64_VA_BITS_48=y +CONFIG_ARM64_VA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PA_BITS=48 +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_CLUSTER=y +CONFIG_SCHED_SMT=y +CONFIG_NR_CPUS=256 +CONFIG_HOTPLUG_CPU=y +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=4 +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +CONFIG_HZ_300=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=300 +CONFIG_SCHED_HRTICK=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_TIME_ACCOUNTING=y +CONFIG_ARCH_SUPPORTS_KEXEC=y +CONFIG_ARCH_SUPPORTS_KEXEC_FILE=y +CONFIG_ARCH_SELECTS_KEXEC_FILE=y +CONFIG_ARCH_SUPPORTS_KEXEC_SIG=y +CONFIG_ARCH_SUPPORTS_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_SUPPORTS_CRASH_DUMP=y +CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION=y +CONFIG_TRANS_TABLE=y +CONFIG_XEN_DOM0=y +CONFIG_XEN=y +CONFIG_ARCH_FORCE_MAX_ORDER=10 +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +# CONFIG_ARM64_SW_TTBR0_PAN is not set +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_COMPAT=y +CONFIG_KUSER_HELPERS=y +CONFIG_COMPAT_ALIGNMENT_FIXUPS=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y + +# +# ARMv8.1 architectural features +# +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_PAN=y +CONFIG_AS_HAS_LSE_ATOMICS=y +CONFIG_ARM64_LSE_ATOMICS=y +CONFIG_ARM64_USE_LSE_ATOMICS=y +# end of ARMv8.1 architectural features + +# +# ARMv8.2 architectural features +# +CONFIG_AS_HAS_ARMV8_2=y +CONFIG_AS_HAS_SHA3=y +# CONFIG_ARM64_PMEM is not set +CONFIG_ARM64_RAS_EXTN=y +CONFIG_ARM64_CNP=y +# end of ARMv8.2 architectural features + +# +# ARMv8.3 architectural features +# +CONFIG_ARM64_PTR_AUTH=y +CONFIG_ARM64_PTR_AUTH_KERNEL=y +CONFIG_CC_HAS_BRANCH_PROT_PAC_RET=y +CONFIG_CC_HAS_SIGN_RETURN_ADDRESS=y +CONFIG_AS_HAS_ARMV8_3=y +CONFIG_AS_HAS_CFI_NEGATE_RA_STATE=y +CONFIG_AS_HAS_LDAPR=y +# end of ARMv8.3 architectural features + +# +# ARMv8.4 architectural features +# +CONFIG_ARM64_AMU_EXTN=y +CONFIG_AS_HAS_ARMV8_4=y +CONFIG_ARM64_TLB_RANGE=y +# end of ARMv8.4 architectural features + +# +# ARMv8.5 architectural features +# +CONFIG_AS_HAS_ARMV8_5=y +CONFIG_ARM64_BTI=y +CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI=y +CONFIG_ARM64_E0PD=y +CONFIG_ARM64_AS_HAS_MTE=y +CONFIG_ARM64_MTE=y +# end of ARMv8.5 architectural features + +# +# ARMv8.7 architectural features +# +CONFIG_ARM64_EPAN=y +# end of ARMv8.7 architectural features + +CONFIG_ARM64_SVE=y +CONFIG_ARM64_SME=y +CONFIG_ARM64_PSEUDO_NMI=y +# CONFIG_ARM64_DEBUG_PRIORITY_MASKING is not set +CONFIG_RELOCATABLE=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_RANDOMIZE_MODULE_REGION_FULL=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_STACKPROTECTOR_PER_TASK=y +# end of Kernel Features + +# +# Boot options +# +# CONFIG_ARM64_ACPI_PARKING_PROTOCOL is not set +CONFIG_CMDLINE="" +CONFIG_EFI_STUB=y +CONFIG_EFI=y +CONFIG_DMI=y +# end of Boot options + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set +CONFIG_HIBERNATE_CALLBACKS=y +CONFIG_HIBERNATION=y +CONFIG_HIBERNATION_SNAPSHOT_DEV=y +CONFIG_PM_STD_PARTITION="" +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_USERSPACE_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_CPU_PM=y +CONFIG_ENERGY_MODEL=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_HIBERNATION_HEADER=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# end of Power management options + +# +# CPU Power Management +# + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_GOV_TEO=y +CONFIG_DT_IDLE_STATES=y +CONFIG_DT_IDLE_GENPD=y + +# +# ARM CPU Idle Drivers +# +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y +# end of ARM CPU Idle Drivers +# end of CPU Idle + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y + +# +# CPU frequency scaling drivers +# +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +# CONFIG_ACPI_CPPC_CPUFREQ is not set +# CONFIG_ARM_SCMI_CPUFREQ is not set +# end of CPU Frequency scaling +# end of CPU Power Management + +CONFIG_ARCH_SUPPORTS_ACPI=y +CONFIG_ACPI=y +CONFIG_ACPI_GENERIC_GSI=y +CONFIG_ACPI_CCA_REQUIRED=y +CONFIG_ACPI_TABLE_LIB=y +CONFIG_ACPI_THERMAL_LIB=y +# CONFIG_ACPI_DEBUGGER is not set +CONFIG_ACPI_SPCR_TABLE=y +# CONFIG_ACPI_FPDT is not set +# CONFIG_ACPI_EC_DEBUGFS is not set +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +# CONFIG_ACPI_TINY_POWER_BUTTON is not set +CONFIG_ACPI_VIDEO=m +CONFIG_ACPI_FAN=m +# CONFIG_ACPI_TAD is not set +CONFIG_ACPI_DOCK=y +CONFIG_ACPI_PROCESSOR_IDLE=y +CONFIG_ACPI_MCFG=y +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_IPMI=m +CONFIG_ACPI_THERMAL=m +CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y +CONFIG_ACPI_TABLE_UPGRADE=y +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_PCI_SLOT=y +CONFIG_ACPI_CONTAINER=y +CONFIG_ACPI_HED=y +CONFIG_ACPI_CUSTOM_METHOD=m +# CONFIG_ACPI_BGRT is not set +CONFIG_ACPI_REDUCED_HARDWARE_ONLY=y +CONFIG_ACPI_NUMA=y +CONFIG_ACPI_HMAT=y +CONFIG_HAVE_ACPI_APEI=y +CONFIG_ACPI_APEI=y +CONFIG_ACPI_APEI_GHES=y +# CONFIG_ACPI_APEI_PCIEAER is not set +CONFIG_ACPI_APEI_SEA=y +CONFIG_ACPI_APEI_MEMORY_FAILURE=y +CONFIG_ACPI_APEI_EINJ=y +# CONFIG_ACPI_APEI_ERST_DEBUG is not set +CONFIG_ACPI_WATCHDOG=y +CONFIG_ACPI_CONFIGFS=m +# CONFIG_ACPI_PFRUT is not set +CONFIG_ACPI_IORT=y +CONFIG_ACPI_GTDT=y +# CONFIG_ACPI_AGDI is not set +CONFIG_ACPI_APMT=y +CONFIG_ACPI_PPTT=y +CONFIG_ACPI_PCC=y +# CONFIG_ACPI_FFH is not set +CONFIG_PMIC_OPREGION=y +CONFIG_ACPI_VIOT=y +CONFIG_ACPI_PRMT=y +CONFIG_HAVE_KVM=y +CONFIG_KVM_COMMON=y +CONFIG_HAVE_KVM_IRQCHIP=y +CONFIG_HAVE_KVM_IRQ_ROUTING=y +CONFIG_HAVE_KVM_DIRTY_RING=y +CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL=y +CONFIG_NEED_KVM_DIRTY_RING_WITH_BITMAP=y +CONFIG_KVM_MMIO=y +CONFIG_HAVE_KVM_MSI=y +CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y +CONFIG_KVM_VFIO=y +CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y +CONFIG_HAVE_KVM_IRQ_BYPASS=y +CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE=y +CONFIG_KVM_XFER_TO_GUEST_WORK=y +CONFIG_KVM_GENERIC_HARDWARE_ENABLING=y +CONFIG_KVM_GENERIC_MMU_NOTIFIER=y +CONFIG_VIRTUALIZATION=y +CONFIG_KVM=y +# CONFIG_NVHE_EL2_DEBUG is not set +CONFIG_CPU_MITIGATIONS=y + +# +# General architecture-dependent options +# +CONFIG_ARCH_HAS_SUBPAGE_FAULTS=y +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_KPROBES=y +CONFIG_JUMP_LABEL=y +# CONFIG_STATIC_KEYS_SELFTEST is not set +CONFIG_UPROBES=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_KRETPROBES=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y +CONFIG_HAVE_NMI=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_ARCH_HAS_FORTIFY_SOURCE=y +CONFIG_ARCH_HAS_KEEPINITRD=y +CONFIG_ARCH_HAS_SET_MEMORY=y +CONFIG_ARCH_HAS_SET_DIRECT_MAP=y +CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_HAVE_ASM_MODVERSIONS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_RSEQ=y +CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_PERF_EVENTS_NMI=y +CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y +CONFIG_MMU_GATHER_TABLE_FREE=y +CONFIG_MMU_GATHER_RCU_TABLE_FREE=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y +CONFIG_ARCH_HAS_NMI_SAFE_THIS_CPU_OPS=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP=y +CONFIG_SECCOMP_FILTER=y +# CONFIG_SECCOMP_CACHE_DEBUG is not set +CONFIG_HAVE_ARCH_STACKLEAK=y +CONFIG_HAVE_STACKPROTECTOR=y +CONFIG_STACKPROTECTOR=y +CONFIG_STACKPROTECTOR_STRONG=y +CONFIG_ARCH_SUPPORTS_SHADOW_CALL_STACK=y +# CONFIG_SHADOW_CALL_STACK is not set +CONFIG_ARCH_SUPPORTS_LTO_CLANG=y +CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y +CONFIG_LTO_NONE=y +CONFIG_ARCH_SUPPORTS_CFI_CLANG=y +CONFIG_HAVE_CONTEXT_TRACKING_USER=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOVE_PUD=y +CONFIG_HAVE_MOVE_PMD=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_HAVE_ARCH_HUGE_VMALLOC=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_WANT_PMD_MKWRITE=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_HAVE_ARCH_VMAP_STACK=y +CONFIG_VMAP_STACK=y +CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET=y +CONFIG_RANDOMIZE_KSTACK_OFFSET=y +# CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_STRICT_MODULE_RWX=y +CONFIG_HAVE_ARCH_COMPILER_H=y +CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +CONFIG_ARCH_USE_MEMREMAP_PROT=y +# CONFIG_LOCK_EVENT_COUNTS is not set +CONFIG_ARCH_HAS_RELR=y +CONFIG_HAVE_PREEMPT_DYNAMIC=y +CONFIG_HAVE_PREEMPT_DYNAMIC_KEY=y +CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_SUPPORTS_PAGE_TABLE_CHECK=y +CONFIG_ARCH_HAVE_TRACE_MMIO_ACCESS=y +CONFIG_ARCH_HAS_HW_PTE_YOUNG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +# end of GCOV-based kernel profiling + +CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FUNCTION_ALIGNMENT=4 +# end of General architecture-dependent options + +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_DEBUG is not set +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODULE_UNLOAD_TAINT_TRACKING is not set +CONFIG_MODVERSIONS=y +CONFIG_ASM_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_MODULE_SIG is not set +CONFIG_MODULE_COMPRESS_NONE=y +# CONFIG_MODULE_COMPRESS_GZIP is not set +# CONFIG_MODULE_COMPRESS_XZ is not set +# CONFIG_MODULE_COMPRESS_ZSTD is not set +# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set +CONFIG_MODPROBE_PATH="/sbin/modprobe" +# CONFIG_TRIM_UNUSED_KSYMS is not set +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_BLOCK=y +CONFIG_BLOCK_LEGACY_AUTOLOAD=y +CONFIG_BLK_CGROUP_RWSTAT=y +CONFIG_BLK_CGROUP_PUNT_BIO=y +CONFIG_BLK_DEV_BSG_COMMON=y +CONFIG_BLK_ICQ=y +CONFIG_BLK_DEV_BSGLIB=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BLK_DEV_INTEGRITY_T10=y +CONFIG_BLK_DEV_WRITE_MOUNTED=y +CONFIG_BLK_DEV_ZONED=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_BLK_DEV_THROTTLING_LOW=y +CONFIG_BLK_WBT=y +CONFIG_BLK_WBT_MQ=y +CONFIG_BLK_CGROUP_IOLATENCY=y +# CONFIG_BLK_CGROUP_FC_APPID is not set +# CONFIG_BLK_CGROUP_IOCOST is not set +# CONFIG_BLK_CGROUP_IOPRIO is not set +CONFIG_BLK_DEBUG_FS=y +CONFIG_BLK_DEBUG_FS_ZONED=y +CONFIG_BLK_SED_OPAL=y +# CONFIG_BLK_INLINE_ENCRYPTION is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +CONFIG_OSF_PARTITION=y +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +CONFIG_CMDLINE_PARTITION=y +# end of Partition Types + +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_MQ_VIRTIO=y +CONFIG_BLK_PM=y +CONFIG_BLOCK_HOLDER_DEPRECATED=y +CONFIG_BLK_MQ_STACKING=y + +# +# IO Schedulers +# +CONFIG_MQ_IOSCHED_DEADLINE=y +CONFIG_MQ_IOSCHED_KYBER=y +CONFIG_IOSCHED_BFQ=y +CONFIG_BFQ_GROUP_IOSCHED=y +# CONFIG_BFQ_CGROUP_DEBUG is not set +# end of IO Schedulers + +CONFIG_PREEMPT_NOTIFIERS=y +CONFIG_PADATA=y +CONFIG_ASN1=y +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y +CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y +CONFIG_FREEZER=y + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_STATE=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_HAVE_ELF_PROT=y +CONFIG_ARCH_USE_GNU_PROPERTY=y +CONFIG_ELFCORE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_SCRIPT=y +CONFIG_BINFMT_MISC=m +CONFIG_COREDUMP=y +# end of Executable file formats + +# +# Memory Management options +# +CONFIG_ZPOOL=y +CONFIG_SWAP=y +CONFIG_ZSWAP=y +CONFIG_ZSWAP_DEFAULT_ON=y +# CONFIG_ZSWAP_EXCLUSIVE_LOADS_DEFAULT_ON is not set +# CONFIG_ZSWAP_SHRINKER_DEFAULT_ON is not set +# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_DEFLATE is not set +# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZO is not set +# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_842 is not set +# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4 is not set +# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4HC is not set +CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD=y +CONFIG_ZSWAP_COMPRESSOR_DEFAULT="zstd" +# CONFIG_ZSWAP_ZPOOL_DEFAULT_ZBUD is not set +CONFIG_ZSWAP_ZPOOL_DEFAULT_Z3FOLD=y +# CONFIG_ZSWAP_ZPOOL_DEFAULT_ZSMALLOC is not set +CONFIG_ZSWAP_ZPOOL_DEFAULT="z3fold" +CONFIG_ZBUD=y +CONFIG_Z3FOLD=y +CONFIG_ZSMALLOC=y +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_ZSMALLOC_CHAIN_SIZE=8 + +# +# Slab allocator options +# +CONFIG_SLUB=y +# CONFIG_SLUB_TINY is not set +CONFIG_SLAB_MERGE_DEFAULT=y +CONFIG_SLAB_FREELIST_RANDOM=y +# CONFIG_SLAB_FREELIST_HARDENED is not set +# CONFIG_SLUB_STATS is not set +CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_RANDOM_KMALLOC_CACHES is not set +# end of Slab allocator options + +# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_FAST_GUP=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_MEMORY_ISOLATION=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +# CONFIG_MEMORY_HOTPLUG is not set +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y +CONFIG_MEMORY_BALLOON=y +CONFIG_BALLOON_COMPACTION=y +CONFIG_COMPACTION=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_PAGE_REPORTING=y +CONFIG_MIGRATION=y +CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y +CONFIG_ARCH_ENABLE_THP_MIGRATION=y +CONFIG_CONTIG_ALLOC=y +CONFIG_PCP_BATCH_SCALE_MAX=5 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_MMU_NOTIFIER=y +CONFIG_KSM=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +CONFIG_MEMORY_FAILURE=y +# CONFIG_HWPOISON_INJECT is not set +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_TRANSPARENT_HUGEPAGE=y +# CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS is not set +CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y +# CONFIG_TRANSPARENT_HUGEPAGE_NEVER is not set +CONFIG_THP_SWAP=y +# CONFIG_READ_ONLY_THP_FOR_FS is not set +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_USE_PERCPU_NUMA_NODE_ID=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set +# CONFIG_CMA_SYSFS is not set +CONFIG_CMA_AREAS=7 +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set +CONFIG_PAGE_IDLE_FLAG=y +CONFIG_IDLE_PAGE_TRACKING=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_CURRENT_STACK_POINTER=y +CONFIG_ARCH_HAS_PTE_DEVMAP=y +CONFIG_ARCH_HAS_ZONE_DMA_SET=y +CONFIG_ZONE_DMA=y +CONFIG_ZONE_DMA32=y +CONFIG_GET_FREE_REGION=y +CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y +CONFIG_ARCH_USES_PG_ARCH_X=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PERCPU_STATS=y +# CONFIG_GUP_TEST is not set +# CONFIG_DMAPOOL_TEST is not set +CONFIG_ARCH_HAS_PTE_SPECIAL=y +CONFIG_MAPPING_DIRTY_HELPERS=y +CONFIG_MEMFD_CREATE=y +CONFIG_SECRETMEM=y +# CONFIG_ANON_VMA_NAME is not set +# CONFIG_USERFAULTFD is not set +CONFIG_LRU_GEN=y +# CONFIG_LRU_GEN_ENABLED is not set +# CONFIG_LRU_GEN_STATS is not set +CONFIG_LRU_GEN_WALKS_MMU=y +CONFIG_ARCH_SUPPORTS_PER_VMA_LOCK=y +CONFIG_PER_VMA_LOCK=y +CONFIG_LOCK_MM_AND_FIND_VMA=y +CONFIG_IOMMU_MM_DATA=y + +# +# Data Access Monitoring +# +# CONFIG_DAMON is not set +# end of Data Access Monitoring +# end of Memory Management options + +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +CONFIG_NET_INGRESS=y +CONFIG_NET_EGRESS=y +CONFIG_NET_XGRESS=y +CONFIG_NET_REDIRECT=y +CONFIG_SKB_EXTENSIONS=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=m +CONFIG_UNIX=y +CONFIG_UNIX_SCM=y +CONFIG_AF_UNIX_OOB=y +CONFIG_UNIX_DIAG=m +CONFIG_TLS=m +CONFIG_TLS_DEVICE=y +# CONFIG_TLS_TOE is not set +CONFIG_XFRM=y +CONFIG_XFRM_OFFLOAD=y +CONFIG_XFRM_ALGO=m +CONFIG_XFRM_USER=m +CONFIG_XFRM_INTERFACE=m +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_XFRM_STATISTICS=y +CONFIG_XFRM_AH=m +CONFIG_XFRM_ESP=m +CONFIG_XFRM_IPCOMP=m +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_XDP_SOCKETS=y +# CONFIG_XDP_SOCKETS_DIAG is not set +CONFIG_NET_HANDSHAKE=y +# CONFIG_NET_HANDSHAKE_KUNIT_TEST is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_ROUTE_CLASSID=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IP_TUNNEL=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE_COMMON=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_NET_IPVTI=m +CONFIG_NET_UDP_TUNNEL=m +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m +# CONFIG_INET_ESPINTCP is not set +CONFIG_INET_IPCOMP=m +CONFIG_INET_TABLE_PERTURB_ORDER=16 +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_INET_UDP_DIAG=m +CONFIG_INET_RAW_DIAG=m +CONFIG_INET_DIAG_DESTROY=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_NV=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_DCTCP=m +CONFIG_TCP_CONG_CDG=m +CONFIG_TCP_CONG_BBR=m +# CONFIG_DEFAULT_CUBIC is not set +CONFIG_DEFAULT_RENO=y +CONFIG_DEFAULT_TCP_CONG="reno" +CONFIG_TCP_SIGPOOL=y +# CONFIG_TCP_AO is not set +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m +# CONFIG_INET6_ESPINTCP is not set +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_ILA=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_IPV6_SEG6_LWTUNNEL=y +CONFIG_IPV6_SEG6_HMAC=y +CONFIG_IPV6_SEG6_BPF=y +# CONFIG_IPV6_RPL_LWTUNNEL is not set +# CONFIG_IPV6_IOAM6_LWTUNNEL is not set +CONFIG_NETLABEL=y +# CONFIG_MPTCP is not set +CONFIG_NETWORK_SECMARK=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NETWORK_PHY_TIMESTAMPING=y +CONFIG_NETFILTER=y +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=m + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_EGRESS=y +CONFIG_NETFILTER_SKIP_EGRESS=y +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_FAMILY_BRIDGE=y +CONFIG_NETFILTER_FAMILY_ARP=y +CONFIG_NETFILTER_BPF_LINK=y +CONFIG_NETFILTER_NETLINK_HOOK=m +CONFIG_NETFILTER_NETLINK_ACCT=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_NETLINK_OSF=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_LOG_SYSLOG=m +CONFIG_NETFILTER_CONNCOUNT=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMEOUT=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_LABELS=y +CONFIG_NF_CONNTRACK_OVS=y +CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_GRE=y +CONFIG_NF_CT_PROTO_SCTP=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_BROADCAST=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_NETLINK_TIMEOUT=m +CONFIG_NF_CT_NETLINK_HELPER=m +CONFIG_NETFILTER_NETLINK_GLUE_CT=y +CONFIG_NF_NAT=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_REDIRECT=y +CONFIG_NF_NAT_MASQUERADE=y +CONFIG_NF_NAT_OVS=y +CONFIG_NETFILTER_SYNPROXY=m +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=y +CONFIG_NF_TABLES_NETDEV=y +CONFIG_NFT_NUMGEN=m +CONFIG_NFT_CT=m +CONFIG_NFT_FLOW_OFFLOAD=m +CONFIG_NFT_CONNLIMIT=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_TUNNEL=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_QUOTA=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_REJECT_INET=m +CONFIG_NFT_COMPAT=m +CONFIG_NFT_HASH=m +CONFIG_NFT_FIB=m +CONFIG_NFT_FIB_INET=m +CONFIG_NFT_XFRM=m +CONFIG_NFT_SOCKET=m +CONFIG_NFT_OSF=m +CONFIG_NFT_TPROXY=m +CONFIG_NFT_SYNPROXY=m +CONFIG_NF_DUP_NETDEV=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m +CONFIG_NFT_FIB_NETDEV=m +CONFIG_NFT_REJECT_NETDEV=m +CONFIG_NF_FLOW_TABLE_INET=m +CONFIG_NF_FLOW_TABLE=m +CONFIG_NF_FLOW_TABLE_PROCFS=y +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XTABLES_COMPAT=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_SET=m + +# +# Xtables targets +# +CONFIG_NETFILTER_XT_TARGET_AUDIT=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_NAT=m +CONFIG_NETFILTER_XT_TARGET_NETMAP=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ECN=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_L2TP=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +# end of Core Netfilter Configuration + +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_IPMAC=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_MH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_TWOS=m + +# +# IPVS SH scheduler +# +CONFIG_IP_VS_SH_TAB_BITS=8 + +# +# IPVS MH scheduler +# +CONFIG_IP_VS_MH_TAB_INDEX=12 + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_NFCT=y +CONFIG_IP_VS_PE_SIP=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_SOCKET_IPV4=m +CONFIG_NF_TPROXY_IPV4=m +CONFIG_NF_TABLES_IPV4=y +CONFIG_NFT_REJECT_IPV4=m +CONFIG_NFT_DUP_IPV4=m +CONFIG_NFT_FIB_IPV4=m +CONFIG_NF_TABLES_ARP=y +CONFIG_NF_DUP_IPV4=m +CONFIG_NF_LOG_ARP=m +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_SECURITY=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +# end of IP: Netfilter Configuration + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_SOCKET_IPV6=m +CONFIG_NF_TPROXY_IPV6=m +CONFIG_NF_TABLES_IPV6=y +CONFIG_NFT_REJECT_IPV6=m +CONFIG_NFT_DUP_IPV6=m +CONFIG_NFT_FIB_IPV6=m +CONFIG_NF_DUP_IPV6=m +CONFIG_NF_REJECT_IPV6=m +CONFIG_NF_LOG_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_SRH=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_SECURITY=m +CONFIG_IP6_NF_NAT=m +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +# end of IPv6: Netfilter Configuration + +CONFIG_NF_DEFRAG_IPV6=m +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_CONNTRACK_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m + +# +# DCCP CCIDs Configuration +# +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=y +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_TFRC_LIB=y +# end of DCCP CCIDs Configuration + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set +# end of DCCP Kernel Hacking + +CONFIG_IP_SCTP=m +CONFIG_SCTP_DBG_OBJCNT=y +CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set +CONFIG_SCTP_COOKIE_HMAC_MD5=y +CONFIG_SCTP_COOKIE_HMAC_SHA1=y +CONFIG_INET_SCTP_DIAG=m +CONFIG_RDS=m +CONFIG_RDS_TCP=m +# CONFIG_RDS_DEBUG is not set +CONFIG_TIPC=m +CONFIG_TIPC_MEDIA_UDP=y +CONFIG_TIPC_CRYPTO=y +CONFIG_TIPC_DIAG=m +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +CONFIG_ATM_CLIP_NO_ICMP=y +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y +CONFIG_L2TP=m +CONFIG_L2TP_DEBUGFS=m +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_STP=y +CONFIG_GARP=y +CONFIG_MRP=y +CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_BRIDGE_MRP=y +# CONFIG_BRIDGE_CFM is not set +CONFIG_NET_DSA=m +CONFIG_NET_DSA_TAG_NONE=m +CONFIG_NET_DSA_TAG_AR9331=m +CONFIG_NET_DSA_TAG_BRCM_COMMON=m +CONFIG_NET_DSA_TAG_BRCM=m +CONFIG_NET_DSA_TAG_BRCM_LEGACY=m +CONFIG_NET_DSA_TAG_BRCM_PREPEND=m +CONFIG_NET_DSA_TAG_HELLCREEK=m +CONFIG_NET_DSA_TAG_GSWIP=m +CONFIG_NET_DSA_TAG_DSA_COMMON=m +CONFIG_NET_DSA_TAG_DSA=m +CONFIG_NET_DSA_TAG_EDSA=m +CONFIG_NET_DSA_TAG_MTK=m +CONFIG_NET_DSA_TAG_KSZ=m +CONFIG_NET_DSA_TAG_OCELOT=m +CONFIG_NET_DSA_TAG_OCELOT_8021Q=m +CONFIG_NET_DSA_TAG_QCA=m +CONFIG_NET_DSA_TAG_RTL4_A=m +CONFIG_NET_DSA_TAG_RTL8_4=m +CONFIG_NET_DSA_TAG_RZN1_A5PSW=m +CONFIG_NET_DSA_TAG_LAN9303=m +CONFIG_NET_DSA_TAG_SJA1105=m +CONFIG_NET_DSA_TAG_TRAILER=m +CONFIG_NET_DSA_TAG_XRS700X=m +CONFIG_VLAN_8021Q=y +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLAN_8021Q_MVRP=y +CONFIG_LLC=y +CONFIG_LLC2=m +CONFIG_ATALK=m +CONFIG_X25=m +CONFIG_LAPB=m +CONFIG_PHONET=m +CONFIG_6LOWPAN=m +# CONFIG_6LOWPAN_DEBUGFS is not set +CONFIG_6LOWPAN_NHC=m +CONFIG_6LOWPAN_NHC_DEST=m +CONFIG_6LOWPAN_NHC_FRAGMENT=m +CONFIG_6LOWPAN_NHC_HOP=m +CONFIG_6LOWPAN_NHC_IPV6=m +CONFIG_6LOWPAN_NHC_MOBILITY=m +CONFIG_6LOWPAN_NHC_ROUTING=m +CONFIG_6LOWPAN_NHC_UDP=m +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y +CONFIG_IEEE802154_SOCKET=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_CBS=m +CONFIG_NET_SCH_ETF=m +CONFIG_NET_SCH_MQPRIO_LIB=m +CONFIG_NET_SCH_TAPRIO=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_SKBPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m +CONFIG_NET_SCH_CAKE=m +CONFIG_NET_SCH_FQ=m +CONFIG_NET_SCH_HHF=m +CONFIG_NET_SCH_PIE=m +CONFIG_NET_SCH_FQ_PIE=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m +CONFIG_NET_SCH_ETS=m +CONFIG_NET_SCH_DEFAULT=y +# CONFIG_DEFAULT_FQ is not set +# CONFIG_DEFAULT_CODEL is not set +# CONFIG_DEFAULT_FQ_CODEL is not set +# CONFIG_DEFAULT_FQ_PIE is not set +# CONFIG_DEFAULT_SFQ is not set +CONFIG_DEFAULT_PFIFO_FAST=y +CONFIG_DEFAULT_NET_SCH="pfifo_fast" + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=m +CONFIG_NET_CLS_BPF=m +CONFIG_NET_CLS_FLOWER=m +CONFIG_NET_CLS_MATCHALL=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_CANID=m +CONFIG_NET_EMATCH_IPSET=m +CONFIG_NET_EMATCH_IPT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_SAMPLE=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_ACT_CSUM=m +CONFIG_NET_ACT_MPLS=m +CONFIG_NET_ACT_VLAN=m +CONFIG_NET_ACT_BPF=m +CONFIG_NET_ACT_CONNMARK=m +CONFIG_NET_ACT_CTINFO=m +CONFIG_NET_ACT_SKBMOD=m +CONFIG_NET_ACT_IFE=m +CONFIG_NET_ACT_TUNNEL_KEY=m +CONFIG_NET_ACT_CT=m +CONFIG_NET_ACT_GATE=m +CONFIG_NET_IFE_SKBMARK=m +CONFIG_NET_IFE_SKBPRIO=m +CONFIG_NET_IFE_SKBTCINDEX=m +# CONFIG_NET_TC_SKB_EXT is not set +CONFIG_NET_SCH_FIFO=y +CONFIG_DCB=y +CONFIG_DNS_RESOLVER=y +CONFIG_BATMAN_ADV=m +CONFIG_BATMAN_ADV_BATMAN_V=y +CONFIG_BATMAN_ADV_BLA=y +CONFIG_BATMAN_ADV_DAT=y +CONFIG_BATMAN_ADV_NC=y +CONFIG_BATMAN_ADV_MCAST=y +CONFIG_BATMAN_ADV_DEBUG=y +CONFIG_BATMAN_ADV_TRACING=y +CONFIG_OPENVSWITCH=m +CONFIG_OPENVSWITCH_GRE=m +CONFIG_OPENVSWITCH_VXLAN=m +CONFIG_OPENVSWITCH_GENEVE=m +CONFIG_VSOCKETS=m +CONFIG_VSOCKETS_DIAG=m +CONFIG_VSOCKETS_LOOPBACK=m +CONFIG_VIRTIO_VSOCKETS=m +CONFIG_VIRTIO_VSOCKETS_COMMON=m +CONFIG_NETLINK_DIAG=m +CONFIG_MPLS=y +CONFIG_NET_MPLS_GSO=m +CONFIG_MPLS_ROUTING=m +CONFIG_MPLS_IPTUNNEL=m +CONFIG_NET_NSH=m +CONFIG_HSR=m +CONFIG_NET_SWITCHDEV=y +CONFIG_NET_L3_MASTER_DEV=y +# CONFIG_QRTR is not set +# CONFIG_NET_NCSI is not set +CONFIG_PCPU_DEV_REFCNT=y +CONFIG_MAX_SKB_FRAGS=17 +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_XPS=y +CONFIG_CGROUP_NET_PRIO=y +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +CONFIG_BPF_STREAM_PARSER=y +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +CONFIG_NET_DROP_MONITOR=m +# end of Network testing +# end of Networking options + +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +CONFIG_AX25=m +CONFIG_AX25_DAMA_SLAVE=y +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_YAM=m +# end of AX.25 network device drivers + +CONFIG_CAN=m +CONFIG_CAN_RAW=m +CONFIG_CAN_BCM=m +CONFIG_CAN_GW=m +CONFIG_CAN_J1939=m +# CONFIG_CAN_ISOTP is not set +CONFIG_BT=m +CONFIG_BT_BREDR=y +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_LE=y +CONFIG_BT_LE_L2CAP_ECRED=y +CONFIG_BT_6LOWPAN=m +CONFIG_BT_LEDS=y +# CONFIG_BT_MSFTEXT is not set +CONFIG_BT_AOSPEXT=y +# CONFIG_BT_DEBUGFS is not set +# CONFIG_BT_SELFTEST is not set + +# +# Bluetooth device drivers +# +CONFIG_BT_INTEL=m +CONFIG_BT_BCM=m +CONFIG_BT_RTL=m +CONFIG_BT_QCA=m +CONFIG_BT_MTK=m +CONFIG_BT_HCIBTUSB=m +# CONFIG_BT_HCIBTUSB_AUTOSUSPEND is not set +CONFIG_BT_HCIBTUSB_POLL_SYNC=y +CONFIG_BT_HCIBTUSB_BCM=y +CONFIG_BT_HCIBTUSB_MTK=y +CONFIG_BT_HCIBTUSB_RTL=y +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_SERDEV=y +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_NOKIA=m +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_3WIRE=y +CONFIG_BT_HCIUART_INTEL=y +CONFIG_BT_HCIUART_BCM=y +CONFIG_BT_HCIUART_RTL=y +CONFIG_BT_HCIUART_QCA=y +CONFIG_BT_HCIUART_AG6XX=y +CONFIG_BT_HCIUART_MRVL=y +CONFIG_BT_HCIBCM203X=m +# CONFIG_BT_HCIBCM4377 is not set +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_BT_MTKSDIO=m +CONFIG_BT_MTKUART=m +CONFIG_BT_HCIRSI=m +CONFIG_BT_VIRTIO=m +# CONFIG_BT_NXPUART is not set +# end of Bluetooth device drivers + +CONFIG_AF_RXRPC=m +# CONFIG_AF_RXRPC_IPV6 is not set +# CONFIG_AF_RXRPC_INJECT_LOSS is not set +# CONFIG_AF_RXRPC_INJECT_RX_DELAY is not set +# CONFIG_AF_RXRPC_DEBUG is not set +# CONFIG_RXKAD is not set +# CONFIG_RXPERF is not set +# CONFIG_AF_KCM is not set +CONFIG_STREAM_PARSER=y +# CONFIG_MCTP is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=m +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y +CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_CRDA_SUPPORT=y +CONFIG_CFG80211_WEXT=y +CONFIG_CFG80211_WEXT_EXPORT=y +# CONFIG_CFG80211_KUNIT_TEST is not set +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +# CONFIG_MAC80211_KUNIT_TEST is not set +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_MESSAGE_TRACING is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +CONFIG_RFKILL=m +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +CONFIG_RFKILL_GPIO=m +CONFIG_NET_9P=m +CONFIG_NET_9P_FD=m +CONFIG_NET_9P_VIRTIO=m +CONFIG_NET_9P_XEN=m +# CONFIG_NET_9P_DEBUG is not set +CONFIG_CAIF=m +# CONFIG_CAIF_DEBUG is not set +CONFIG_CAIF_NETDEV=m +CONFIG_CAIF_USB=m +CONFIG_CEPH_LIB=m +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +CONFIG_CEPH_LIB_USE_DNS_RESOLVER=y +CONFIG_NFC=m +CONFIG_NFC_DIGITAL=m +CONFIG_NFC_NCI=m +CONFIG_NFC_NCI_SPI=m +CONFIG_NFC_NCI_UART=m +CONFIG_NFC_HCI=m +CONFIG_NFC_SHDLC=y + +# +# Near Field Communication (NFC) devices +# +CONFIG_NFC_TRF7970A=m +CONFIG_NFC_SIM=m +CONFIG_NFC_PORT100=m +CONFIG_NFC_VIRTUAL_NCI=m +CONFIG_NFC_FDP=m +CONFIG_NFC_FDP_I2C=m +CONFIG_NFC_PN544=m +CONFIG_NFC_PN544_I2C=m +CONFIG_NFC_PN533=m +CONFIG_NFC_PN533_USB=m +CONFIG_NFC_PN533_I2C=m +CONFIG_NFC_PN532_UART=m +CONFIG_NFC_MICROREAD=m +CONFIG_NFC_MICROREAD_I2C=m +CONFIG_NFC_MRVL=m +CONFIG_NFC_MRVL_USB=m +CONFIG_NFC_MRVL_UART=m +CONFIG_NFC_MRVL_I2C=m +CONFIG_NFC_MRVL_SPI=m +CONFIG_NFC_ST21NFCA=m +CONFIG_NFC_ST21NFCA_I2C=m +CONFIG_NFC_ST_NCI=m +CONFIG_NFC_ST_NCI_I2C=m +CONFIG_NFC_ST_NCI_SPI=m +CONFIG_NFC_NXP_NCI=m +CONFIG_NFC_NXP_NCI_I2C=m +CONFIG_NFC_S3FWRN5=m +CONFIG_NFC_S3FWRN5_I2C=m +CONFIG_NFC_S3FWRN82_UART=m +CONFIG_NFC_ST95HF=m +# end of Near Field Communication (NFC) devices + +CONFIG_PSAMPLE=m +CONFIG_NET_IFE=m +CONFIG_LWTUNNEL=y +CONFIG_LWTUNNEL_BPF=y +CONFIG_DST_CACHE=y +CONFIG_GRO_CELLS=y +CONFIG_SOCK_VALIDATE_XMIT=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_SOCK_MSG=y +CONFIG_NET_DEVLINK=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_POOL_STATS=y +CONFIG_FAILOVER=y +CONFIG_ETHTOOL_NETLINK=y +# CONFIG_NETDEV_ADDR_LIST_TEST is not set +# CONFIG_NET_TEST is not set + +# +# Device Drivers +# +CONFIG_ARM_AMBA=y +CONFIG_HAVE_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=y +CONFIG_PCIEAER=y +CONFIG_PCIEAER_INJECT=m +CONFIG_PCIEAER_CXL=y +CONFIG_PCIE_ECRC=y +CONFIG_PCIEASPM=y +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +# CONFIG_PCIEASPM_PERFORMANCE is not set +CONFIG_PCIE_PME=y +# CONFIG_PCIE_DPC is not set +# CONFIG_PCIE_PTM is not set +CONFIG_PCI_MSI=y +CONFIG_PCI_QUIRKS=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +CONFIG_PCI_STUB=y +# CONFIG_PCI_PF_STUB is not set +CONFIG_PCI_ATS=y +CONFIG_PCI_DOE=y +CONFIG_PCI_ECAM=y +CONFIG_PCI_IOV=y +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y +CONFIG_PCI_LABEL=y +# CONFIG_PCI_DYNAMIC_OF_NODES is not set +# CONFIG_PCIE_BUS_TUNE_OFF is not set +CONFIG_PCIE_BUS_DEFAULT=y +# CONFIG_PCIE_BUS_SAFE is not set +# CONFIG_PCIE_BUS_PERFORMANCE is not set +# CONFIG_PCIE_BUS_PEER2PEER is not set +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_ACPI=y +# CONFIG_HOTPLUG_PCI_ACPI_AMPERE_ALTRA is not set +# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# +# PCI controller drivers +# +CONFIG_PCIE_ALTERA=y +CONFIG_PCIE_ALTERA_MSI=y +CONFIG_PCI_HOST_THUNDER_PEM=y +CONFIG_PCI_HOST_THUNDER_ECAM=y +# CONFIG_PCI_FTPCI100 is not set +CONFIG_PCI_HOST_COMMON=y +CONFIG_PCI_HOST_GENERIC=y +# CONFIG_PCIE_HISI_ERR is not set +# CONFIG_PCIE_MICROCHIP_HOST is not set +CONFIG_PCIE_ROCKCHIP=y +CONFIG_PCIE_ROCKCHIP_HOST=y +CONFIG_PCIE_ROCKCHIP_EP=y +CONFIG_PCI_XGENE=y +CONFIG_PCI_XGENE_MSI=y +# CONFIG_PCIE_XILINX is not set + +# +# Cadence-based PCIe controllers +# +# CONFIG_PCIE_CADENCE_PLAT_HOST is not set +# CONFIG_PCIE_CADENCE_PLAT_EP is not set +# end of Cadence-based PCIe controllers + +# +# DesignWare-based PCIe controllers +# +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_DW_EP=y +# CONFIG_PCIE_AL is not set +# CONFIG_PCI_MESON is not set +CONFIG_PCI_HISI=y +# CONFIG_PCIE_KIRIN is not set +CONFIG_PCIE_DW_PLAT=y +CONFIG_PCIE_DW_PLAT_HOST=y +CONFIG_PCIE_DW_PLAT_EP=y +CONFIG_PCIE_ROCKCHIP_DW_HOST=y +# end of DesignWare-based PCIe controllers + +# +# Mobiveil-based PCIe controllers +# +# end of Mobiveil-based PCIe controllers +# end of PCI controller drivers + +# +# PCI Endpoint +# +CONFIG_PCI_ENDPOINT=y +CONFIG_PCI_ENDPOINT_CONFIGFS=y +CONFIG_PCI_EPF_TEST=m +CONFIG_PCI_EPF_NTB=m +# end of PCI Endpoint + +# +# PCI switch controller drivers +# +# CONFIG_PCI_SW_SWITCHTEC is not set +# end of PCI switch controller drivers + +CONFIG_CXL_BUS=m +CONFIG_CXL_PCI=m +# CONFIG_CXL_MEM_RAW_COMMANDS is not set +CONFIG_CXL_ACPI=m +CONFIG_CXL_MEM=m +CONFIG_CXL_PORT=m +CONFIG_CXL_SUSPEND=y +CONFIG_CXL_REGION=y +# CONFIG_CXL_REGION_INVALIDATION_TEST is not set +CONFIG_CXL_PMU=m +# CONFIG_PCCARD is not set +# CONFIG_RAPIDIO is not set + +# +# Generic Driver Options +# +CONFIG_AUXILIARY_BUS=y +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_DEVTMPFS_SAFE is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y + +# +# Firmware loader +# +CONFIG_FW_LOADER=y +CONFIG_FW_LOADER_DEBUG=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_FW_LOADER_USER_HELPER is not set +# CONFIG_FW_LOADER_COMPRESS is not set +CONFIG_FW_CACHE=y +CONFIG_FW_UPLOAD=y +# end of Firmware loader + +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_ALLOW_DEV_COREDUMP=y +CONFIG_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +CONFIG_HMEM_REPORTING=y +# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set +# CONFIG_DM_KUNIT_TEST is not set +# CONFIG_DRIVER_PE_KUNIT_TEST is not set +CONFIG_SYS_HYPERVISOR=y +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_SOC_BUS=y +CONFIG_REGMAP=y +# CONFIG_REGMAP_KUNIT is not set +# CONFIG_REGMAP_BUILD is not set +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SLIMBUS=m +CONFIG_REGMAP_SPI=m +CONFIG_REGMAP_SPMI=m +CONFIG_REGMAP_W1=m +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_REGMAP_SOUNDWIRE=m +CONFIG_REGMAP_SOUNDWIRE_MBQ=m +CONFIG_REGMAP_SCCB=m +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_DMA_FENCE_TRACE is not set +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_ARCH_NUMA=y +# CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set +# end of Generic Driver Options + +# +# Bus devices +# +CONFIG_ARM_CCI=y +CONFIG_ARM_CCI400_COMMON=y +# CONFIG_MOXTET is not set +CONFIG_VEXPRESS_CONFIG=y +CONFIG_MHI_BUS=m +# CONFIG_MHI_BUS_DEBUG is not set +CONFIG_MHI_BUS_PCI_GENERIC=m +# CONFIG_MHI_BUS_EP is not set +# end of Bus devices + +# +# Cache Drivers +# +# end of Cache Drivers + +CONFIG_CONNECTOR=m + +# +# Firmware Drivers +# + +# +# ARM System Control and Management Interface Protocol +# +CONFIG_ARM_SCMI_PROTOCOL=y +# CONFIG_ARM_SCMI_RAW_MODE_SUPPORT is not set +CONFIG_ARM_SCMI_HAVE_TRANSPORT=y +CONFIG_ARM_SCMI_HAVE_SHMEM=y +CONFIG_ARM_SCMI_HAVE_MSG=y +CONFIG_ARM_SCMI_TRANSPORT_MAILBOX=y +CONFIG_ARM_SCMI_TRANSPORT_OPTEE=y +CONFIG_ARM_SCMI_TRANSPORT_SMC=y +# CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE is not set +CONFIG_ARM_SCMI_TRANSPORT_VIRTIO=y +CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y +# CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_ATOMIC_ENABLE is not set +CONFIG_ARM_SCMI_POWER_CONTROL=m +# end of ARM System Control and Management Interface Protocol + +CONFIG_ARM_SCPI_PROTOCOL=y +CONFIG_ARM_SDE_INTERFACE=y +# CONFIG_FIRMWARE_MEMMAP is not set +CONFIG_DMIID=y +CONFIG_DMI_SYSFS=y +CONFIG_ISCSI_IBFT=y +# CONFIG_FW_CFG_SYSFS is not set +CONFIG_SYSFB=y +CONFIG_SYSFB_SIMPLEFB=y +CONFIG_ARM_FFA_TRANSPORT=m +CONFIG_ARM_FFA_SMCCC=y +CONFIG_FW_CS_DSP=m +# CONFIG_GOOGLE_FIRMWARE is not set + +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_ESRT=y +CONFIG_EFI_VARS_PSTORE=y +CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y +CONFIG_EFI_SOFT_RESERVE=y +CONFIG_EFI_PARAMS_FROM_FDT=y +CONFIG_EFI_RUNTIME_WRAPPERS=y +CONFIG_EFI_GENERIC_STUB=y +# CONFIG_EFI_ZBOOT is not set +CONFIG_EFI_ARMSTUB_DTB_LOADER=y +CONFIG_EFI_BOOTLOADER_CONTROL=m +CONFIG_EFI_CAPSULE_LOADER=m +CONFIG_EFI_TEST=m +CONFIG_RESET_ATTACK_MITIGATION=y +CONFIG_EFI_DISABLE_PCI_DMA=y +CONFIG_EFI_EARLYCON=y +CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y +# CONFIG_EFI_DISABLE_RUNTIME is not set +# CONFIG_EFI_COCO_SECRET is not set +# end of EFI (Extensible Firmware Interface) Support + +CONFIG_UEFI_CPER=y +CONFIG_UEFI_CPER_ARM=y +# CONFIG_TEE_STMM_EFI is not set +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_PSCI_CHECKER=y + +# +# Qualcomm firmware drivers +# +# end of Qualcomm firmware drivers + +CONFIG_HAVE_ARM_SMCCC=y +CONFIG_HAVE_ARM_SMCCC_DISCOVERY=y +CONFIG_ARM_SMCCC_SOC_ID=y + +# +# Tegra firmware driver +# +# end of Tegra firmware driver +# end of Firmware Drivers + +CONFIG_GNSS=m +CONFIG_GNSS_SERIAL=m +CONFIG_GNSS_MTK_SERIAL=m +CONFIG_GNSS_SIRF_SERIAL=m +CONFIG_GNSS_UBX_SERIAL=m +# CONFIG_GNSS_USB is not set +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set + +# +# Partition parsers +# +CONFIG_MTD_CMDLINE_PARTS=m +CONFIG_MTD_OF_PARTS=y +CONFIG_MTD_AFS_PARTS=m +# CONFIG_MTD_REDBOOT_PARTS is not set +# end of Partition parsers + +# +# User Modules And Translation Layers +# +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y + +# +# Note that in some cases UBI block is preferred. See MTD_UBI_BLOCK. +# +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m +CONFIG_SSFDC=m +CONFIG_SM_FTL=m +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_PSTORE is not set +CONFIG_MTD_SWAP=m +# CONFIG_MTD_PARTITIONED_MASTER is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# end of RAM/ROM/Flash chip drivers + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PHYSMAP_VERSATILE is not set +# CONFIG_MTD_PHYSMAP_GEMINI is not set +CONFIG_MTD_PHYSMAP_GPIO_ADDR=y +CONFIG_MTD_PCI=m +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set +# end of Mapping drivers for chip access + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +CONFIG_MTD_DATAFLASH=y +# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set +# CONFIG_MTD_DATAFLASH_OTP is not set +# CONFIG_MTD_MCHP23K256 is not set +CONFIG_MTD_MCHP48L640=m +CONFIG_MTD_SST25L=y +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# end of Self-contained MTD device drivers + +# +# NAND +# +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_ONENAND=m +# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set +# CONFIG_MTD_ONENAND_GENERIC is not set +# CONFIG_MTD_ONENAND_OTP is not set +# CONFIG_MTD_ONENAND_2X_PROGRAM is not set +CONFIG_MTD_RAW_NAND=y + +# +# Raw/parallel NAND flash controllers +# +CONFIG_MTD_NAND_DENALI=y +# CONFIG_MTD_NAND_DENALI_PCI is not set +CONFIG_MTD_NAND_DENALI_DT=y +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_BRCMNAND is not set +# CONFIG_MTD_NAND_MXIC is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_NAND_CADENCE is not set +# CONFIG_MTD_NAND_ARASAN is not set +# CONFIG_MTD_NAND_INTEL_LGM is not set +CONFIG_MTD_NAND_ROCKCHIP=m + +# +# Misc +# +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_RICOH is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_SPI_NAND=m + +# +# ECC engine support +# +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +# CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC is not set +# CONFIG_MTD_NAND_ECC_SW_BCH is not set +CONFIG_MTD_NAND_ECC_MXIC=y +# end of ECC engine support +# end of NAND + +# +# LPDDR & LPDDR2 PCM memory drivers +# +# CONFIG_MTD_LPDDR is not set +# end of LPDDR & LPDDR2 PCM memory drivers + +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set +CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y +# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_LIMIT=20 +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +# CONFIG_MTD_UBI_BLOCK is not set +CONFIG_MTD_HYPERBUS=m +CONFIG_DTC=y +CONFIG_OF=y +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_KOBJ=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OF_RESOLVE=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_NUMA=y +# CONFIG_PARPORT is not set +CONFIG_PNP=y +CONFIG_PNP_DEBUG_MESSAGES=y + +# +# Protocols +# +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y +CONFIG_BLK_DEV_NULL_BLK=m +CONFIG_CDROM=y +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +CONFIG_ZRAM=m +CONFIG_ZRAM_DEF_COMP_LZORLE=y +# CONFIG_ZRAM_DEF_COMP_ZSTD is not set +# CONFIG_ZRAM_DEF_COMP_LZ4 is not set +# CONFIG_ZRAM_DEF_COMP_LZO is not set +# CONFIG_ZRAM_DEF_COMP_LZ4HC is not set +# CONFIG_ZRAM_DEF_COMP_842 is not set +CONFIG_ZRAM_DEF_COMP="lzo-rle" +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_ZRAM_TRACK_ENTRY_ACTIME is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set +# CONFIG_ZRAM_MULTI_COMP is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +CONFIG_BLK_DEV_DRBD=m +# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_CDROM_PKTCDVD is not set +CONFIG_ATA_OVER_ETH=m +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_BLKDEV_BACKEND=m +CONFIG_VIRTIO_BLK=y +CONFIG_BLK_DEV_RBD=m +CONFIG_BLK_DEV_UBLK=m +CONFIG_BLKDEV_UBLK_LEGACY_OPCODES=y + +# +# NVME Support +# +CONFIG_NVME_KEYRING=m +CONFIG_NVME_AUTH=y +CONFIG_NVME_CORE=y +CONFIG_BLK_DEV_NVME=y +CONFIG_NVME_MULTIPATH=y +# CONFIG_NVME_VERBOSE_ERRORS is not set +CONFIG_NVME_HWMON=y +CONFIG_NVME_FABRICS=m +CONFIG_NVME_FC=m +CONFIG_NVME_TCP=m +CONFIG_NVME_TCP_TLS=y +CONFIG_NVME_HOST_AUTH=y +CONFIG_NVME_TARGET=m +CONFIG_NVME_TARGET_PASSTHRU=y +CONFIG_NVME_TARGET_LOOP=m +CONFIG_NVME_TARGET_FC=m +CONFIG_NVME_TARGET_FCLOOP=m +CONFIG_NVME_TARGET_TCP=m +CONFIG_NVME_TARGET_TCP_TLS=y +CONFIG_NVME_TARGET_AUTH=y +# end of NVME Support + +# +# Misc devices +# +CONFIG_AD525X_DPOT=m +CONFIG_AD525X_DPOT_I2C=m +CONFIG_AD525X_DPOT_SPI=m +# CONFIG_DUMMY_IRQ is not set +CONFIG_PHANTOM=m +CONFIG_TIFM_CORE=m +CONFIG_TIFM_7XX1=m +# CONFIG_ICS932S401 is not set +CONFIG_ENCLOSURE_SERVICES=m +CONFIG_HI6421V600_IRQ=m +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +CONFIG_SRAM=y +CONFIG_DW_XDATA_PCIE=m +# CONFIG_PCI_ENDPOINT_TEST is not set +CONFIG_XILINX_SDFEC=m +CONFIG_MISC_RTSX=m +# CONFIG_HISI_HIKEY_USB is not set +# CONFIG_OPEN_DICE is not set +CONFIG_VCPU_STALL_DETECTOR=m +# CONFIG_NSM is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=m +CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_MAX6875=m +CONFIG_EEPROM_93CX6=m +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_IDT_89HPESX is not set +CONFIG_EEPROM_EE1004=m +# end of EEPROM support + +CONFIG_CB710_CORE=m +# CONFIG_CB710_DEBUG is not set +CONFIG_CB710_DEBUG_ASSUMPTIONS=y + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# end of Texas Instruments shared transport line discipline + +# CONFIG_SENSORS_LIS3_I2C is not set +CONFIG_ALTERA_STAPL=m +# CONFIG_VMWARE_VMCI is not set +CONFIG_GENWQE=m +CONFIG_GENWQE_PLATFORM_ERROR_RECOVERY=0 +CONFIG_ECHO=m +CONFIG_BCM_VK=m +# CONFIG_BCM_VK_TTY is not set +CONFIG_MISC_ALCOR_PCI=m +CONFIG_MISC_RTSX_PCI=m +CONFIG_MISC_RTSX_USB=m +CONFIG_UACCE=m +# CONFIG_PVPANIC is not set +CONFIG_GP_PCI1XXXX=m +# end of Misc devices + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +CONFIG_RAID_ATTRS=m +CONFIG_SCSI_COMMON=y +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +CONFIG_SCSI_NETLINK=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=m +CONFIG_BLK_DEV_SR=y +CONFIG_CHR_DEV_SG=y +CONFIG_BLK_DEV_BSG=y +CONFIG_CHR_DEV_SCH=m +CONFIG_SCSI_ENCLOSURE=m +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=y +CONFIG_SCSI_SAS_LIBSAS=m +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_SAS_HOST_SMP=y +CONFIG_SCSI_SRP_ATTRS=m +# end of SCSI Transports + +CONFIG_SCSI_LOWLEVEL=y +CONFIG_ISCSI_TCP=m +CONFIG_ISCSI_BOOT_SYSFS=y +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +CONFIG_SCSI_BNX2_ISCSI=m +CONFIG_SCSI_BNX2X_FCOE=m +CONFIG_BE2ISCSI=m +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +CONFIG_SCSI_HPSA=m +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_HISI_SAS is not set +CONFIG_SCSI_MVSAS=m +# CONFIG_SCSI_MVSAS_DEBUG is not set +CONFIG_SCSI_MVSAS_TASKLET=y +CONFIG_SCSI_MVUMI=m +# CONFIG_SCSI_ADVANSYS is not set +CONFIG_SCSI_ARCMSR=m +CONFIG_SCSI_ESAS2R=m +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_MPT3SAS=m +CONFIG_SCSI_MPT2SAS_MAX_SGE=128 +CONFIG_SCSI_MPT3SAS_MAX_SGE=128 +# CONFIG_SCSI_MPT2SAS is not set +CONFIG_SCSI_MPI3MR=m +# CONFIG_SCSI_SMARTPQI is not set +# CONFIG_SCSI_HPTIOP is not set +CONFIG_SCSI_BUSLOGIC=m +CONFIG_SCSI_FLASHPOINT=y +# CONFIG_SCSI_MYRB is not set +# CONFIG_SCSI_MYRS is not set +# CONFIG_XEN_SCSI_FRONTEND is not set +CONFIG_LIBFC=m +CONFIG_LIBFCOE=m +CONFIG_FCOE=m +CONFIG_SCSI_SNIC=m +# CONFIG_SCSI_SNIC_DEBUG_FS is not set +CONFIG_SCSI_DMX3191D=m +# CONFIG_SCSI_FDOMAIN_PCI is not set +# CONFIG_SCSI_IPS is not set +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_STEX=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +CONFIG_SCSI_IPR=m +CONFIG_SCSI_IPR_TRACE=y +CONFIG_SCSI_IPR_DUMP=y +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_TCM_QLA2XXX=m +# CONFIG_TCM_QLA2XXX_DEBUG is not set +CONFIG_SCSI_QLA_ISCSI=m +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_EFCT is not set +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_AM53C974=m +CONFIG_SCSI_WD719X=m +CONFIG_SCSI_DEBUG=m +CONFIG_SCSI_PMCRAID=m +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_BFA_FC is not set +CONFIG_SCSI_VIRTIO=y +CONFIG_SCSI_CHELSIO_FCOE=m +CONFIG_SCSI_DH=y +CONFIG_SCSI_DH_RDAC=m +CONFIG_SCSI_DH_HP_SW=m +CONFIG_SCSI_DH_EMC=m +CONFIG_SCSI_DH_ALUA=m +# end of SCSI device support + +CONFIG_ATA=y +CONFIG_SATA_HOST=y +CONFIG_PATA_TIMINGS=y +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_ATA_FORCE=y +CONFIG_ATA_ACPI=y +# CONFIG_SATA_ZPODD is not set +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI=y +CONFIG_SATA_MOBILE_LPM_POLICY=0 +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_DWC=y +CONFIG_AHCI_CEVA=y +CONFIG_SATA_INIC162X=m +CONFIG_SATA_ACARD_AHCI=m +CONFIG_SATA_SIL24=y +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +CONFIG_PDC_ADMA=m +CONFIG_SATA_QSTOR=m +CONFIG_SATA_SX4=m +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +CONFIG_ATA_PIIX=y +# CONFIG_SATA_DWC is not set +CONFIG_SATA_MV=m +CONFIG_SATA_NV=m +CONFIG_SATA_PROMISE=m +CONFIG_SATA_SIL=m +CONFIG_SATA_SIS=m +CONFIG_SATA_SVW=m +CONFIG_SATA_ULI=m +CONFIG_SATA_VIA=m +CONFIG_SATA_VITESSE=m + +# +# PATA SFF controllers with BMDMA +# +CONFIG_PATA_ALI=m +CONFIG_PATA_AMD=m +CONFIG_PATA_ARTOP=m +CONFIG_PATA_ATIIXP=m +CONFIG_PATA_ATP867X=m +CONFIG_PATA_CMD64X=m +CONFIG_PATA_CYPRESS=m +CONFIG_PATA_EFAR=m +CONFIG_PATA_HPT366=m +CONFIG_PATA_HPT37X=m +CONFIG_PATA_HPT3X2N=m +CONFIG_PATA_HPT3X3=m +# CONFIG_PATA_HPT3X3_DMA is not set +CONFIG_PATA_IT8213=m +CONFIG_PATA_IT821X=m +CONFIG_PATA_JMICRON=m +CONFIG_PATA_MARVELL=m +CONFIG_PATA_NETCELL=m +CONFIG_PATA_NINJA32=m +CONFIG_PATA_NS87415=m +CONFIG_PATA_OLDPIIX=m +CONFIG_PATA_OPTIDMA=m +CONFIG_PATA_PDC2027X=m +CONFIG_PATA_PDC_OLD=m +# CONFIG_PATA_RADISYS is not set +CONFIG_PATA_RDC=m +CONFIG_PATA_SCH=m +CONFIG_PATA_SERVERWORKS=m +CONFIG_PATA_SIL680=m +CONFIG_PATA_SIS=m +CONFIG_PATA_TOSHIBA=m +CONFIG_PATA_TRIFLEX=m +CONFIG_PATA_VIA=m +CONFIG_PATA_WINBOND=m + +# +# PIO-only SFF controllers +# +CONFIG_PATA_CMD640_PCI=m +CONFIG_PATA_MPIIX=m +CONFIG_PATA_NS87410=m +CONFIG_PATA_OPTI=m +CONFIG_PATA_PLATFORM=y +CONFIG_PATA_OF_PLATFORM=y +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +CONFIG_PATA_ACPI=m +CONFIG_ATA_GENERIC=y +# CONFIG_PATA_LEGACY is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y +CONFIG_MD_BITMAP_FILE=y +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_CLUSTER=m +CONFIG_BCACHE=m +# CONFIG_BCACHE_DEBUG is not set +# CONFIG_BCACHE_ASYNC_REGISTRATION is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=m +# CONFIG_DM_DEBUG is not set +CONFIG_DM_BUFIO=m +# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set +CONFIG_DM_BIO_PRISON=m +CONFIG_DM_PERSISTENT_DATA=m +CONFIG_DM_UNSTRIPED=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_THIN_PROVISIONING=m +CONFIG_DM_CACHE=m +CONFIG_DM_CACHE_SMQ=m +CONFIG_DM_WRITECACHE=m +# CONFIG_DM_EBS is not set +CONFIG_DM_ERA=m +CONFIG_DM_CLONE=m +CONFIG_DM_MIRROR=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_RAID=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_QL=m +CONFIG_DM_MULTIPATH_ST=m +# CONFIG_DM_MULTIPATH_HST is not set +CONFIG_DM_MULTIPATH_IOA=m +CONFIG_DM_DELAY=m +CONFIG_DM_DUST=m +CONFIG_DM_UEVENT=y +CONFIG_DM_FLAKEY=m +CONFIG_DM_VERITY=m +# CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG is not set +CONFIG_DM_VERITY_FEC=y +CONFIG_DM_SWITCH=m +CONFIG_DM_LOG_WRITES=m +CONFIG_DM_INTEGRITY=m +CONFIG_DM_ZONED=m +CONFIG_DM_AUDIT=y +CONFIG_TARGET_CORE=m +CONFIG_TCM_IBLOCK=m +CONFIG_TCM_FILEIO=m +CONFIG_TCM_PSCSI=m +CONFIG_TCM_USER2=m +CONFIG_LOOPBACK_TARGET=m +CONFIG_TCM_FC=m +CONFIG_ISCSI_TARGET=m +# CONFIG_REMOTE_TARGET is not set +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=128 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m +# CONFIG_FUSION_LOGGING is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +CONFIG_FIREWIRE_NOSY=m +# end of IEEE 1394 (FireWire) support + +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_WIREGUARD=m +# CONFIG_WIREGUARD_DEBUG is not set +CONFIG_EQUALIZER=m +CONFIG_NET_FC=y +CONFIG_IFB=m +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_RANDOM=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +CONFIG_IPVLAN_L3S=y +CONFIG_IPVLAN=m +CONFIG_IPVTAP=m +CONFIG_VXLAN=m +CONFIG_GENEVE=m +CONFIG_BAREUDP=m +CONFIG_GTP=m +CONFIG_AMT=m +CONFIG_MACSEC=m +CONFIG_NETCONSOLE=y +CONFIG_NETCONSOLE_DYNAMIC=y +# CONFIG_NETCONSOLE_EXTENDED_LOG is not set +CONFIG_NETPOLL=y +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_TUN=m +CONFIG_TAP=m +CONFIG_TUN_VNET_CROSS_LE=y +CONFIG_VETH=m +CONFIG_VIRTIO_NET=m +CONFIG_NLMON=m +# CONFIG_NETKIT is not set +CONFIG_NET_VRF=m +CONFIG_MHI_NET=m +# CONFIG_ARCNET is not set +CONFIG_ATM_DRIVERS=y +CONFIG_ATM_DUMMY=m +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_FORE200E=m +# CONFIG_ATM_FORE200E_USE_TASKLET is not set +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_ATM_SOLOS=m +CONFIG_CAIF_DRIVERS=y +CONFIG_CAIF_TTY=m +CONFIG_CAIF_VIRTIO=m + +# +# Distributed Switch Architecture drivers +# +CONFIG_B53=m +CONFIG_B53_SPI_DRIVER=m +CONFIG_B53_MDIO_DRIVER=m +CONFIG_B53_MMAP_DRIVER=m +CONFIG_B53_SRAB_DRIVER=m +CONFIG_B53_SERDES=m +CONFIG_NET_DSA_BCM_SF2=m +CONFIG_NET_DSA_LOOP=m +CONFIG_NET_DSA_HIRSCHMANN_HELLCREEK=m +CONFIG_NET_DSA_LANTIQ_GSWIP=m +CONFIG_NET_DSA_MT7530=m +CONFIG_NET_DSA_MT7530_MDIO=m +CONFIG_NET_DSA_MT7530_MMIO=m +CONFIG_NET_DSA_MV88E6060=m +CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON=m +CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C=m +CONFIG_NET_DSA_MICROCHIP_KSZ_SPI=m +# CONFIG_NET_DSA_MICROCHIP_KSZ_PTP is not set +CONFIG_NET_DSA_MICROCHIP_KSZ8863_SMI=m +CONFIG_NET_DSA_MV88E6XXX=m +# CONFIG_NET_DSA_MV88E6XXX_PTP is not set +# CONFIG_NET_DSA_MSCC_OCELOT_EXT is not set +# CONFIG_NET_DSA_MSCC_SEVILLE is not set +CONFIG_NET_DSA_AR9331=m +CONFIG_NET_DSA_QCA8K=m +# CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT is not set +CONFIG_NET_DSA_SJA1105=m +# CONFIG_NET_DSA_SJA1105_PTP is not set +CONFIG_NET_DSA_XRS700X=m +CONFIG_NET_DSA_XRS700X_I2C=m +CONFIG_NET_DSA_XRS700X_MDIO=m +CONFIG_NET_DSA_REALTEK=m +CONFIG_NET_DSA_REALTEK_MDIO=m +CONFIG_NET_DSA_REALTEK_SMI=m +CONFIG_NET_DSA_REALTEK_RTL8365MB=m +CONFIG_NET_DSA_REALTEK_RTL8366RB=m +CONFIG_NET_DSA_SMSC_LAN9303=m +CONFIG_NET_DSA_SMSC_LAN9303_I2C=m +CONFIG_NET_DSA_SMSC_LAN9303_MDIO=m +CONFIG_NET_DSA_VITESSE_VSC73XX=m +CONFIG_NET_DSA_VITESSE_VSC73XX_SPI=m +CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM=m +# end of Distributed Switch Architecture drivers + +CONFIG_ETHERNET=y +CONFIG_MDIO=m +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +CONFIG_ET131X=m +CONFIG_NET_VENDOR_ALACRITECH=y +# CONFIG_SLICOSS is not set +CONFIG_NET_VENDOR_ALTEON=y +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_ALTERA_TSE=m +CONFIG_NET_VENDOR_AMAZON=y +# CONFIG_ENA_ETHERNET is not set +CONFIG_NET_VENDOR_AMD=y +CONFIG_AMD8111_ETH=m +CONFIG_PCNET32=m +CONFIG_AMD_XGBE=m +# CONFIG_AMD_XGBE_DCB is not set +# CONFIG_PDS_CORE is not set +CONFIG_NET_VENDOR_AQUANTIA=y +CONFIG_AQTION=m +CONFIG_NET_VENDOR_ARC=y +# CONFIG_EMAC_ROCKCHIP is not set +CONFIG_NET_VENDOR_ASIX=y +# CONFIG_SPI_AX88796C is not set +CONFIG_NET_VENDOR_ATHEROS=y +CONFIG_ATL2=m +CONFIG_ATL1=m +CONFIG_ATL1E=m +CONFIG_ATL1C=m +CONFIG_ALX=m +CONFIG_NET_VENDOR_BROADCOM=y +CONFIG_B44=m +CONFIG_B44_PCI_AUTOSELECT=y +CONFIG_B44_PCICORE_AUTOSELECT=y +CONFIG_B44_PCI=y +CONFIG_BCMGENET=m +CONFIG_BNX2=m +CONFIG_CNIC=m +CONFIG_TIGON3=m +CONFIG_TIGON3_HWMON=y +CONFIG_BNX2X=m +CONFIG_BNX2X_SRIOV=y +CONFIG_SYSTEMPORT=m +CONFIG_BNXT=m +CONFIG_BNXT_SRIOV=y +CONFIG_BNXT_FLOWER_OFFLOAD=y +# CONFIG_BNXT_DCB is not set +CONFIG_BNXT_HWMON=y +CONFIG_NET_VENDOR_CADENCE=y +CONFIG_MACB=y +CONFIG_MACB_USE_HWSTAMP=y +# CONFIG_MACB_PCI is not set +CONFIG_NET_VENDOR_CAVIUM=y +CONFIG_THUNDER_NIC_PF=y +# CONFIG_THUNDER_NIC_VF is not set +CONFIG_THUNDER_NIC_BGX=y +CONFIG_THUNDER_NIC_RGX=y +CONFIG_CAVIUM_PTP=y +# CONFIG_LIQUIDIO is not set +# CONFIG_LIQUIDIO_VF is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +CONFIG_NET_VENDOR_CORTINA=y +# CONFIG_GEMINI_ETHERNET is not set +CONFIG_NET_VENDOR_DAVICOM=y +# CONFIG_DM9051 is not set +CONFIG_DNET=m +CONFIG_NET_VENDOR_DEC=y +# CONFIG_NET_TULIP is not set +CONFIG_NET_VENDOR_DLINK=y +CONFIG_DL2K=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_ENGLEDER=y +# CONFIG_TSNEP is not set +CONFIG_NET_VENDOR_EZCHIP=y +# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set +CONFIG_NET_VENDOR_FUNGIBLE=y +# CONFIG_FUN_ETH is not set +CONFIG_NET_VENDOR_GOOGLE=y +# CONFIG_GVE is not set +CONFIG_NET_VENDOR_HISILICON=y +CONFIG_HIX5HD2_GMAC=y +# CONFIG_HISI_FEMAC is not set +# CONFIG_HIP04_ETH is not set +CONFIG_HNS_MDIO=y +CONFIG_HNS=y +CONFIG_HNS_DSAF=y +CONFIG_HNS_ENET=y +CONFIG_HNS3=y +CONFIG_HNS3_HCLGE=y +# CONFIG_HNS3_DCB is not set +# CONFIG_HNS3_HCLGEVF is not set +CONFIG_HNS3_ENET=y +CONFIG_NET_VENDOR_HUAWEI=y +# CONFIG_HINIC is not set +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_INTEL=y +CONFIG_E100=m +CONFIG_E1000=m +CONFIG_E1000E=m +CONFIG_IGB=m +CONFIG_IGB_HWMON=y +CONFIG_IGBVF=m +CONFIG_IXGBE=m +CONFIG_IXGBE_HWMON=y +CONFIG_IXGBE_DCB=y +CONFIG_IXGBE_IPSEC=y +CONFIG_IXGBEVF=m +CONFIG_IXGBEVF_IPSEC=y +CONFIG_I40E=m +# CONFIG_I40E_DCB is not set +CONFIG_IAVF=m +CONFIG_I40EVF=m +# CONFIG_ICE is not set +CONFIG_FM10K=m +# CONFIG_IGC is not set +# CONFIG_IDPF is not set +CONFIG_JME=m +CONFIG_NET_VENDOR_ADI=y +CONFIG_ADIN1110=m +CONFIG_NET_VENDOR_LITEX=y +CONFIG_LITEX_LITEETH=m +CONFIG_NET_VENDOR_MARVELL=y +CONFIG_MVMDIO=m +CONFIG_SKGE=m +# CONFIG_SKGE_DEBUG is not set +CONFIG_SKGE_GENESIS=y +CONFIG_SKY2=m +# CONFIG_SKY2_DEBUG is not set +CONFIG_OCTEONTX2_MBOX=m +# CONFIG_OCTEONTX2_AF is not set +CONFIG_OCTEONTX2_PF=m +CONFIG_OCTEONTX2_VF=m +# CONFIG_OCTEON_EP is not set +# CONFIG_PRESTERA is not set +CONFIG_NET_VENDOR_MELLANOX=y +CONFIG_MLX4_EN=m +CONFIG_MLX4_EN_DCB=y +CONFIG_MLX4_CORE=m +CONFIG_MLX4_DEBUG=y +CONFIG_MLX4_CORE_GEN2=y +CONFIG_MLX5_CORE=m +# CONFIG_MLX5_FPGA is not set +CONFIG_MLX5_CORE_EN=y +CONFIG_MLX5_EN_ARFS=y +CONFIG_MLX5_EN_RXNFC=y +CONFIG_MLX5_MPFS=y +CONFIG_MLX5_ESWITCH=y +CONFIG_MLX5_BRIDGE=y +CONFIG_MLX5_CORE_EN_DCB=y +# CONFIG_MLX5_CORE_IPOIB is not set +# CONFIG_MLX5_MACSEC is not set +# CONFIG_MLX5_EN_IPSEC is not set +# CONFIG_MLX5_EN_TLS is not set +CONFIG_MLX5_SW_STEERING=y +# CONFIG_MLX5_SF is not set +# CONFIG_MLX5_DPLL is not set +# CONFIG_MLXSW_CORE is not set +# CONFIG_MLXFW is not set +CONFIG_MLXBF_GIGE=m +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +CONFIG_KSZ884X_PCI=m +CONFIG_NET_VENDOR_MICROCHIP=y +CONFIG_ENC28J60=m +CONFIG_ENC28J60_WRITEVERIFY=y +# CONFIG_ENCX24J600 is not set +# CONFIG_LAN743X is not set +# CONFIG_LAN966X_SWITCH is not set +# CONFIG_VCAP is not set +CONFIG_NET_VENDOR_MICROSEMI=y +CONFIG_MSCC_OCELOT_SWITCH_LIB=m +CONFIG_MSCC_OCELOT_SWITCH=m +CONFIG_NET_VENDOR_MICROSOFT=y +CONFIG_NET_VENDOR_MYRI=y +CONFIG_MYRI10GE=m +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NI=y +# CONFIG_NI_XGE_MANAGEMENT_ENET is not set +CONFIG_NET_VENDOR_NATSEMI=y +CONFIG_NATSEMI=m +CONFIG_NS83820=m +CONFIG_NET_VENDOR_NETERION=y +# CONFIG_S2IO is not set +CONFIG_NET_VENDOR_NETRONOME=y +# CONFIG_NFP is not set +CONFIG_NET_VENDOR_8390=y +CONFIG_NE2K_PCI=m +CONFIG_NET_VENDOR_NVIDIA=y +CONFIG_FORCEDETH=m +CONFIG_NET_VENDOR_OKI=y +CONFIG_ETHOC=m +CONFIG_NET_VENDOR_PACKET_ENGINES=y +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_NET_VENDOR_PENSANDO=y +CONFIG_IONIC=m +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_QED is not set +CONFIG_NET_VENDOR_BROCADE=y +CONFIG_BNA=m +CONFIG_NET_VENDOR_QUALCOMM=y +CONFIG_QCA7000=m +# CONFIG_QCA7000_SPI is not set +CONFIG_QCA7000_UART=m +CONFIG_QCOM_EMAC=m +CONFIG_RMNET=m +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_REALTEK=y +CONFIG_8139CP=m +CONFIG_8139TOO=m +CONFIG_8139TOO_PIO=y +CONFIG_8139TOO_TUNE_TWISTER=y +CONFIG_8139TOO_8129=y +CONFIG_8139_OLD_RX_RESET=y +CONFIG_R8169=m +CONFIG_R8169_LEDS=y +CONFIG_NET_VENDOR_RENESAS=y +CONFIG_NET_VENDOR_ROCKER=y +CONFIG_ROCKER=m +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +CONFIG_NET_VENDOR_SOLARFLARE=y +# CONFIG_SFC is not set +# CONFIG_SFC_FALCON is not set +# CONFIG_SFC_SIENA is not set +CONFIG_NET_VENDOR_SMSC=y +CONFIG_SMC91X=y +# CONFIG_EPIC100 is not set +CONFIG_SMSC911X=y +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_SOCIONEXT=y +CONFIG_NET_VENDOR_STMICRO=y +CONFIG_STMMAC_ETH=y +# CONFIG_STMMAC_SELFTESTS is not set +CONFIG_STMMAC_PLATFORM=y +# CONFIG_DWMAC_DWC_QOS_ETH is not set +CONFIG_DWMAC_GENERIC=y +CONFIG_DWMAC_ROCKCHIP=y +# CONFIG_DWMAC_INTEL_PLAT is not set +# CONFIG_STMMAC_PCI is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_SYNOPSYS=y +# CONFIG_DWC_XLGMAC is not set +CONFIG_NET_VENDOR_TEHUTI=y +CONFIG_TEHUTI=m +CONFIG_NET_VENDOR_TI=y +# CONFIG_TI_CPSW_PHY_SEL is not set +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VERTEXCOM=y +# CONFIG_MSE102X is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WANGXUN=y +CONFIG_LIBWX=m +CONFIG_NGBE=m +# CONFIG_TXGBE is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +CONFIG_NET_VENDOR_XILINX=y +CONFIG_XILINX_EMACLITE=m +CONFIG_XILINX_LL_TEMAC=m +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_NET_SB1000=y +CONFIG_PHYLINK=y +CONFIG_PHYLIB=y +CONFIG_SWPHY=y +CONFIG_LED_TRIGGER_PHY=y +CONFIG_PHYLIB_LEDS=y +CONFIG_FIXED_PHY=y +CONFIG_SFP=m + +# +# MII PHY device drivers +# +CONFIG_AMD_PHY=m +CONFIG_ADIN_PHY=m +CONFIG_ADIN1100_PHY=m +CONFIG_AQUANTIA_PHY=m +CONFIG_AX88796B_PHY=m +CONFIG_BROADCOM_PHY=m +# CONFIG_BCM54140_PHY is not set +CONFIG_BCM7XXX_PHY=m +CONFIG_BCM84881_PHY=m +CONFIG_BCM87XX_PHY=m +CONFIG_BCM_NET_PHYLIB=m +CONFIG_BCM_NET_PHYPTP=m +CONFIG_CICADA_PHY=m +# CONFIG_CORTINA_PHY is not set +CONFIG_DAVICOM_PHY=m +CONFIG_ICPLUS_PHY=m +CONFIG_LXT_PHY=m +# CONFIG_INTEL_XWAY_PHY is not set +CONFIG_LSI_ET1011C_PHY=m +CONFIG_MARVELL_PHY=m +CONFIG_MARVELL_10G_PHY=m +# CONFIG_MARVELL_88Q2XXX_PHY is not set +CONFIG_MARVELL_88X2222_PHY=m +CONFIG_MAXLINEAR_GPHY=m +CONFIG_MEDIATEK_GE_PHY=m +# CONFIG_MEDIATEK_GE_SOC_PHY is not set +CONFIG_MICREL_PHY=y +# CONFIG_MICROCHIP_T1S_PHY is not set +CONFIG_MICROCHIP_PHY=m +CONFIG_MICROCHIP_T1_PHY=m +CONFIG_MICROSEMI_PHY=m +CONFIG_MOTORCOMM_PHY=y +CONFIG_NATIONAL_PHY=m +# CONFIG_NXP_CBTX_PHY is not set +CONFIG_NXP_C45_TJA11XX_PHY=m +# CONFIG_NXP_TJA11XX_PHY is not set +# CONFIG_NCN26000_PHY is not set +CONFIG_AT803X_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_REALTEK_PHY=y +# CONFIG_RENESAS_PHY is not set +CONFIG_ROCKCHIP_PHY=y +CONFIG_SMSC_PHY=m +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_DP83822_PHY is not set +CONFIG_DP83TC811_PHY=m +CONFIG_DP83848_PHY=m +# CONFIG_DP83867_PHY is not set +CONFIG_DP83869_PHY=m +CONFIG_DP83TD510_PHY=m +# CONFIG_DP83TG720_PHY is not set +CONFIG_VITESSE_PHY=m +# CONFIG_XILINX_GMII2RGMII is not set +# CONFIG_MICREL_KS8995MA is not set +CONFIG_PSE_CONTROLLER=y +CONFIG_PSE_REGULATOR=m +CONFIG_CAN_DEV=m +CONFIG_CAN_VCAN=m +CONFIG_CAN_VXCAN=m +CONFIG_CAN_NETLINK=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RX_OFFLOAD=y +# CONFIG_CAN_CAN327 is not set +# CONFIG_CAN_FLEXCAN is not set +CONFIG_CAN_GRCAN=m +CONFIG_CAN_KVASER_PCIEFD=m +CONFIG_CAN_SLCAN=m +CONFIG_CAN_XILINXCAN=m +CONFIG_CAN_C_CAN=m +CONFIG_CAN_C_CAN_PLATFORM=m +CONFIG_CAN_C_CAN_PCI=m +CONFIG_CAN_CC770=m +CONFIG_CAN_CC770_ISA=m +CONFIG_CAN_CC770_PLATFORM=m +# CONFIG_CAN_CTUCANFD_PCI is not set +# CONFIG_CAN_CTUCANFD_PLATFORM is not set +# CONFIG_CAN_IFI_CANFD is not set +CONFIG_CAN_M_CAN=m +CONFIG_CAN_M_CAN_PCI=m +CONFIG_CAN_M_CAN_PLATFORM=m +CONFIG_CAN_M_CAN_TCAN4X5X=m +CONFIG_CAN_PEAK_PCIEFD=m +CONFIG_CAN_SJA1000=m +CONFIG_CAN_EMS_PCI=m +CONFIG_CAN_F81601=m +CONFIG_CAN_KVASER_PCI=m +CONFIG_CAN_PEAK_PCI=m +CONFIG_CAN_PEAK_PCIEC=y +CONFIG_CAN_PLX_PCI=m +CONFIG_CAN_SJA1000_ISA=m +CONFIG_CAN_SJA1000_PLATFORM=m +CONFIG_CAN_SOFTING=m + +# +# CAN SPI interfaces +# +CONFIG_CAN_HI311X=m +CONFIG_CAN_MCP251X=m +CONFIG_CAN_MCP251XFD=m +# CONFIG_CAN_MCP251XFD_SANITY is not set +# end of CAN SPI interfaces + +# +# CAN USB interfaces +# +CONFIG_CAN_8DEV_USB=m +CONFIG_CAN_EMS_USB=m +CONFIG_CAN_ESD_USB=m +CONFIG_CAN_ETAS_ES58X=m +# CONFIG_CAN_F81604 is not set +CONFIG_CAN_GS_USB=m +CONFIG_CAN_KVASER_USB=m +CONFIG_CAN_MCBA_USB=m +CONFIG_CAN_PEAK_USB=m +CONFIG_CAN_UCAN=m +# end of CAN USB interfaces + +# CONFIG_CAN_DEBUG_DEVICES is not set +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_BUS=y +CONFIG_FWNODE_MDIO=y +CONFIG_OF_MDIO=y +CONFIG_ACPI_MDIO=y +CONFIG_MDIO_DEVRES=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_BCM_UNIMAC=m +CONFIG_MDIO_CAVIUM=y +CONFIG_MDIO_GPIO=m +# CONFIG_MDIO_HISI_FEMAC is not set +CONFIG_MDIO_I2C=m +CONFIG_MDIO_MVUSB=m +CONFIG_MDIO_MSCC_MIIM=m +# CONFIG_MDIO_OCTEON is not set +# CONFIG_MDIO_IPQ4019 is not set +CONFIG_MDIO_IPQ8064=m +CONFIG_MDIO_REGMAP=m +CONFIG_MDIO_THUNDER=y + +# +# MDIO Multiplexers +# +CONFIG_MDIO_BUS_MUX=y +CONFIG_MDIO_BUS_MUX_GPIO=m +CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y +CONFIG_MDIO_BUS_MUX_MMIOREG=y + +# +# PCS device drivers +# +CONFIG_PCS_XPCS=y +CONFIG_PCS_LYNX=m +CONFIG_PCS_MTK_LYNXI=m +# end of PCS device drivers + +CONFIG_PPP=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOATM=m +CONFIG_PPPOE=m +# CONFIG_PPPOE_HASH_BITS_1 is not set +# CONFIG_PPPOE_HASH_BITS_2 is not set +CONFIG_PPPOE_HASH_BITS_4=y +# CONFIG_PPPOE_HASH_BITS_8 is not set +CONFIG_PPPOE_HASH_BITS=4 +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_SLIP=m +CONFIG_SLHC=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y +CONFIG_USB_NET_DRIVERS=y +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_LAN78XX=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SR9800=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET_ENABLE=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_CDC_PHONET=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_USB_NET_CH9200=m +CONFIG_USB_NET_AQC111=m +CONFIG_USB_RTL8153_ECM=m +CONFIG_WLAN=y +CONFIG_WLAN_VENDOR_ADMTEK=y +CONFIG_ADM8211=m +CONFIG_ATH_COMMON=m +CONFIG_WLAN_VENDOR_ATH=y +# CONFIG_ATH_DEBUG is not set +CONFIG_ATH5K=m +# CONFIG_ATH5K_DEBUG is not set +# CONFIG_ATH5K_TRACER is not set +CONFIG_ATH5K_PCI=y +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +CONFIG_ATH9K_PCI=y +CONFIG_ATH9K_AHB=y +CONFIG_ATH9K_DYNACK=y +CONFIG_ATH9K_WOW=y +CONFIG_ATH9K_RFKILL=y +CONFIG_ATH9K_CHANNEL_CONTEXT=y +CONFIG_ATH9K_PCOEM=y +CONFIG_ATH9K_PCI_NO_EEPROM=m +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set +CONFIG_ATH9K_HWRNG=y +CONFIG_CARL9170=m +CONFIG_CARL9170_LEDS=y +CONFIG_CARL9170_WPC=y +CONFIG_CARL9170_HWRNG=y +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +CONFIG_ATH6KL_USB=m +# CONFIG_ATH6KL_DEBUG is not set +# CONFIG_ATH6KL_TRACING is not set +CONFIG_AR5523=m +CONFIG_WIL6210=m +CONFIG_WIL6210_ISR_COR=y +# CONFIG_WIL6210_TRACING is not set +# CONFIG_WIL6210_DEBUGFS is not set +CONFIG_ATH10K=m +CONFIG_ATH10K_CE=y +CONFIG_ATH10K_PCI=m +CONFIG_ATH10K_AHB=y +CONFIG_ATH10K_SDIO=m +CONFIG_ATH10K_USB=m +# CONFIG_ATH10K_DEBUG is not set +# CONFIG_ATH10K_DEBUGFS is not set +# CONFIG_ATH10K_TRACING is not set +CONFIG_WCN36XX=m +# CONFIG_WCN36XX_DEBUGFS is not set +CONFIG_ATH11K=m +CONFIG_ATH11K_AHB=m +# CONFIG_ATH11K_PCI is not set +# CONFIG_ATH11K_DEBUG is not set +# CONFIG_ATH11K_TRACING is not set +# CONFIG_ATH12K is not set +CONFIG_WLAN_VENDOR_ATMEL=y +CONFIG_AT76C50X_USB=m +CONFIG_WLAN_VENDOR_BROADCOM=y +CONFIG_B43=m +CONFIG_B43_BCMA=y +CONFIG_B43_SSB=y +CONFIG_B43_BUSES_BCMA_AND_SSB=y +# CONFIG_B43_BUSES_BCMA is not set +# CONFIG_B43_BUSES_SSB is not set +CONFIG_B43_PCI_AUTOSELECT=y +CONFIG_B43_PCICORE_AUTOSELECT=y +CONFIG_B43_SDIO=y +CONFIG_B43_BCMA_PIO=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_G=y +CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_PHY_HT=y +CONFIG_B43_LEDS=y +CONFIG_B43_HWRNG=y +# CONFIG_B43_DEBUG is not set +CONFIG_B43LEGACY=m +CONFIG_B43LEGACY_PCI_AUTOSELECT=y +CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y +CONFIG_B43LEGACY_LEDS=y +CONFIG_B43LEGACY_HWRNG=y +# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_PIO=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +# CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_BRCMUTIL=m +CONFIG_BRCMSMAC=m +CONFIG_BRCMSMAC_LEDS=y +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_PROTO_BCDC=y +CONFIG_BRCMFMAC_PROTO_MSGBUF=y +CONFIG_BRCMFMAC_SDIO=y +CONFIG_BRCMFMAC_USB=y +CONFIG_BRCMFMAC_PCIE=y +CONFIG_BRCM_TRACING=y +# CONFIG_BRCMDBG is not set +CONFIG_WLAN_VENDOR_INTEL=y +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_LIBIPW=m +# CONFIG_LIBIPW_DEBUG is not set +CONFIG_IWLEGACY=m +CONFIG_IWL4965=m +CONFIG_IWL3945=m + +# +# iwl3945 / iwl4965 Debugging Options +# +# CONFIG_IWLEGACY_DEBUG is not set +# end of iwl3945 / iwl4965 Debugging Options + +CONFIG_IWLWIFI=m +CONFIG_IWLWIFI_LEDS=y +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y + +# +# Debugging Options +# +# CONFIG_IWLWIFI_DEBUG is not set +CONFIG_IWLWIFI_DEVICE_TRACING=y +# end of Debugging Options + +CONFIG_WLAN_VENDOR_INTERSIL=y +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +# CONFIG_P54_PCI is not set +CONFIG_P54_SPI=m +CONFIG_P54_SPI_DEFAULT_EEPROM=y +CONFIG_P54_LEDS=y +CONFIG_WLAN_VENDOR_MARVELL=y +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_DEBUG is not set +CONFIG_LIBERTAS_MESH=y +CONFIG_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_MWIFIEX_PCIE=m +CONFIG_MWIFIEX_USB=m +CONFIG_MWL8K=m +CONFIG_WLAN_VENDOR_MEDIATEK=y +CONFIG_MT7601U=m +CONFIG_MT76_CORE=m +CONFIG_MT76_LEDS=y +CONFIG_MT76_USB=m +CONFIG_MT76_SDIO=m +CONFIG_MT76x02_LIB=m +CONFIG_MT76x02_USB=m +CONFIG_MT76_CONNAC_LIB=m +CONFIG_MT792x_LIB=m +CONFIG_MT792x_USB=m +CONFIG_MT76x0_COMMON=m +CONFIG_MT76x0U=m +CONFIG_MT76x0E=m +CONFIG_MT76x2_COMMON=m +CONFIG_MT76x2E=m +CONFIG_MT76x2U=m +CONFIG_MT7603E=m +CONFIG_MT7615_COMMON=m +CONFIG_MT7615E=m +CONFIG_MT7663_USB_SDIO_COMMON=m +CONFIG_MT7663U=m +CONFIG_MT7663S=m +CONFIG_MT7915E=m +CONFIG_MT7921_COMMON=m +CONFIG_MT7921E=m +CONFIG_MT7921S=m +CONFIG_MT7921U=m +CONFIG_MT7996E=m +CONFIG_MT7925_COMMON=m +CONFIG_MT7925E=m +CONFIG_MT7925U=m +CONFIG_WLAN_VENDOR_MICROCHIP=y +CONFIG_WILC1000=m +CONFIG_WILC1000_SDIO=m +CONFIG_WILC1000_SPI=m +# CONFIG_WILC1000_HW_OOB_INTR is not set +CONFIG_WLAN_VENDOR_PURELIFI=y +# CONFIG_PLFXLC is not set +CONFIG_WLAN_VENDOR_RALINK=y +CONFIG_RT2X00=m +CONFIG_RT2400PCI=m +CONFIG_RT2500PCI=m +CONFIG_RT61PCI=m +CONFIG_RT2800PCI=m +CONFIG_RT2800PCI_RT33XX=y +CONFIG_RT2800PCI_RT35XX=y +CONFIG_RT2800PCI_RT53XX=y +CONFIG_RT2800PCI_RT3290=y +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RT2800_LIB=m +CONFIG_RT2800_LIB_MMIO=m +CONFIG_RT2X00_LIB_MMIO=m +CONFIG_RT2X00_LIB_PCI=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +CONFIG_WLAN_VENDOR_REALTEK=y +CONFIG_RTL8180=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +CONFIG_RTL_CARDS=m +CONFIG_RTL8192CE=m +CONFIG_RTL8192SE=m +CONFIG_RTL8192DE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8188EE=m +CONFIG_RTL8192EE=m +CONFIG_RTL8821AE=m +CONFIG_RTL8192CU=m +CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_PCI=m +CONFIG_RTLWIFI_USB=m +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8192C_COMMON=m +CONFIG_RTL8723_COMMON=m +CONFIG_RTLBTCOEXIST=m +CONFIG_RTL8XXXU=m +# CONFIG_RTL8XXXU_UNTESTED is not set +CONFIG_RTW88=m +CONFIG_RTW88_CORE=m +CONFIG_RTW88_PCI=m +CONFIG_RTW88_USB=m +CONFIG_RTW88_8822B=m +CONFIG_RTW88_8822C=m +CONFIG_RTW88_8723D=m +CONFIG_RTW88_8821C=m +CONFIG_RTW88_8822BE=m +# CONFIG_RTW88_8822BS is not set +CONFIG_RTW88_8822BU=m +CONFIG_RTW88_8822CE=m +# CONFIG_RTW88_8822CS is not set +CONFIG_RTW88_8822CU=m +CONFIG_RTW88_8723DE=m +# CONFIG_RTW88_8723DS is not set +CONFIG_RTW88_8723DU=m +CONFIG_RTW88_8821CE=m +# CONFIG_RTW88_8821CS is not set +CONFIG_RTW88_8821CU=m +# CONFIG_RTW88_DEBUG is not set +# CONFIG_RTW88_DEBUGFS is not set +CONFIG_RTW89=m +CONFIG_RTW89_CORE=m +CONFIG_RTW89_PCI=m +CONFIG_RTW89_8851B=m +CONFIG_RTW89_8852A=m +CONFIG_RTW89_8852B=m +CONFIG_RTW89_8852C=m +CONFIG_RTW89_8851BE=m +CONFIG_RTW89_8852AE=m +CONFIG_RTW89_8852BE=m +CONFIG_RTW89_8852CE=m +# CONFIG_RTW89_DEBUGMSG is not set +# CONFIG_RTW89_DEBUGFS is not set +CONFIG_WLAN_VENDOR_RSI=y +CONFIG_RSI_91X=m +# CONFIG_RSI_DEBUGFS is not set +CONFIG_RSI_SDIO=m +CONFIG_RSI_USB=m +CONFIG_RSI_COEX=y +CONFIG_WLAN_VENDOR_SILABS=y +CONFIG_WFX=m +CONFIG_WLAN_VENDOR_ST=y +CONFIG_CW1200=m +CONFIG_CW1200_WLAN_SDIO=m +CONFIG_CW1200_WLAN_SPI=m +CONFIG_WLAN_VENDOR_TI=y +CONFIG_WL1251=m +CONFIG_WL1251_SPI=m +CONFIG_WL1251_SDIO=m +CONFIG_WL12XX=m +CONFIG_WL18XX=m +CONFIG_WLCORE=m +CONFIG_WLCORE_SPI=m +CONFIG_WLCORE_SDIO=m +# CONFIG_RTL8723DS is not set +# CONFIG_RTL8822BU is not set +# CONFIG_RTL8821CU is not set +# CONFIG_88XXAU is not set +# CONFIG_RTL8192EU is not set +# CONFIG_RTL8189ES is not set +CONFIG_WLAN_VENDOR_ZYDAS=y +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_WLAN_VENDOR_QUANTENNA=y +CONFIG_QTNFMAC=m +CONFIG_QTNFMAC_PCIE=m +CONFIG_MAC80211_HWSIM=m +CONFIG_VIRT_WIFI=m +CONFIG_WAN=y +CONFIG_HDLC=m +CONFIG_HDLC_RAW=m +CONFIG_HDLC_RAW_ETH=m +# CONFIG_HDLC_CISCO is not set +# CONFIG_HDLC_FR is not set +# CONFIG_HDLC_PPP is not set +# CONFIG_HDLC_X25 is not set +# CONFIG_FRAMER is not set +# CONFIG_PCI200SYN is not set +# CONFIG_WANXL is not set +# CONFIG_PC300TOO is not set +# CONFIG_FARSYNC is not set +# CONFIG_LAPBETHER is not set +CONFIG_IEEE802154_DRIVERS=m +CONFIG_IEEE802154_FAKELB=m +CONFIG_IEEE802154_AT86RF230=m +CONFIG_IEEE802154_MRF24J40=m +CONFIG_IEEE802154_CC2520=m +CONFIG_IEEE802154_ATUSB=m +CONFIG_IEEE802154_ADF7242=m +CONFIG_IEEE802154_CA8210=m +# CONFIG_IEEE802154_CA8210_DEBUGFS is not set +CONFIG_IEEE802154_MCR20A=m +CONFIG_IEEE802154_HWSIM=m + +# +# Wireless WAN +# +CONFIG_WWAN=m +CONFIG_WWAN_DEBUGFS=y +CONFIG_WWAN_HWSIM=m +CONFIG_MHI_WWAN_CTRL=m +CONFIG_MHI_WWAN_MBIM=m +CONFIG_RPMSG_WWAN_CTRL=m +CONFIG_IOSM=m +CONFIG_MTK_T7XX=m +# end of Wireless WAN + +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_NETDEV_BACKEND=m +CONFIG_VMXNET3=m +CONFIG_FUJITSU_ES=m +CONFIG_NETDEVSIM=m +CONFIG_NET_FAILOVER=y +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_LEDS=y +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_SPARSEKMAP=m +CONFIG_INPUT_MATRIXKMAP=y +CONFIG_INPUT_VIVALDIFMAP=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_KUNIT_TEST is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ADC=m +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +CONFIG_KEYBOARD_QT1050=m +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_GPIO_POLLED=m +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_PINEPHONE is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_KEYBOARD_CROS_EC=y +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +# CONFIG_KEYBOARD_CYPRESS_SF is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_BYD=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y +CONFIG_MOUSE_PS2_CYPRESS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_FOCALTECH=y +CONFIG_MOUSE_PS2_SMBUS=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_CYAPA is not set +# CONFIG_MOUSE_ELAN_I2C is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +CONFIG_MOUSE_SYNAPTICS_I2C=m +CONFIG_MOUSE_SYNAPTICS_USB=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADC=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=m +CONFIG_JOYSTICK_IFORCE_232=m +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_JOYSTICK_AS5011=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_PSXPAD_SPI=m +CONFIG_JOYSTICK_PSXPAD_SPI_FF=y +CONFIG_JOYSTICK_PXRC=m +CONFIG_JOYSTICK_QWIIC=m +CONFIG_JOYSTICK_FSIA6B=m +CONFIG_JOYSTICK_SENSEHAT=m +# CONFIG_JOYSTICK_SEESAW is not set +CONFIG_INPUT_TABLET=y +# CONFIG_TABLET_USB_ACECAD is not set +# CONFIG_TABLET_USB_AIPTEK is not set +# CONFIG_TABLET_USB_HANWANG is not set +# CONFIG_TABLET_USB_KBTAB is not set +# CONFIG_TABLET_USB_PEGASUS is not set +# CONFIG_TABLET_SERIAL_WACOM4 is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_AD7879=m +CONFIG_TOUCHSCREEN_AD7879_I2C=m +CONFIG_TOUCHSCREEN_AD7879_SPI=m +CONFIG_TOUCHSCREEN_ADC=m +CONFIG_TOUCHSCREEN_AR1021_I2C=m +CONFIG_TOUCHSCREEN_ATMEL_MXT=m +CONFIG_TOUCHSCREEN_ATMEL_MXT_T37=y +CONFIG_TOUCHSCREEN_AUO_PIXCIR=m +CONFIG_TOUCHSCREEN_BU21013=m +CONFIG_TOUCHSCREEN_BU21029=m +CONFIG_TOUCHSCREEN_CHIPONE_ICN8318=m +CONFIG_TOUCHSCREEN_CHIPONE_ICN8505=m +CONFIG_TOUCHSCREEN_CY8CTMA140=m +CONFIG_TOUCHSCREEN_CY8CTMG110=m +CONFIG_TOUCHSCREEN_CYTTSP_CORE=m +CONFIG_TOUCHSCREEN_CYTTSP_I2C=m +CONFIG_TOUCHSCREEN_CYTTSP_SPI=m +CONFIG_TOUCHSCREEN_CYTTSP4_CORE=m +CONFIG_TOUCHSCREEN_CYTTSP4_I2C=m +CONFIG_TOUCHSCREEN_CYTTSP4_SPI=m +# CONFIG_TOUCHSCREEN_CYTTSP5 is not set +CONFIG_TOUCHSCREEN_DYNAPRO=m +CONFIG_TOUCHSCREEN_HAMPSHIRE=m +CONFIG_TOUCHSCREEN_EETI=m +CONFIG_TOUCHSCREEN_EGALAX=m +CONFIG_TOUCHSCREEN_EGALAX_SERIAL=m +CONFIG_TOUCHSCREEN_EXC3000=m +CONFIG_TOUCHSCREEN_FUJITSU=m +CONFIG_TOUCHSCREEN_GOODIX=m +CONFIG_TOUCHSCREEN_HIDEEP=m +CONFIG_TOUCHSCREEN_HYCON_HY46XX=m +# CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX is not set +CONFIG_TOUCHSCREEN_ILI210X=m +CONFIG_TOUCHSCREEN_ILITEK=m +CONFIG_TOUCHSCREEN_S6SY761=m +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_EKTF2127=m +CONFIG_TOUCHSCREEN_ELAN=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_WACOM_W8001=m +CONFIG_TOUCHSCREEN_WACOM_I2C=m +CONFIG_TOUCHSCREEN_MAX11801=m +CONFIG_TOUCHSCREEN_MCS5000=m +CONFIG_TOUCHSCREEN_MMS114=m +CONFIG_TOUCHSCREEN_MELFAS_MIP4=m +CONFIG_TOUCHSCREEN_MSG2638=m +CONFIG_TOUCHSCREEN_MTOUCH=m +# CONFIG_TOUCHSCREEN_NOVATEK_NVT_TS is not set +CONFIG_TOUCHSCREEN_IMAGIS=m +CONFIG_TOUCHSCREEN_IMX6UL_TSC=m +CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_EDT_FT5X06=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_PIXCIR=m +CONFIG_TOUCHSCREEN_WDT87XX_I2C=m +CONFIG_TOUCHSCREEN_WM97XX=m +CONFIG_TOUCHSCREEN_WM9705=y +CONFIG_TOUCHSCREEN_WM9712=y +CONFIG_TOUCHSCREEN_WM9713=y +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_JASTEC=y +CONFIG_TOUCHSCREEN_USB_ELO=y +CONFIG_TOUCHSCREEN_USB_E2I=y +CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y +CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y +CONFIG_TOUCHSCREEN_USB_NEXIO=y +CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y +CONFIG_TOUCHSCREEN_TOUCHIT213=m +CONFIG_TOUCHSCREEN_TSC_SERIO=m +CONFIG_TOUCHSCREEN_TSC200X_CORE=m +CONFIG_TOUCHSCREEN_TSC2004=m +CONFIG_TOUCHSCREEN_TSC2005=m +CONFIG_TOUCHSCREEN_TSC2007=m +CONFIG_TOUCHSCREEN_TSC2007_IIO=y +CONFIG_TOUCHSCREEN_RM_TS=m +CONFIG_TOUCHSCREEN_SILEAD=m +CONFIG_TOUCHSCREEN_SIS_I2C=m +CONFIG_TOUCHSCREEN_ST1232=m +CONFIG_TOUCHSCREEN_STMFTS=m +CONFIG_TOUCHSCREEN_SUR40=m +CONFIG_TOUCHSCREEN_SURFACE3_SPI=m +CONFIG_TOUCHSCREEN_SX8654=m +CONFIG_TOUCHSCREEN_TPS6507X=m +CONFIG_TOUCHSCREEN_ZET6223=m +CONFIG_TOUCHSCREEN_ZFORCE=m +CONFIG_TOUCHSCREEN_COLIBRI_VF50=m +CONFIG_TOUCHSCREEN_ROHM_BU21023=m +CONFIG_TOUCHSCREEN_IQS5XX=m +# CONFIG_TOUCHSCREEN_IQS7211 is not set +CONFIG_TOUCHSCREEN_ZINITIX=m +# CONFIG_TOUCHSCREEN_HIMAX_HX83112B is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_ATMEL_CAPTOUCH is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_MMA8450 is not set +CONFIG_INPUT_GPIO_BEEPER=m +CONFIG_INPUT_GPIO_DECODER=m +CONFIG_INPUT_GPIO_VIBRA=m +CONFIG_INPUT_ATI_REMOTE2=m +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +CONFIG_INPUT_UINPUT=m +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_PWM_VIBRA is not set +# CONFIG_INPUT_RK805_PWRKEY is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +CONFIG_INPUT_DA7280_HAPTICS=m +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IBM_PANEL is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_IQS269A is not set +CONFIG_INPUT_IQS626A=m +CONFIG_INPUT_IQS7222=m +# CONFIG_INPUT_CMA3000 is not set +CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y +CONFIG_INPUT_SOC_BUTTON_ARRAY=m +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set +CONFIG_RMI4_CORE=m +CONFIG_RMI4_I2C=m +CONFIG_RMI4_SPI=m +CONFIG_RMI4_SMB=m +CONFIG_RMI4_F03=y +CONFIG_RMI4_F03_SERIO=m +CONFIG_RMI4_2D_SENSOR=y +CONFIG_RMI4_F11=y +CONFIG_RMI4_F12=y +CONFIG_RMI4_F30=y +CONFIG_RMI4_F34=y +CONFIG_RMI4_F3A=y +CONFIG_RMI4_F54=y +CONFIG_RMI4_F55=y + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_AMBAKMI=y +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_SERIO_ALTERA_PS2=m +# CONFIG_SERIO_PS2MULT is not set +CONFIG_SERIO_ARC_PS2=m +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_SERIO_GPIO_PS2 is not set +# CONFIG_USERIO is not set +CONFIG_GAMEPORT=m +# CONFIG_GAMEPORT_EMU10K1 is not set +# CONFIG_GAMEPORT_FM801 is not set +# end of Hardware I/O ports +# end of Input device support + +# +# Character devices +# +CONFIG_TTY=y +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=16 +CONFIG_LEGACY_TIOCSTI=y +CONFIG_LDISC_AUTOLOAD=y + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_16550A_VARIANTS=y +CONFIG_SERIAL_8250_FINTEK=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DMA=y +CONFIG_SERIAL_8250_PCILIB=y +CONFIG_SERIAL_8250_PCI=m +CONFIG_SERIAL_8250_EXAR=m +CONFIG_SERIAL_8250_NR_UARTS=8 +CONFIG_SERIAL_8250_RUNTIME_UARTS=8 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +# CONFIG_SERIAL_8250_PCI1XXXX is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_DWLIB=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_DW=y +# CONFIG_SERIAL_8250_RT288X is not set +CONFIG_SERIAL_8250_PERICOM=y +CONFIG_SERIAL_OF_PLATFORM=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AMBA_PL010=y +CONFIG_SERIAL_AMBA_PL010_CONSOLE=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# CONFIG_SERIAL_EARLYCON_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_SERIAL_SIFIVE=m +CONFIG_SERIAL_SCCNXP=y +CONFIG_SERIAL_SCCNXP_CONSOLE=y +CONFIG_SERIAL_SC16IS7XX_CORE=m +CONFIG_SERIAL_SC16IS7XX=m +CONFIG_SERIAL_SC16IS7XX_I2C=y +CONFIG_SERIAL_SC16IS7XX_SPI=y +CONFIG_SERIAL_ALTERA_JTAGUART=m +CONFIG_SERIAL_ALTERA_UART=m +CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4 +CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200 +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +CONFIG_SERIAL_ARC=m +CONFIG_SERIAL_ARC_NR_PORTS=1 +CONFIG_SERIAL_RP2=m +CONFIG_SERIAL_RP2_NR_UARTS=32 +CONFIG_SERIAL_FSL_LPUART=m +CONFIG_SERIAL_FSL_LINFLEXUART=m +CONFIG_SERIAL_CONEXANT_DIGICOLOR=m +CONFIG_SERIAL_SPRD=m +CONFIG_SERIAL_LITEUART=m +CONFIG_SERIAL_LITEUART_MAX_PORTS=1 +# end of Serial drivers + +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_MOXA_INTELLIO=m +CONFIG_MOXA_SMARTIO=m +CONFIG_N_HDLC=m +CONFIG_N_GSM=m +CONFIG_NOZOMI=m +CONFIG_NULL_TTY=m +CONFIG_HVC_DRIVER=y +CONFIG_HVC_IRQ=y +CONFIG_HVC_XEN=y +CONFIG_HVC_XEN_FRONTEND=y +# CONFIG_HVC_DCC is not set +CONFIG_RPMSG_TTY=m +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +# CONFIG_TTY_PRINTK is not set +CONFIG_VIRTIO_CONSOLE=y +CONFIG_IPMI_HANDLER=m +CONFIG_IPMI_DMI_DECODE=y +CONFIG_IPMI_PLAT_DATA=y +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +# CONFIG_IPMI_SSIF is not set +CONFIG_IPMI_IPMB=m +# CONFIG_IPMI_WATCHDOG is not set +# CONFIG_IPMI_POWEROFF is not set +# CONFIG_SSIF_IPMI_BMC is not set +# CONFIG_IPMB_DEVICE_INTERFACE is not set +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_TIMERIOMEM=m +# CONFIG_HW_RANDOM_BA431 is not set +CONFIG_HW_RANDOM_VIRTIO=m +CONFIG_HW_RANDOM_OPTEE=m +# CONFIG_HW_RANDOM_CCTRNG is not set +# CONFIG_HW_RANDOM_XIPHERA is not set +CONFIG_HW_RANDOM_ROCKCHIP=m +CONFIG_HW_RANDOM_ARM_SMCCC_TRNG=m +CONFIG_HW_RANDOM_CN10K=y +# CONFIG_APPLICOM is not set +CONFIG_DEVMEM=y +CONFIG_DEVPORT=y +CONFIG_TCG_TPM=y +CONFIG_HW_RANDOM_TPM=y +# CONFIG_TCG_TIS is not set +# CONFIG_TCG_TIS_SPI is not set +# CONFIG_TCG_TIS_I2C is not set +CONFIG_TCG_TIS_I2C_CR50=m +# CONFIG_TCG_TIS_I2C_ATMEL is not set +CONFIG_TCG_TIS_I2C_INFINEON=y +# CONFIG_TCG_TIS_I2C_NUVOTON is not set +# CONFIG_TCG_ATMEL is not set +# CONFIG_TCG_INFINEON is not set +# CONFIG_TCG_XEN is not set +CONFIG_TCG_CRB=y +# CONFIG_TCG_VTPM_PROXY is not set +# CONFIG_TCG_FTPM_TEE is not set +# CONFIG_TCG_TIS_ST33ZP24_I2C is not set +# CONFIG_TCG_TIS_ST33ZP24_SPI is not set +CONFIG_XILLYBUS_CLASS=m +# CONFIG_XILLYBUS is not set +CONFIG_XILLYUSB=m +# end of Character devices + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_ACPI_I2C_OPREGION=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +CONFIG_I2C_ARB_GPIO_CHALLENGE=m +CONFIG_I2C_MUX_GPIO=m +CONFIG_I2C_MUX_GPMUX=m +CONFIG_I2C_MUX_LTC4306=m +CONFIG_I2C_MUX_PCA9541=m +CONFIG_I2C_MUX_PCA954x=m +CONFIG_I2C_MUX_PINCTRL=m +CONFIG_I2C_MUX_REG=m +CONFIG_I2C_DEMUX_PINCTRL=m +CONFIG_I2C_MUX_MLXCPLD=m +# end of Multiplexer I2C Chip support + +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_SMBUS=m +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +CONFIG_I2C_CCGX_UCSI=m +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_AMD_MP2 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_NVIDIA_GPU is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# ACPI drivers +# +CONFIG_I2C_SCMI=m + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_CADENCE=m +CONFIG_I2C_CBUS_GPIO=m +CONFIG_I2C_DESIGNWARE_CORE=y +# CONFIG_I2C_DESIGNWARE_SLAVE is not set +CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_I2C_DESIGNWARE_PCI=m +CONFIG_I2C_EMEV2=m +CONFIG_I2C_GPIO=m +CONFIG_I2C_GPIO_FAULT_INJECTOR=y +CONFIG_I2C_HISI=m +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PCA_PLATFORM=m +CONFIG_I2C_RK3X=y +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_THUNDERX is not set +CONFIG_I2C_XILINX=m + +# +# External I2C/SMBus adapter drivers +# +CONFIG_I2C_DIOLAN_U2C=m +CONFIG_I2C_CP2615=m +CONFIG_I2C_PCI1XXXX=m +CONFIG_I2C_ROBOTFUZZ_OSIF=m +CONFIG_I2C_TAOS_EVM=m +CONFIG_I2C_TINY_USB=m + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_MLXCPLD is not set +CONFIG_I2C_CROS_EC_TUNNEL=y +CONFIG_I2C_VIRTIO=m +# end of I2C Hardware Bus support + +CONFIG_I2C_STUB=m +CONFIG_I2C_SLAVE=y +CONFIG_I2C_SLAVE_EEPROM=m +CONFIG_I2C_SLAVE_TESTUNIT=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# end of I2C support + +CONFIG_I3C=m +CONFIG_CDNS_I3C_MASTER=m +CONFIG_DW_I3C_MASTER=m +CONFIG_SVC_I3C_MASTER=m +CONFIG_MIPI_I3C_HCI=m +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_ALTERA=m +CONFIG_SPI_ALTERA_CORE=m +CONFIG_SPI_AXI_SPI_ENGINE=m +CONFIG_SPI_BITBANG=m +CONFIG_SPI_CADENCE=m +CONFIG_SPI_CADENCE_QUADSPI=y +CONFIG_SPI_CADENCE_XSPI=m +CONFIG_SPI_DESIGNWARE=m +# CONFIG_SPI_DW_DMA is not set +CONFIG_SPI_DW_PCI=m +CONFIG_SPI_DW_MMIO=m +CONFIG_SPI_HISI_KUNPENG=m +CONFIG_SPI_HISI_SFC_V3XX=m +CONFIG_SPI_GPIO=m +CONFIG_SPI_FSL_LIB=m +CONFIG_SPI_FSL_SPI=m +CONFIG_SPI_MICROCHIP_CORE=m +CONFIG_SPI_MICROCHIP_CORE_QSPI=m +CONFIG_SPI_OC_TINY=m +# CONFIG_SPI_PCI1XXXX is not set +CONFIG_SPI_PL022=y +# CONFIG_SPI_PXA2XX is not set +CONFIG_SPI_ROCKCHIP=y +CONFIG_SPI_ROCKCHIP_SFC=y +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_SN_F_OSPI is not set +CONFIG_SPI_MXIC=m +# CONFIG_SPI_THUNDERX is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_SPI_AMD is not set + +# +# SPI Multiplexer support +# +CONFIG_SPI_MUX=m + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=m +CONFIG_SPI_LOOPBACK_TEST=m +CONFIG_SPI_TLE62X0=m +CONFIG_SPI_SLAVE=y +CONFIG_SPI_SLAVE_TIME=m +CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m +CONFIG_SPI_DYNAMIC=y +CONFIG_SPMI=y +# CONFIG_SPMI_HISI3670 is not set +# CONFIG_HSI is not set +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +CONFIG_PPS_CLIENT_LDISC=m +CONFIG_PPS_CLIENT_GPIO=m + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_DP83640_PHY=m +CONFIG_PTP_1588_CLOCK_INES=m +CONFIG_PTP_1588_CLOCK_KVM=m +CONFIG_PTP_1588_CLOCK_IDT82P33=m +CONFIG_PTP_1588_CLOCK_IDTCM=m +# CONFIG_PTP_1588_CLOCK_MOCK is not set +CONFIG_PTP_1588_CLOCK_OCP=m +# end of PTP clock support + +CONFIG_PINCTRL=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_PINMUX=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +CONFIG_PINCTRL_CY8C95X0=m +# CONFIG_PINCTRL_MCP23S08 is not set +# CONFIG_PINCTRL_MICROCHIP_SGPIO is not set +# CONFIG_PINCTRL_OCELOT is not set +CONFIG_PINCTRL_RK805=m +CONFIG_PINCTRL_ROCKCHIP=y +CONFIG_PINCTRL_SINGLE=y +CONFIG_PINCTRL_STMFX=m +CONFIG_PINCTRL_SX150X=y + +# +# Renesas pinctrl drivers +# +# end of Renesas pinctrl drivers + +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_FASTPATH_LIMIT=512 +CONFIG_OF_GPIO=y +CONFIG_GPIO_ACPI=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_OF_GPIO_MM_GPIOCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_CDEV_V1=y +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_REGMAP=m +CONFIG_GPIO_MAX730X=m +CONFIG_GPIO_IDIO_16=m + +# +# Memory mapped GPIO drivers +# +CONFIG_GPIO_74XX_MMIO=m +CONFIG_GPIO_ALTERA=m +# CONFIG_GPIO_AMDPT is not set +CONFIG_GPIO_CADENCE=m +CONFIG_GPIO_DWAPB=m +CONFIG_GPIO_EXAR=m +# CONFIG_GPIO_FTGPIO010 is not set +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_GRGPIO=m +CONFIG_GPIO_HISI=m +CONFIG_GPIO_HLWD=m +CONFIG_GPIO_LOGICVC=m +CONFIG_GPIO_MB86S7X=m +CONFIG_GPIO_PL061=y +CONFIG_GPIO_ROCKCHIP=y +# CONFIG_GPIO_SIFIVE is not set +CONFIG_GPIO_SYSCON=y +CONFIG_GPIO_XGENE=y +CONFIG_GPIO_XILINX=y +CONFIG_GPIO_AMD_FCH=m +# end of Memory mapped GPIO drivers + +# +# I2C GPIO expanders +# +CONFIG_GPIO_ADNP=m +# CONFIG_GPIO_FXL6408 is not set +# CONFIG_GPIO_DS4520 is not set +CONFIG_GPIO_GW_PLD=m +CONFIG_GPIO_MAX7300=m +CONFIG_GPIO_MAX732X=m +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_GPIO_PCA9570=m +CONFIG_GPIO_PCF857X=m +CONFIG_GPIO_TPIC2810=m +# end of I2C GPIO expanders + +# +# MFD GPIO expanders +# +# end of MFD GPIO expanders + +# +# PCI GPIO expanders +# +CONFIG_GPIO_PCI_IDIO_16=m +CONFIG_GPIO_PCIE_IDIO_24=m +CONFIG_GPIO_RDC321X=m +# end of PCI GPIO expanders + +# +# SPI GPIO expanders +# +CONFIG_GPIO_74X164=m +CONFIG_GPIO_MAX3191X=m +CONFIG_GPIO_MAX7301=m +CONFIG_GPIO_MC33880=m +CONFIG_GPIO_PISOSR=m +CONFIG_GPIO_XRA1403=m +# end of SPI GPIO expanders + +# +# USB GPIO expanders +# +# end of USB GPIO expanders + +# +# Virtual GPIO drivers +# +CONFIG_GPIO_AGGREGATOR=m +# CONFIG_GPIO_LATCH is not set +CONFIG_GPIO_MOCKUP=m +CONFIG_GPIO_VIRTIO=m +# CONFIG_GPIO_SIM is not set +# end of Virtual GPIO drivers + +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +# CONFIG_W1_MASTER_AMD_AXI is not set +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_GPIO=m +CONFIG_W1_MASTER_SGI=m +# end of 1-wire Bus Masters + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2405=m +CONFIG_W1_SLAVE_DS2408=m +CONFIG_W1_SLAVE_DS2408_READBACK=y +CONFIG_W1_SLAVE_DS2413=m +CONFIG_W1_SLAVE_DS2406=m +CONFIG_W1_SLAVE_DS2423=m +CONFIG_W1_SLAVE_DS2805=m +CONFIG_W1_SLAVE_DS2430=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +# CONFIG_W1_SLAVE_DS2433_CRC is not set +CONFIG_W1_SLAVE_DS2438=m +CONFIG_W1_SLAVE_DS250X=m +CONFIG_W1_SLAVE_DS2780=m +CONFIG_W1_SLAVE_DS2781=m +CONFIG_W1_SLAVE_DS28E04=m +CONFIG_W1_SLAVE_DS28E17=m +# end of 1-wire Slaves + +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +# CONFIG_POWER_RESET_LTC2952 is not set +CONFIG_POWER_RESET_REGULATOR=y +CONFIG_POWER_RESET_RESTART=y +CONFIG_POWER_RESET_VEXPRESS=y +CONFIG_POWER_RESET_XGENE=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_REBOOT_MODE=y +CONFIG_SYSCON_REBOOT_MODE=y +# CONFIG_NVMEM_REBOOT_MODE is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_POWER_SUPPLY_HWMON=y +CONFIG_GENERIC_ADC_BATTERY=m +# CONFIG_IP5XXX_POWER is not set +# CONFIG_TEST_POWER is not set +CONFIG_CHARGER_ADP5061=m +CONFIG_BATTERY_CW2015=m +CONFIG_BATTERY_DS2760=m +CONFIG_BATTERY_DS2780=m +CONFIG_BATTERY_DS2781=m +CONFIG_BATTERY_DS2782=m +# CONFIG_BATTERY_SAMSUNG_SDI is not set +CONFIG_BATTERY_SBS=m +CONFIG_CHARGER_SBS=m +CONFIG_MANAGER_SBS=m +CONFIG_BATTERY_BQ27XXX=m +CONFIG_BATTERY_BQ27XXX_I2C=m +CONFIG_BATTERY_BQ27XXX_HDQ=m +# CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM is not set +CONFIG_BATTERY_MAX17040=m +CONFIG_BATTERY_MAX17042=m +CONFIG_BATTERY_MAX1721X=m +CONFIG_CHARGER_ISP1704=m +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +CONFIG_CHARGER_GPIO=m +# CONFIG_CHARGER_MANAGER is not set +CONFIG_CHARGER_LT3651=m +CONFIG_CHARGER_LTC4162L=m +CONFIG_CHARGER_DETECTOR_MAX14656=m +# CONFIG_CHARGER_MAX77976 is not set +# CONFIG_CHARGER_MT6370 is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ2515X is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_BQ25980 is not set +CONFIG_CHARGER_BQ256XX=m +# CONFIG_CHARGER_RK817 is not set +CONFIG_CHARGER_SMB347=m +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +CONFIG_BATTERY_GOLDFISH=m +CONFIG_BATTERY_RT5033=m +# CONFIG_CHARGER_RT9455 is not set +# CONFIG_CHARGER_RT9467 is not set +# CONFIG_CHARGER_RT9471 is not set +# CONFIG_CHARGER_CROS_USBPD is not set +CONFIG_CHARGER_CROS_PCHG=m +CONFIG_CHARGER_UCS1002=m +# CONFIG_CHARGER_BD99954 is not set +# CONFIG_BATTERY_UG3105 is not set +# CONFIG_FUEL_GAUGE_MM8013 is not set +CONFIG_HWMON=y +CONFIG_HWMON_VID=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +CONFIG_SENSORS_AD7314=m +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM1177=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7X10=m +CONFIG_SENSORS_ADT7310=m +CONFIG_SENSORS_ADT7410=m +CONFIG_SENSORS_ADT7411=m +CONFIG_SENSORS_ADT7462=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7475=m +CONFIG_SENSORS_AHT10=m +CONFIG_SENSORS_AQUACOMPUTER_D5NEXT=m +CONFIG_SENSORS_AS370=m +CONFIG_SENSORS_ASC7621=m +CONFIG_SENSORS_AXI_FAN_CONTROL=m +CONFIG_SENSORS_ARM_SCMI=m +CONFIG_SENSORS_ARM_SCPI=m +CONFIG_SENSORS_ATXP1=m +# CONFIG_SENSORS_CORSAIR_CPRO is not set +CONFIG_SENSORS_CORSAIR_PSU=m +CONFIG_SENSORS_DRIVETEMP=m +CONFIG_SENSORS_DS620=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_I5K_AMB=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_FTSTEUTATES=m +# CONFIG_SENSORS_GIGABYTE_WATERFORCE is not set +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_G760A=m +CONFIG_SENSORS_G762=m +CONFIG_SENSORS_GPIO_FAN=m +CONFIG_SENSORS_HIH6130=m +# CONFIG_SENSORS_HS3001 is not set +CONFIG_SENSORS_IBMAEM=m +CONFIG_SENSORS_IBMPEX=m +CONFIG_SENSORS_IIO_HWMON=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_JC42=m +# CONFIG_SENSORS_POWERZ is not set +CONFIG_SENSORS_POWR1220=m +CONFIG_SENSORS_LINEAGE=m +CONFIG_SENSORS_LTC2945=m +CONFIG_SENSORS_LTC2947=m +CONFIG_SENSORS_LTC2947_I2C=m +CONFIG_SENSORS_LTC2947_SPI=m +CONFIG_SENSORS_LTC2990=m +# CONFIG_SENSORS_LTC2991 is not set +CONFIG_SENSORS_LTC2992=m +CONFIG_SENSORS_LTC4151=m +CONFIG_SENSORS_LTC4215=m +CONFIG_SENSORS_LTC4222=m +CONFIG_SENSORS_LTC4245=m +CONFIG_SENSORS_LTC4260=m +CONFIG_SENSORS_LTC4261=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MAX127=m +CONFIG_SENSORS_MAX16065=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX1668=m +CONFIG_SENSORS_MAX197=m +CONFIG_SENSORS_MAX31722=m +CONFIG_SENSORS_MAX31730=m +CONFIG_SENSORS_MAX31760=m +# CONFIG_MAX31827 is not set +CONFIG_SENSORS_MAX6620=m +CONFIG_SENSORS_MAX6621=m +CONFIG_SENSORS_MAX6639=m +CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_MAX6697=m +CONFIG_SENSORS_MAX31790=m +# CONFIG_SENSORS_MC34VR500 is not set +CONFIG_SENSORS_MCP3021=m +CONFIG_SENSORS_TC654=m +CONFIG_SENSORS_TPS23861=m +# CONFIG_SENSORS_MR75203 is not set +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_LM73=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_LM95234=m +CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_LM95245=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_NTC_THERMISTOR=m +CONFIG_SENSORS_NCT6683=m +CONFIG_SENSORS_NCT6775_CORE=m +CONFIG_SENSORS_NCT6775=m +CONFIG_SENSORS_NCT6775_I2C=m +CONFIG_SENSORS_NCT7802=m +CONFIG_SENSORS_NCT7904=m +CONFIG_SENSORS_NPCM7XX=m +CONFIG_SENSORS_NZXT_KRAKEN2=m +# CONFIG_SENSORS_NZXT_SMART2 is not set +CONFIG_SENSORS_OCC_P8_I2C=m +CONFIG_SENSORS_OCC=m +CONFIG_SENSORS_PCF8591=m +CONFIG_PMBUS=m +CONFIG_SENSORS_PMBUS=m +# CONFIG_SENSORS_ACBEL_FSG032 is not set +# CONFIG_SENSORS_ADM1266 is not set +CONFIG_SENSORS_ADM1275=m +CONFIG_SENSORS_BEL_PFE=m +CONFIG_SENSORS_BPA_RS600=m +# CONFIG_SENSORS_DELTA_AHE50DC_FAN is not set +CONFIG_SENSORS_FSP_3Y=m +CONFIG_SENSORS_IBM_CFFPS=m +CONFIG_SENSORS_DPS920AB=m +CONFIG_SENSORS_INSPUR_IPSPS=m +CONFIG_SENSORS_IR35221=m +CONFIG_SENSORS_IR36021=m +CONFIG_SENSORS_IR38064=m +# CONFIG_SENSORS_IR38064_REGULATOR is not set +CONFIG_SENSORS_IRPS5401=m +CONFIG_SENSORS_ISL68137=m +CONFIG_SENSORS_LM25066=m +# CONFIG_SENSORS_LM25066_REGULATOR is not set +CONFIG_SENSORS_LT7182S=m +CONFIG_SENSORS_LTC2978=m +CONFIG_SENSORS_LTC2978_REGULATOR=y +CONFIG_SENSORS_LTC3815=m +# CONFIG_SENSORS_LTC4286 is not set +CONFIG_SENSORS_MAX15301=m +CONFIG_SENSORS_MAX16064=m +CONFIG_SENSORS_MAX16601=m +CONFIG_SENSORS_MAX20730=m +CONFIG_SENSORS_MAX20751=m +CONFIG_SENSORS_MAX31785=m +CONFIG_SENSORS_MAX34440=m +CONFIG_SENSORS_MAX8688=m +# CONFIG_SENSORS_MP2856 is not set +CONFIG_SENSORS_MP2888=m +# CONFIG_SENSORS_MP2975 is not set +# CONFIG_SENSORS_MP5023 is not set +# CONFIG_SENSORS_MP5990 is not set +# CONFIG_SENSORS_MPQ7932 is not set +CONFIG_SENSORS_PIM4328=m +# CONFIG_SENSORS_PLI1209BC is not set +CONFIG_SENSORS_PM6764TR=m +CONFIG_SENSORS_PXE1610=m +CONFIG_SENSORS_Q54SJ108A2=m +CONFIG_SENSORS_STPDDC60=m +# CONFIG_SENSORS_TDA38640 is not set +CONFIG_SENSORS_TPS40422=m +CONFIG_SENSORS_TPS53679=m +CONFIG_SENSORS_TPS546D24=m +CONFIG_SENSORS_UCD9000=m +CONFIG_SENSORS_UCD9200=m +CONFIG_SENSORS_XDPE152=m +CONFIG_SENSORS_XDPE122=m +# CONFIG_SENSORS_XDPE122_REGULATOR is not set +CONFIG_SENSORS_ZL6100=m +CONFIG_SENSORS_PWM_FAN=m +CONFIG_SENSORS_SBTSI=m +CONFIG_SENSORS_SBRMI=m +CONFIG_SENSORS_SHT15=m +CONFIG_SENSORS_SHT21=m +CONFIG_SENSORS_SHT3x=m +CONFIG_SENSORS_SHT4x=m +CONFIG_SENSORS_SHTC1=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_EMC1403=m +CONFIG_SENSORS_EMC2103=m +CONFIG_SENSORS_EMC2305=m +CONFIG_SENSORS_EMC6W201=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_SCH56XX_COMMON=m +CONFIG_SENSORS_SCH5627=m +CONFIG_SENSORS_SCH5636=m +CONFIG_SENSORS_STTS751=m +CONFIG_SENSORS_ADC128D818=m +CONFIG_SENSORS_ADS7828=m +CONFIG_SENSORS_ADS7871=m +CONFIG_SENSORS_AMC6821=m +CONFIG_SENSORS_INA209=m +CONFIG_SENSORS_INA2XX=m +# CONFIG_SENSORS_INA238 is not set +CONFIG_SENSORS_INA3221=m +CONFIG_SENSORS_TC74=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TMP102=m +CONFIG_SENSORS_TMP103=m +CONFIG_SENSORS_TMP108=m +CONFIG_SENSORS_TMP401=m +CONFIG_SENSORS_TMP421=m +# CONFIG_SENSORS_TMP464 is not set +CONFIG_SENSORS_TMP513=m +CONFIG_SENSORS_VEXPRESS=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83773G=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +CONFIG_SENSORS_W83795=m +# CONFIG_SENSORS_W83795_FANCTRL is not set +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_XGENE=m + +# +# ACPI drivers +# +CONFIG_SENSORS_ACPI_POWER=m +CONFIG_THERMAL=y +# CONFIG_THERMAL_NETLINK is not set +CONFIG_THERMAL_STATISTICS=y +# CONFIG_THERMAL_DEBUGFS is not set +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_BANG_BANG=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_CPU_THERMAL=y +CONFIG_CPU_FREQ_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_THERMAL_EMULATION=y +CONFIG_THERMAL_MMIO=m +CONFIG_ROCKCHIP_THERMAL=y +# CONFIG_GENERIC_ADC_THERMAL is not set +CONFIG_KHADAS_MCU_FAN_THERMAL=m +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y +CONFIG_WATCHDOG_OPEN_TIMEOUT=0 +CONFIG_WATCHDOG_SYSFS=y +# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set + +# +# Watchdog Pretimeout Governors +# +# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_GPIO_WATCHDOG=m +CONFIG_WDAT_WDT=m +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_XILINX_WINDOW_WATCHDOG is not set +# CONFIG_ZIIRAVE_WATCHDOG is not set +CONFIG_ARM_SP805_WATCHDOG=y +CONFIG_ARM_SBSA_WATCHDOG=y +# CONFIG_CADENCE_WATCHDOG is not set +CONFIG_DW_WATCHDOG=y +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_ARM_SMC_WATCHDOG=y +# CONFIG_ALIM7101_WDT is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_HP_WATCHDOG is not set +# CONFIG_MEN_A21_WDT is not set +# CONFIG_XEN_WDT is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_SSB_POSSIBLE=y +CONFIG_SSB=m +CONFIG_SSB_SPROM=y +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_SSB_SDIOHOST_POSSIBLE=y +CONFIG_SSB_SDIOHOST=y +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_DRIVER_PCICORE=y +CONFIG_SSB_DRIVER_GPIO=y +CONFIG_BCMA_POSSIBLE=y +CONFIG_BCMA=m +CONFIG_BCMA_BLOCKIO=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +CONFIG_BCMA_HOST_PCI=y +CONFIG_BCMA_HOST_SOC=y +CONFIG_BCMA_DRIVER_PCI=y +CONFIG_BCMA_SFLASH=y +CONFIG_BCMA_DRIVER_GMAC_CMN=y +CONFIG_BCMA_DRIVER_GPIO=y +CONFIG_BCMA_DEBUG=y + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_ACT8945A is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_SMPRO is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_FLEXCOM is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_AXP20X_I2C is not set +CONFIG_MFD_CROS_EC_DEV=y +# CONFIG_MFD_CS42L43_I2C is not set +# CONFIG_MFD_CS42L43_SDW is not set +# CONFIG_MFD_MADERA is not set +# CONFIG_MFD_MAX5970 is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9062 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_GATEWORKS_GSC is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_MP2629 is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_MFD_HI6421_SPMI is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_IQS62X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77541 is not set +# CONFIG_MFD_MAX77620 is not set +# CONFIG_MFD_MAX77650 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77714 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6360 is not set +CONFIG_MFD_MT6370=m +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +CONFIG_MFD_OCELOT=m +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +CONFIG_MFD_NTXEC=m +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_SY7636A is not set +CONFIG_MFD_RDC321X=m +# CONFIG_MFD_RT4831 is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RT5120 is not set +# CONFIG_MFD_RC5T583 is not set +CONFIG_MFD_RK8XX=m +CONFIG_MFD_RK8XX_I2C=m +CONFIG_MFD_RK8XX_SPI=m +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +CONFIG_MFD_SIMPLE_MFD_I2C=m +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_TI_LMU is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65086 is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TI_LP873X is not set +# CONFIG_MFD_TI_LP87565 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS65219 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS6594_I2C is not set +# CONFIG_MFD_TPS6594_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +CONFIG_MFD_WL1273_CORE=m +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TQMX86 is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_LOCHNAGAR is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_ROHM_BD718XX is not set +# CONFIG_MFD_ROHM_BD71828 is not set +# CONFIG_MFD_ROHM_BD957XMUF is not set +# CONFIG_MFD_STPMIC1 is not set +CONFIG_MFD_STMFX=m +# CONFIG_MFD_WCD934X is not set +# CONFIG_MFD_ATC260X_I2C is not set +CONFIG_MFD_KHADAS_MCU=m +# CONFIG_MFD_QCOM_PM8008 is not set +CONFIG_MFD_VEXPRESS_SYSREG=y +# CONFIG_RAVE_SP_CORE is not set +# CONFIG_MFD_INTEL_M10_BMC_SPI is not set +CONFIG_MFD_RSMU_I2C=m +CONFIG_MFD_RSMU_SPI=m +# end of Multifunction device drivers + +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_NETLINK_EVENTS is not set +# CONFIG_REGULATOR_88PG86X is not set +CONFIG_REGULATOR_ACT8865=y +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ARM_SCMI is not set +# CONFIG_REGULATOR_AW37503 is not set +# CONFIG_REGULATOR_CROS_EC is not set +# CONFIG_REGULATOR_DA9121 is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +CONFIG_REGULATOR_FAN53555=y +CONFIG_REGULATOR_FAN53880=m +CONFIG_REGULATOR_GPIO=y +# CONFIG_REGULATOR_ISL9305 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_LTC3676 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX77503 is not set +# CONFIG_REGULATOR_MAX77857 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +CONFIG_REGULATOR_MAX8893=m +# CONFIG_REGULATOR_MAX8952 is not set +CONFIG_REGULATOR_MAX8973=y +# CONFIG_REGULATOR_MAX20086 is not set +# CONFIG_REGULATOR_MAX20411 is not set +# CONFIG_REGULATOR_MAX77826 is not set +CONFIG_REGULATOR_MCP16502=m +CONFIG_REGULATOR_MP5416=m +CONFIG_REGULATOR_MP8859=m +CONFIG_REGULATOR_MP886X=m +CONFIG_REGULATOR_MPQ7920=m +# CONFIG_REGULATOR_MT6311 is not set +CONFIG_REGULATOR_MT6315=m +CONFIG_REGULATOR_MT6370=m +CONFIG_REGULATOR_PCA9450=y +CONFIG_REGULATOR_PF8X00=m +CONFIG_REGULATOR_PFUZE100=m +# CONFIG_REGULATOR_PV88060 is not set +# CONFIG_REGULATOR_PV88080 is not set +# CONFIG_REGULATOR_PV88090 is not set +CONFIG_REGULATOR_PWM=y +CONFIG_REGULATOR_QCOM_SPMI=y +# CONFIG_REGULATOR_QCOM_USB_VBUS is not set +# CONFIG_REGULATOR_RAA215300 is not set +# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set +CONFIG_REGULATOR_RK808=m +# CONFIG_REGULATOR_RT4801 is not set +# CONFIG_REGULATOR_RT4803 is not set +# CONFIG_REGULATOR_RT5190A is not set +# CONFIG_REGULATOR_RT5739 is not set +CONFIG_REGULATOR_RT5759=m +CONFIG_REGULATOR_RT6160=m +# CONFIG_REGULATOR_RT6190 is not set +CONFIG_REGULATOR_RT6245=m +CONFIG_REGULATOR_RTQ2134=m +# CONFIG_REGULATOR_RTMV20 is not set +CONFIG_REGULATOR_RTQ6752=m +# CONFIG_REGULATOR_RTQ2208 is not set +CONFIG_REGULATOR_SLG51000=m +# CONFIG_REGULATOR_SY8106A is not set +CONFIG_REGULATOR_SY8824X=m +# CONFIG_REGULATOR_SY8827N is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS6286X is not set +# CONFIG_REGULATOR_TPS6287X is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_REGULATOR_VCTRL=m +CONFIG_REGULATOR_VEXPRESS=m +# CONFIG_REGULATOR_QCOM_LABIBB is not set +CONFIG_RC_CORE=m +CONFIG_LIRC=y +CONFIG_RC_MAP=m +CONFIG_RC_DECODERS=y +CONFIG_IR_IMON_DECODER=m +CONFIG_IR_JVC_DECODER=m +CONFIG_IR_MCE_KBD_DECODER=m +CONFIG_IR_NEC_DECODER=m +CONFIG_IR_RC5_DECODER=m +CONFIG_IR_RC6_DECODER=m +CONFIG_IR_RCMM_DECODER=m +CONFIG_IR_SANYO_DECODER=m +CONFIG_IR_SHARP_DECODER=m +CONFIG_IR_SONY_DECODER=m +CONFIG_IR_XMP_DECODER=m +CONFIG_RC_DEVICES=y +CONFIG_IR_ENE=m +CONFIG_IR_FINTEK=m +CONFIG_IR_GPIO_CIR=m +CONFIG_IR_GPIO_TX=m +CONFIG_IR_HIX5HD2=m +CONFIG_IR_IGORPLUGUSB=m +CONFIG_IR_IGUANA=m +CONFIG_IR_IMON=m +CONFIG_IR_IMON_RAW=m +CONFIG_IR_ITE_CIR=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_NUVOTON=m +CONFIG_IR_PWM_TX=m +CONFIG_IR_REDRAT3=m +CONFIG_IR_SERIAL=m +CONFIG_IR_SERIAL_TRANSMITTER=y +CONFIG_IR_SPI=m +CONFIG_IR_STREAMZAP=m +CONFIG_IR_TOY=m +CONFIG_IR_TTUSBIR=m +CONFIG_RC_ATI_REMOTE=m +CONFIG_RC_LOOPBACK=m +CONFIG_RC_XBOX_DVD=m +CONFIG_CEC_CORE=m +CONFIG_CEC_NOTIFIER=y +CONFIG_CEC_PIN=y + +# +# CEC support +# +# CONFIG_MEDIA_CEC_RC is not set +CONFIG_CEC_PIN_ERROR_INJ=y +CONFIG_MEDIA_CEC_SUPPORT=y +CONFIG_CEC_CH7322=m +CONFIG_CEC_CROS_EC=m +CONFIG_CEC_GPIO=m +CONFIG_USB_PULSE8_CEC=m +CONFIG_USB_RAINSHADOW_CEC=m +# end of CEC support + +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_SUPPORT_FILTER=y +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y + +# +# Media device types +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_SDR_SUPPORT=y +CONFIG_MEDIA_PLATFORM_SUPPORT=y +CONFIG_MEDIA_TEST_SUPPORT=y +# end of Media device types + +CONFIG_VIDEO_DEV=m +CONFIG_MEDIA_CONTROLLER=y +CONFIG_DVB_CORE=m + +# +# Video4Linux options +# +CONFIG_VIDEO_V4L2_I2C=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +# CONFIG_VIDEO_ADV_DEBUG is not set +CONFIG_VIDEO_FIXED_MINOR_RANGES=y +CONFIG_VIDEO_TUNER=m +CONFIG_V4L2_H264=m +CONFIG_V4L2_VP9=m +CONFIG_V4L2_MEM2MEM_DEV=m +CONFIG_V4L2_FLASH_LED_CLASS=m +CONFIG_V4L2_FWNODE=m +CONFIG_V4L2_ASYNC=m +CONFIG_V4L2_CCI=m +CONFIG_V4L2_CCI_I2C=m +# end of Video4Linux options + +# +# Media controller options +# +CONFIG_MEDIA_CONTROLLER_DVB=y +# end of Media controller options + +# +# Digital TV options +# +CONFIG_DVB_MMAP=y +CONFIG_DVB_NET=y +CONFIG_DVB_MAX_ADAPTERS=16 +CONFIG_DVB_DYNAMIC_MINORS=y +CONFIG_DVB_DEMUX_SECTION_LOSS_LOG=y +# CONFIG_DVB_ULE_DEBUG is not set +# end of Digital TV options + +# +# Media drivers +# + +# +# Drivers filtered as selected at 'Filter media drivers' +# + +# +# Media drivers +# +CONFIG_MEDIA_USB_SUPPORT=y + +# +# Webcam devices +# +CONFIG_USB_GSPCA=m +CONFIG_USB_GSPCA_BENQ=m +CONFIG_USB_GSPCA_CONEX=m +CONFIG_USB_GSPCA_CPIA1=m +CONFIG_USB_GSPCA_DTCS033=m +CONFIG_USB_GSPCA_ETOMS=m +CONFIG_USB_GSPCA_FINEPIX=m +CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_JL2005BCD=m +CONFIG_USB_GSPCA_KINECT=m +CONFIG_USB_GSPCA_KONICA=m +CONFIG_USB_GSPCA_MARS=m +CONFIG_USB_GSPCA_MR97310A=m +CONFIG_USB_GSPCA_NW80X=m +CONFIG_USB_GSPCA_OV519=m +CONFIG_USB_GSPCA_OV534=m +CONFIG_USB_GSPCA_OV534_9=m +CONFIG_USB_GSPCA_PAC207=m +CONFIG_USB_GSPCA_PAC7302=m +CONFIG_USB_GSPCA_PAC7311=m +CONFIG_USB_GSPCA_SE401=m +CONFIG_USB_GSPCA_SN9C2028=m +CONFIG_USB_GSPCA_SN9C20X=m +CONFIG_USB_GSPCA_SONIXB=m +CONFIG_USB_GSPCA_SONIXJ=m +CONFIG_USB_GSPCA_SPCA1528=m +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SQ905=m +CONFIG_USB_GSPCA_SQ905C=m +CONFIG_USB_GSPCA_SQ930X=m +CONFIG_USB_GSPCA_STK014=m +CONFIG_USB_GSPCA_STK1135=m +CONFIG_USB_GSPCA_STV0680=m +CONFIG_USB_GSPCA_SUNPLUS=m +CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TOPRO=m +CONFIG_USB_GSPCA_TOUPTEK=m +CONFIG_USB_GSPCA_TV8532=m +CONFIG_USB_GSPCA_VC032X=m +CONFIG_USB_GSPCA_VICAM=m +CONFIG_USB_GSPCA_XIRLINK_CIT=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_USB_GL860=m +CONFIG_USB_M5602=m +CONFIG_USB_STV06XX=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_PWC_INPUT_EVDEV=y +CONFIG_USB_S2255=m +CONFIG_VIDEO_USBTV=m +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y + +# +# Analog TV USB devices +# +CONFIG_VIDEO_GO7007=m +CONFIG_VIDEO_GO7007_USB=m +CONFIG_VIDEO_GO7007_LOADER=m +CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_STK1160=m + +# +# Analog/digital TV USB devices +# +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_AU0828_V4L2=y +CONFIG_VIDEO_AU0828_RC=y +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_RC=y +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m + +# +# Digital TV USB devices +# +CONFIG_DVB_AS102=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set +CONFIG_DVB_USB_V2=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_AF9035=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_AZ6007=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_DVBSKY=m +CONFIG_DVB_USB_EC168=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_MXL111SF=m +CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_ZD1301=m +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_CXUSB=m +# CONFIG_DVB_USB_CXUSB_ANALOG is not set +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_DIB3000MC=m +CONFIG_DVB_USB_DIBUSB_MB=m +CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_PCTV452E=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_VP7045=m +CONFIG_SMS_USB_DRV=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m + +# +# Webcam, TV (analog/digital) USB devices +# +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_V4L2=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_EM28XX_RC=m + +# +# Software defined radio USB devices +# +CONFIG_USB_AIRSPY=m +CONFIG_USB_HACKRF=m +CONFIG_USB_MSI2500=m +CONFIG_MEDIA_PCI_SUPPORT=y + +# +# Media capture support +# +# CONFIG_VIDEO_MGB4 is not set +CONFIG_VIDEO_SOLO6X10=m +# CONFIG_VIDEO_TW5864 is not set +CONFIG_VIDEO_TW68=m +# CONFIG_VIDEO_TW686X is not set +CONFIG_VIDEO_ZORAN=m +# CONFIG_VIDEO_ZORAN_DC30 is not set +# CONFIG_VIDEO_ZORAN_ZR36060 is not set + +# +# Media capture/analog TV support +# +CONFIG_VIDEO_DT3155=m +CONFIG_VIDEO_IVTV=m +CONFIG_VIDEO_IVTV_ALSA=m +CONFIG_VIDEO_FB_IVTV=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_MXB=m + +# +# Media capture/analog/hybrid TV support +# +CONFIG_VIDEO_BT848=m +CONFIG_DVB_BT8XX=m +CONFIG_VIDEO_CX18=m +CONFIG_VIDEO_CX18_ALSA=m +CONFIG_VIDEO_CX23885=m +CONFIG_MEDIA_ALTERA_CI=m +CONFIG_VIDEO_CX25821=m +CONFIG_VIDEO_CX25821_ALSA=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_ENABLE_VP3054=y +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88_MPEG=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_RC=y +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_GO7007=m +CONFIG_VIDEO_SAA7164=m + +# +# Media digital TV PCI Adapters +# +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set +CONFIG_DVB_DDBRIDGE=m +# CONFIG_DVB_DDBRIDGE_MSIENABLE is not set +CONFIG_DVB_DM1105=m +CONFIG_MANTIS_CORE=m +CONFIG_DVB_MANTIS=m +CONFIG_DVB_HOPPER=m +# CONFIG_DVB_NETUP_UNIDVB is not set +CONFIG_DVB_NGENE=m +CONFIG_DVB_PLUTO2=m +CONFIG_DVB_PT1=m +CONFIG_DVB_PT3=m +CONFIG_DVB_SMIPCIE=m +CONFIG_DVB_BUDGET_CORE=m +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +# CONFIG_IPU_BRIDGE is not set +CONFIG_RADIO_ADAPTERS=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_SHARK=m +CONFIG_RADIO_SHARK2=m +CONFIG_RADIO_SI4713=m +CONFIG_RADIO_TEA575X=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_TEF6862=m +CONFIG_RADIO_WL1273=m +CONFIG_USB_DSBR=m +CONFIG_USB_KEENE=m +CONFIG_USB_MA901=m +CONFIG_USB_MR800=m +CONFIG_USB_RAREMONO=m +CONFIG_RADIO_SI470X=m +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m +CONFIG_USB_SI4713=m +CONFIG_PLATFORM_SI4713=m +CONFIG_I2C_SI4713=m +CONFIG_MEDIA_PLATFORM_DRIVERS=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SDR_PLATFORM_DRIVERS=y +CONFIG_DVB_PLATFORM_DRIVERS=y +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m +CONFIG_VIDEO_MUX=m + +# +# Allegro DVT media platform drivers +# + +# +# Amlogic media platform drivers +# + +# +# Amphion drivers +# + +# +# Aspeed media platform drivers +# + +# +# Atmel media platform drivers +# + +# +# Cadence media platform drivers +# +CONFIG_VIDEO_CADENCE_CSI2RX=m +CONFIG_VIDEO_CADENCE_CSI2TX=m + +# +# Chips&Media media platform drivers +# + +# +# Intel media platform drivers +# + +# +# Marvell media platform drivers +# +CONFIG_VIDEO_CAFE_CCIC=m + +# +# Mediatek media platform drivers +# + +# +# Microchip Technology, Inc. media platform drivers +# + +# +# Nuvoton media platform drivers +# + +# +# NVidia media platform drivers +# + +# +# NXP media platform drivers +# + +# +# Qualcomm media platform drivers +# + +# +# Renesas media platform drivers +# + +# +# Rockchip media platform drivers +# +CONFIG_VIDEO_ROCKCHIP_RGA=m +CONFIG_VIDEO_ROCKCHIP_ISP1=m + +# +# Samsung media platform drivers +# + +# +# STMicroelectronics media platform drivers +# + +# +# Sunxi media platform drivers +# + +# +# Texas Instruments drivers +# + +# +# Verisilicon media platform drivers +# +CONFIG_VIDEO_HANTRO=m +CONFIG_VIDEO_HANTRO_ROCKCHIP=y + +# +# VIA media platform drivers +# + +# +# Xilinx media platform drivers +# +CONFIG_VIDEO_XILINX=m +CONFIG_VIDEO_XILINX_CSI2RXSS=m +CONFIG_VIDEO_XILINX_TPG=m +CONFIG_VIDEO_XILINX_VTC=m + +# +# MMC/SDIO DVB adapters +# +CONFIG_SMS_SDIO_DRV=m +CONFIG_V4L_TEST_DRIVERS=y +CONFIG_VIDEO_VIM2M=m +CONFIG_VIDEO_VICODEC=m +CONFIG_VIDEO_VIMC=m +CONFIG_VIDEO_VIVID=m +CONFIG_VIDEO_VIVID_CEC=y +CONFIG_VIDEO_VIVID_MAX_DEVS=64 +# CONFIG_VIDEO_VISL is not set +CONFIG_DVB_TEST_DRIVERS=y +CONFIG_DVB_VIDTV=m +CONFIG_MEDIA_COMMON_OPTIONS=y + +# +# common driver options +# +CONFIG_CYPRESS_FIRMWARE=m +CONFIG_TTPCI_EEPROM=m +CONFIG_UVC_COMMON=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_SMS_SIANO_MDTV=m +CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set +CONFIG_VIDEO_V4L2_TPG=m +CONFIG_VIDEOBUF2_CORE=m +CONFIG_VIDEOBUF2_V4L2=m +CONFIG_VIDEOBUF2_MEMOPS=m +CONFIG_VIDEOBUF2_DMA_CONTIG=m +CONFIG_VIDEOBUF2_VMALLOC=m +CONFIG_VIDEOBUF2_DMA_SG=m +CONFIG_VIDEOBUF2_DVB=m +# end of Media drivers + +# +# Media ancillary drivers +# +CONFIG_MEDIA_ATTACH=y + +# +# IR I2C driver auto-selected by 'Autoselect ancillary drivers' +# +CONFIG_VIDEO_IR_I2C=m +CONFIG_VIDEO_CAMERA_SENSOR=y +CONFIG_VIDEO_APTINA_PLL=m +CONFIG_VIDEO_CCS_PLL=m +# CONFIG_VIDEO_ALVIUM_CSI2 is not set +# CONFIG_VIDEO_AR0521 is not set +# CONFIG_VIDEO_GC0308 is not set +# CONFIG_VIDEO_GC2145 is not set +CONFIG_VIDEO_HI556=m +CONFIG_VIDEO_HI846=m +# CONFIG_VIDEO_HI847 is not set +CONFIG_VIDEO_IMX208=m +CONFIG_VIDEO_IMX214=m +CONFIG_VIDEO_IMX219=m +CONFIG_VIDEO_IMX258=m +CONFIG_VIDEO_IMX274=m +CONFIG_VIDEO_IMX290=m +# CONFIG_VIDEO_IMX296 is not set +CONFIG_VIDEO_IMX319=m +CONFIG_VIDEO_IMX334=m +CONFIG_VIDEO_IMX335=m +CONFIG_VIDEO_IMX355=m +CONFIG_VIDEO_IMX412=m +# CONFIG_VIDEO_IMX415 is not set +CONFIG_VIDEO_MAX9271_LIB=m +CONFIG_VIDEO_MT9M001=m +CONFIG_VIDEO_MT9M111=m +# CONFIG_VIDEO_MT9M114 is not set +CONFIG_VIDEO_MT9P031=m +CONFIG_VIDEO_MT9T112=m +CONFIG_VIDEO_MT9V011=m +CONFIG_VIDEO_MT9V032=m +CONFIG_VIDEO_MT9V111=m +# CONFIG_VIDEO_OG01A1B is not set +# CONFIG_VIDEO_OV01A10 is not set +CONFIG_VIDEO_OV02A10=m +# CONFIG_VIDEO_OV08D10 is not set +# CONFIG_VIDEO_OV08X40 is not set +CONFIG_VIDEO_OV13858=m +CONFIG_VIDEO_OV13B10=m +CONFIG_VIDEO_OV2640=m +CONFIG_VIDEO_OV2659=m +CONFIG_VIDEO_OV2680=m +CONFIG_VIDEO_OV2685=m +CONFIG_VIDEO_OV2740=m +# CONFIG_VIDEO_OV4689 is not set +CONFIG_VIDEO_OV5640=m +CONFIG_VIDEO_OV5645=m +CONFIG_VIDEO_OV5647=m +CONFIG_VIDEO_OV5648=m +CONFIG_VIDEO_OV5670=m +CONFIG_VIDEO_OV5675=m +# CONFIG_VIDEO_OV5693 is not set +CONFIG_VIDEO_OV5695=m +# CONFIG_VIDEO_OV64A40 is not set +CONFIG_VIDEO_OV6650=m +CONFIG_VIDEO_OV7251=m +CONFIG_VIDEO_OV7640=m +CONFIG_VIDEO_OV7670=m +CONFIG_VIDEO_OV772X=m +CONFIG_VIDEO_OV7740=m +CONFIG_VIDEO_OV8856=m +# CONFIG_VIDEO_OV8858 is not set +CONFIG_VIDEO_OV8865=m +CONFIG_VIDEO_OV9282=m +CONFIG_VIDEO_OV9640=m +CONFIG_VIDEO_OV9650=m +CONFIG_VIDEO_OV9734=m +CONFIG_VIDEO_RDACM20=m +CONFIG_VIDEO_RDACM21=m +CONFIG_VIDEO_RJ54N1=m +CONFIG_VIDEO_S5C73M3=m +CONFIG_VIDEO_S5K5BAF=m +CONFIG_VIDEO_S5K6A3=m +# CONFIG_VIDEO_ST_VGXY61 is not set +CONFIG_VIDEO_CCS=m +CONFIG_VIDEO_ET8EK8=m + +# +# Camera ISPs +# +# CONFIG_VIDEO_THP7312 is not set +# end of Camera ISPs + +# +# Lens drivers +# +CONFIG_VIDEO_AD5820=m +CONFIG_VIDEO_AK7375=m +CONFIG_VIDEO_DW9714=m +# CONFIG_VIDEO_DW9719 is not set +CONFIG_VIDEO_DW9768=m +CONFIG_VIDEO_DW9807_VCM=m +# end of Lens drivers + +# +# Flash devices +# +CONFIG_VIDEO_ADP1653=m +CONFIG_VIDEO_LM3560=m +CONFIG_VIDEO_LM3646=m +# end of Flash devices + +# +# Audio decoders, processors and mixers +# +CONFIG_VIDEO_CS3308=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_SONY_BTF_MPX=m +# CONFIG_VIDEO_TDA1997X is not set +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +# CONFIG_VIDEO_TLV320AIC23B is not set +CONFIG_VIDEO_TVAUDIO=m +CONFIG_VIDEO_UDA1342=m +CONFIG_VIDEO_VP27SMPX=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_WM8775=m +# end of Audio decoders, processors and mixers + +# +# RDS decoders +# +CONFIG_VIDEO_SAA6588=m +# end of RDS decoders + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7183 is not set +# CONFIG_VIDEO_ADV748X is not set +# CONFIG_VIDEO_ADV7604 is not set +# CONFIG_VIDEO_ADV7842 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_ISL7998X is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_MAX9286 is not set +# CONFIG_VIDEO_ML86V7667 is not set +# CONFIG_VIDEO_SAA7110 is not set +CONFIG_VIDEO_SAA711X=m +# CONFIG_VIDEO_TC358743 is not set +# CONFIG_VIDEO_TC358746 is not set +# CONFIG_VIDEO_TVP514X is not set +CONFIG_VIDEO_TVP5150=m +# CONFIG_VIDEO_TVP7002 is not set +CONFIG_VIDEO_TW2804=m +# CONFIG_VIDEO_TW9900 is not set +CONFIG_VIDEO_TW9903=m +CONFIG_VIDEO_TW9906=m +# CONFIG_VIDEO_TW9910 is not set +# CONFIG_VIDEO_VPX3220 is not set + +# +# Video and audio decoders +# +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_CX25840=m +# end of Video decoders + +# +# Video encoders +# +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_ADV7393 is not set +# CONFIG_VIDEO_AK881X is not set +CONFIG_VIDEO_SAA7127=m +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_THS8200 is not set +# end of Video encoders + +# +# Video improvement chips +# +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m +# end of Video improvement chips + +# +# Audio/Video compression chips +# +CONFIG_VIDEO_SAA6752HS=m +# end of Audio/Video compression chips + +# +# SDR tuner chips +# +# CONFIG_SDR_MAX2175 is not set +# end of SDR tuner chips + +# +# Miscellaneous helper chips +# +# CONFIG_VIDEO_I2C is not set +CONFIG_VIDEO_M52790=m +# CONFIG_VIDEO_ST_MIPID02 is not set +# CONFIG_VIDEO_THS7303 is not set +# end of Miscellaneous helper chips + +# +# Video serializers and deserializers +# +# CONFIG_VIDEO_DS90UB913 is not set +# CONFIG_VIDEO_DS90UB953 is not set +# CONFIG_VIDEO_DS90UB960 is not set +# end of Video serializers and deserializers + +# +# Media SPI Adapters +# +CONFIG_CXD2880_SPI_DRV=m +CONFIG_VIDEO_GS1662=m +# end of Media SPI Adapters + +CONFIG_MEDIA_TUNER=m + +# +# Customize TV tuners +# +CONFIG_MEDIA_TUNER_E4000=m +CONFIG_MEDIA_TUNER_FC0011=m +CONFIG_MEDIA_TUNER_FC0012=m +CONFIG_MEDIA_TUNER_FC0013=m +CONFIG_MEDIA_TUNER_FC2580=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_M88RS6000T=m +CONFIG_MEDIA_TUNER_MAX2165=m +CONFIG_MEDIA_TUNER_MC44S803=m +CONFIG_MEDIA_TUNER_MSI001=m +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2063=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2131=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MXL301RF=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_QM1D1B0004=m +CONFIG_MEDIA_TUNER_QM1D1C0042=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_R820T=m +CONFIG_MEDIA_TUNER_SI2157=m +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA18212=m +CONFIG_MEDIA_TUNER_TDA18218=m +CONFIG_MEDIA_TUNER_TDA18250=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC4000=m +CONFIG_MEDIA_TUNER_XC5000=m +# end of Customize TV tuners + +# +# Customise DVB Frontends +# + +# +# Multistandard (satellite) frontends +# +CONFIG_DVB_M88DS3103=m +CONFIG_DVB_MXL5XX=m +CONFIG_DVB_STB0899=m +CONFIG_DVB_STB6100=m +CONFIG_DVB_STV090x=m +CONFIG_DVB_STV0910=m +CONFIG_DVB_STV6110x=m +CONFIG_DVB_STV6111=m + +# +# Multistandard (cable + terrestrial) frontends +# +CONFIG_DVB_DRXK=m +CONFIG_DVB_MN88472=m +CONFIG_DVB_MN88473=m +CONFIG_DVB_SI2165=m +CONFIG_DVB_TDA18271C2DD=m + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24116=m +CONFIG_DVB_CX24117=m +CONFIG_DVB_CX24120=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_DS3000=m +CONFIG_DVB_MB86A16=m +CONFIG_DVB_MT312=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_SI21XX=m +CONFIG_DVB_STB6000=m +CONFIG_DVB_STV0288=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_STV0900=m +CONFIG_DVB_STV6110=m +CONFIG_DVB_TDA10071=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA8261=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TS2020=m +CONFIG_DVB_TUA6100=m +CONFIG_DVB_TUNER_CX24113=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_ZL10036=m +CONFIG_DVB_ZL10039=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_AF9013=m +CONFIG_DVB_AS102_FE=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_CXD2820R=m +CONFIG_DVB_CXD2841ER=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +# CONFIG_DVB_DIB9000 is not set +CONFIG_DVB_DRXD=m +CONFIG_DVB_EC100=m +CONFIG_DVB_GP8PSK_FE=m +CONFIG_DVB_L64781=m +CONFIG_DVB_MT352=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_RTL2830=m +CONFIG_DVB_RTL2832=m +CONFIG_DVB_RTL2832_SDR=m +# CONFIG_DVB_S5H1432 is not set +CONFIG_DVB_SI2168=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_STV0367=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_ZD1301_DEMOD=m +CONFIG_DVB_ZL10353=m +# CONFIG_DVB_CXD2880 is not set + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_STV0297=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_VES1820=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_AU8522=m +CONFIG_DVB_AU8522_DTV=m +CONFIG_DVB_AU8522_V4L=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LG2160=m +CONFIG_DVB_LGDT3305=m +CONFIG_DVB_LGDT3306A=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_MXL692=m +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_S5H1411=m + +# +# ISDB-T (terrestrial) frontends +# +CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m +CONFIG_DVB_S921=m + +# +# ISDB-S (satellite) & ISDB-T (terrestrial) frontends +# +# CONFIG_DVB_MN88443X is not set +CONFIG_DVB_TC90522=m + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +CONFIG_DVB_TUNER_DIB0070=m +CONFIG_DVB_TUNER_DIB0090=m + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_A8293=m +CONFIG_DVB_AF9033=m +# CONFIG_DVB_ASCOT2E is not set +CONFIG_DVB_ATBM8830=m +# CONFIG_DVB_HELENE is not set +# CONFIG_DVB_HORUS3A is not set +CONFIG_DVB_ISL6405=m +CONFIG_DVB_ISL6421=m +CONFIG_DVB_ISL6423=m +CONFIG_DVB_IX2505V=m +# CONFIG_DVB_LGS8GL5 is not set +CONFIG_DVB_LGS8GXX=m +CONFIG_DVB_LNBH25=m +# CONFIG_DVB_LNBH29 is not set +CONFIG_DVB_LNBP21=m +CONFIG_DVB_LNBP22=m +CONFIG_DVB_M88RS2000=m +CONFIG_DVB_TDA665x=m +CONFIG_DVB_DRX39XYJ=m + +# +# Common Interface (EN50221) controller drivers +# +CONFIG_DVB_CXD2099=m +CONFIG_DVB_SP2=m +# end of Customise DVB Frontends + +# +# Tools to develop new frontends +# +CONFIG_DVB_DUMMY_FE=m +# end of Media ancillary drivers + +# +# Graphics support +# +CONFIG_APERTURE_HELPERS=y +CONFIG_VIDEO_CMDLINE=y +CONFIG_VIDEO_NOMODESET=y +# CONFIG_AUXDISPLAY is not set +CONFIG_DRM=m +CONFIG_DRM_MIPI_DBI=m +CONFIG_DRM_MIPI_DSI=y +CONFIG_DRM_KUNIT_TEST_HELPERS=m +CONFIG_DRM_KUNIT_TEST=m +CONFIG_DRM_KMS_HELPER=m +# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set +# CONFIG_DRM_DEBUG_MODESET_LOCK is not set +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_FBDEV_OVERALLOC=100 +# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +CONFIG_DRM_DP_AUX_BUS=m +CONFIG_DRM_DISPLAY_HELPER=m +CONFIG_DRM_DISPLAY_DP_HELPER=y +CONFIG_DRM_DISPLAY_HDCP_HELPER=y +CONFIG_DRM_DISPLAY_HDMI_HELPER=y +# CONFIG_DRM_DP_AUX_CHARDEV is not set +CONFIG_DRM_DP_CEC=y +CONFIG_DRM_TTM=m +CONFIG_DRM_EXEC=m +CONFIG_DRM_GPUVM=m +CONFIG_DRM_BUDDY=m +CONFIG_DRM_VRAM_HELPER=m +CONFIG_DRM_TTM_HELPER=m +CONFIG_DRM_GEM_DMA_HELPER=m +CONFIG_DRM_GEM_SHMEM_HELPER=m +CONFIG_DRM_SCHED=m + +# +# I2C encoder or helper chips +# +CONFIG_DRM_I2C_CH7006=m +CONFIG_DRM_I2C_SIL164=m +CONFIG_DRM_I2C_NXP_TDA998X=m +CONFIG_DRM_I2C_NXP_TDA9950=m +# end of I2C encoder or helper chips + +# +# ARM devices +# +CONFIG_DRM_HDLCD=m +CONFIG_DRM_HDLCD_SHOW_UNDERRUN=y +# CONFIG_DRM_MALI_DISPLAY is not set +CONFIG_DRM_KOMEDA=m +# end of ARM devices + +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_AMDGPU is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_XE is not set +CONFIG_DRM_VGEM=m +# CONFIG_DRM_VKMS is not set +CONFIG_DRM_ROCKCHIP=m +CONFIG_ROCKCHIP_VOP=y +CONFIG_ROCKCHIP_VOP2=y +CONFIG_ROCKCHIP_ANALOGIX_DP=y +CONFIG_ROCKCHIP_CDN_DP=y +CONFIG_ROCKCHIP_DW_HDMI=y +CONFIG_ROCKCHIP_DW_MIPI_DSI=y +CONFIG_ROCKCHIP_INNO_HDMI=y +CONFIG_ROCKCHIP_LVDS=y +CONFIG_ROCKCHIP_RGB=y +CONFIG_ROCKCHIP_RK3066_HDMI=y +CONFIG_DRM_VMWGFX=m +CONFIG_DRM_UDL=m +CONFIG_DRM_AST=m +CONFIG_DRM_MGAG200=m +CONFIG_DRM_QXL=m +CONFIG_DRM_VIRTIO_GPU=m +CONFIG_DRM_VIRTIO_GPU_KMS=y +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +CONFIG_DRM_PANEL_ABT_Y030XX067A=m +CONFIG_DRM_PANEL_ARM_VERSATILE=m +# CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596 is not set +# CONFIG_DRM_PANEL_AUO_A030JTN01 is not set +# CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0 is not set +CONFIG_DRM_PANEL_BOE_HIMAX8279D=m +CONFIG_DRM_PANEL_BOE_TV101WUM_NL6=m +CONFIG_DRM_PANEL_DSI_CM=m +CONFIG_DRM_PANEL_LVDS=m +CONFIG_DRM_PANEL_SIMPLE=m +CONFIG_DRM_PANEL_EDP=m +# CONFIG_DRM_PANEL_EBBG_FT8719 is not set +CONFIG_DRM_PANEL_ELIDA_KD35T133=m +CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02=m +CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D=m +# CONFIG_DRM_PANEL_HIMAX_HX8394 is not set +CONFIG_DRM_PANEL_ILITEK_IL9322=m +CONFIG_DRM_PANEL_ILITEK_ILI9341=m +# CONFIG_DRM_PANEL_ILITEK_ILI9805 is not set +CONFIG_DRM_PANEL_ILITEK_ILI9881C=m +# CONFIG_DRM_PANEL_ILITEK_ILI9882T is not set +CONFIG_DRM_PANEL_INNOLUX_EJ030NA=m +CONFIG_DRM_PANEL_INNOLUX_P079ZCA=m +# CONFIG_DRM_PANEL_JADARD_JD9365DA_H3 is not set +CONFIG_DRM_PANEL_JDI_LT070ME05000=m +# CONFIG_DRM_PANEL_JDI_LPM102A188A is not set +# CONFIG_DRM_PANEL_JDI_R63452 is not set +CONFIG_DRM_PANEL_KHADAS_TS050=m +CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04=m +# CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W is not set +CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829=m +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +CONFIG_DRM_PANEL_LG_LB035Q02=m +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966 is not set +CONFIG_DRM_PANEL_NEC_NL8048HL11=m +# CONFIG_DRM_PANEL_NEWVISION_NV3051D is not set +CONFIG_DRM_PANEL_NEWVISION_NV3052C=m +CONFIG_DRM_PANEL_NOVATEK_NT35510=m +CONFIG_DRM_PANEL_NOVATEK_NT35560=m +# CONFIG_DRM_PANEL_NOVATEK_NT35950 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT36523 is not set +CONFIG_DRM_PANEL_NOVATEK_NT36672A=m +CONFIG_DRM_PANEL_NOVATEK_NT39016=m +# CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set +CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO=m +# CONFIG_DRM_PANEL_ORISETECH_OTA5601A is not set +CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m +# CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS is not set +CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00=m +CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m +CONFIG_DRM_PANEL_RAYDIUM_RM67191=m +CONFIG_DRM_PANEL_RAYDIUM_RM68200=m +# CONFIG_DRM_PANEL_RAYDIUM_RM692E5 is not set +CONFIG_DRM_PANEL_RONBO_RB070D30=m +CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20=m +CONFIG_DRM_PANEL_SAMSUNG_DB7430=m +CONFIG_DRM_PANEL_SAMSUNG_S6D16D0=m +CONFIG_DRM_PANEL_SAMSUNG_S6D27A1=m +# CONFIG_DRM_PANEL_SAMSUNG_S6D7AA0 is not set +CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2=m +CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=m +# CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set +CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01=m +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +CONFIG_DRM_PANEL_SAMSUNG_SOFEF00=m +CONFIG_DRM_PANEL_SEIKO_43WVF1G=m +CONFIG_DRM_PANEL_SHARP_LQ101R1SX01=m +CONFIG_DRM_PANEL_SHARP_LS037V7DW01=m +CONFIG_DRM_PANEL_SHARP_LS043T1LE01=m +CONFIG_DRM_PANEL_SHARP_LS060T1SX01=m +CONFIG_DRM_PANEL_SITRONIX_ST7701=m +# CONFIG_DRM_PANEL_SITRONIX_ST7703 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set +# CONFIG_DRM_PANEL_SYNAPTICS_R63353 is not set +CONFIG_DRM_PANEL_SONY_ACX565AKM=m +# CONFIG_DRM_PANEL_SONY_TD4353_JDI is not set +# CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521 is not set +# CONFIG_DRM_PANEL_STARTEK_KD070FHFID015 is not set +CONFIG_DRM_PANEL_TDO_TL070WSH30=m +CONFIG_DRM_PANEL_TPO_TD028TTEC1=m +CONFIG_DRM_PANEL_TPO_TD043MTEA1=m +CONFIG_DRM_PANEL_TPO_TPG110=m +CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m +# CONFIG_DRM_PANEL_VISIONOX_RM69299 is not set +# CONFIG_DRM_PANEL_VISIONOX_VTDR6130 is not set +# CONFIG_DRM_PANEL_VISIONOX_R66451 is not set +CONFIG_DRM_PANEL_WIDECHIPS_WS2401=m +CONFIG_DRM_PANEL_XINPENG_XPP055C272=m +# end of Display Panels + +CONFIG_DRM_BRIDGE=y +CONFIG_DRM_PANEL_BRIDGE=y + +# +# Display Interface Bridges +# +CONFIG_DRM_CHIPONE_ICN6211=m +CONFIG_DRM_CHRONTEL_CH7033=m +CONFIG_DRM_CROS_EC_ANX7688=m +CONFIG_DRM_DISPLAY_CONNECTOR=m +CONFIG_DRM_ITE_IT6505=m +CONFIG_DRM_LONTIUM_LT8912B=m +CONFIG_DRM_LONTIUM_LT9211=m +CONFIG_DRM_LONTIUM_LT9611=m +CONFIG_DRM_LONTIUM_LT9611UXC=m +CONFIG_DRM_ITE_IT66121=m +CONFIG_DRM_LVDS_CODEC=m +# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set +CONFIG_DRM_NWL_MIPI_DSI=m +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +CONFIG_DRM_PARADE_PS8640=m +# CONFIG_DRM_SAMSUNG_DSIM is not set +# CONFIG_DRM_SIL_SII8620 is not set +CONFIG_DRM_SII902X=m +CONFIG_DRM_SII9234=m +CONFIG_DRM_SIMPLE_BRIDGE=m +CONFIG_DRM_THINE_THC63LVD1024=m +# CONFIG_DRM_TOSHIBA_TC358762 is not set +CONFIG_DRM_TOSHIBA_TC358764=m +# CONFIG_DRM_TOSHIBA_TC358767 is not set +CONFIG_DRM_TOSHIBA_TC358768=m +# CONFIG_DRM_TOSHIBA_TC358775 is not set +# CONFIG_DRM_TI_DLPC3433 is not set +# CONFIG_DRM_TI_TFP410 is not set +CONFIG_DRM_TI_SN65DSI83=m +# CONFIG_DRM_TI_SN65DSI86 is not set +CONFIG_DRM_TI_TPD12S015=m +CONFIG_DRM_ANALOGIX_ANX6345=m +CONFIG_DRM_ANALOGIX_ANX78XX=m +CONFIG_DRM_ANALOGIX_DP=m +# CONFIG_DRM_ANALOGIX_ANX7625 is not set +CONFIG_DRM_I2C_ADV7511=m +CONFIG_DRM_I2C_ADV7511_AUDIO=y +CONFIG_DRM_I2C_ADV7511_CEC=y +CONFIG_DRM_CDNS_DSI=m +CONFIG_DRM_CDNS_DSI_J721E=y +# CONFIG_DRM_CDNS_MHDP8546 is not set +CONFIG_DRM_DW_HDMI=m +CONFIG_DRM_DW_HDMI_AHB_AUDIO=m +CONFIG_DRM_DW_HDMI_I2S_AUDIO=m +# CONFIG_DRM_DW_HDMI_GP_AUDIO is not set +CONFIG_DRM_DW_HDMI_CEC=m +CONFIG_DRM_DW_MIPI_DSI=m +# end of Display Interface Bridges + +CONFIG_DRM_ETNAVIV=m +CONFIG_DRM_ETNAVIV_THERMAL=y +CONFIG_DRM_HISI_HIBMC=m +CONFIG_DRM_HISI_KIRIN=m +CONFIG_DRM_LOGICVC=m +# CONFIG_DRM_ARCPGU is not set +CONFIG_DRM_BOCHS=m +# CONFIG_DRM_CIRRUS_QEMU is not set +CONFIG_DRM_GM12U320=m +CONFIG_DRM_PANEL_MIPI_DBI=m +CONFIG_DRM_SIMPLEDRM=m +CONFIG_TINYDRM_HX8357D=m +# CONFIG_TINYDRM_ILI9163 is not set +CONFIG_TINYDRM_ILI9225=m +CONFIG_TINYDRM_ILI9341=m +CONFIG_TINYDRM_ILI9486=m +CONFIG_TINYDRM_MI0283QT=m +CONFIG_TINYDRM_REPAPER=m +CONFIG_TINYDRM_ST7586=m +CONFIG_TINYDRM_ST7735R=m +CONFIG_DRM_PL111=m +CONFIG_DRM_XEN=y +CONFIG_DRM_XEN_FRONTEND=m +CONFIG_DRM_LIMA=m +CONFIG_DRM_PANFROST=m +CONFIG_DRM_PANTHOR=m +CONFIG_DRM_TIDSS=m +CONFIG_DRM_GUD=m +CONFIG_DRM_SSD130X=m +CONFIG_DRM_SSD130X_I2C=m +CONFIG_DRM_SSD130X_SPI=m +# CONFIG_DRM_POWERVR is not set +CONFIG_DRM_EXPORT_FOR_TESTS=y +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y +CONFIG_DRM_LIB_RANDOM=y + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_UVESA=m +CONFIG_FB_EFI=y +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_SMSCUFX is not set +CONFIG_FB_UDL=m +# CONFIG_FB_IBM_GXT4500 is not set +CONFIG_FB_VIRTUAL=m +CONFIG_XEN_FBDEV_FRONTEND=y +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +CONFIG_FB_SIMPLE=m +CONFIG_FB_SSD1307=m +# CONFIG_FB_SM712 is not set +CONFIG_FB_CORE=y +CONFIG_FB_NOTIFY=y +CONFIG_FIRMWARE_EDID=y +CONFIG_FB_DEVICE=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYSMEM_FOPS=y +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_DMAMEM_HELPERS=y +CONFIG_FB_IOMEM_FOPS=y +CONFIG_FB_IOMEM_HELPERS=y +CONFIG_FB_SYSMEM_HELPERS=y +CONFIG_FB_SYSMEM_HELPERS_DEFERRED=y +CONFIG_FB_BACKLIGHT=m +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +# end of Frame buffer Devices + +# +# Backlight & LCD device support +# +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI922X is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +CONFIG_LCD_PLATFORM=m +# CONFIG_LCD_AMS369FG06 is not set +# CONFIG_LCD_LMS501KF03 is not set +# CONFIG_LCD_HX8357 is not set +CONFIG_LCD_OTM3225A=m +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_KTD253 is not set +# CONFIG_BACKLIGHT_KTZ8866 is not set +CONFIG_BACKLIGHT_PWM=m +CONFIG_BACKLIGHT_MT6370=m +CONFIG_BACKLIGHT_QCOM_WLED=m +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +CONFIG_BACKLIGHT_LP855X=y +# CONFIG_BACKLIGHT_MP3309C is not set +CONFIG_BACKLIGHT_GPIO=m +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_BACKLIGHT_ARCXCNN is not set +CONFIG_BACKLIGHT_LED=m +# end of Backlight & LCD device support + +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_HDMI=y + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_DUMMY_CONSOLE_COLUMNS=80 +CONFIG_DUMMY_CONSOLE_ROWS=25 +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION is not set +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set +# end of Console display driver support + +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# end of Graphics support + +# CONFIG_DRM_ACCEL is not set +CONFIG_SOUND=m +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_PCM_ELD=y +CONFIG_SND_PCM_IEC958=y +CONFIG_SND_DMAENGINE_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_SEQ_DEVICE=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_COMPRESS_OFFLOAD=m +CONFIG_SND_JACK=y +CONFIG_SND_JACK_INPUT_DEV=y +# CONFIG_SND_OSSEMUL is not set +CONFIG_SND_PCM_TIMER=y +# CONFIG_SND_HRTIMER is not set +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_PROC_FS=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +CONFIG_SND_CTL_FAST_LOOKUP=y +# CONFIG_SND_DEBUG is not set +CONFIG_SND_CTL_INPUT_VALIDATION=y +CONFIG_SND_VMASTER=y +CONFIG_SND_CTL_LED=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_SEQ_MIDI_EVENT=m +CONFIG_SND_SEQ_MIDI=m +CONFIG_SND_SEQ_MIDI_EMUL=m +CONFIG_SND_SEQ_VIRMIDI=m +# CONFIG_SND_SEQ_UMP is not set +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL3_LIB_SEQ=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_DRIVERS=y +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +# CONFIG_SND_PCMTEST is not set +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_SERIAL_GENERIC=m +CONFIG_SND_MPU401=m +CONFIG_SND_AC97_POWER_SAVE=y +CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 +CONFIG_SND_PCI=y +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AW2=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +CONFIG_SND_BT87X_OVERCLOCK=y +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_OXYGEN_LIB=m +CONFIG_SND_OXYGEN=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CTXFI=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_INDIGOIOX=m +CONFIG_SND_INDIGODJX=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1_SEQ=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_ES1968_INPUT=y +CONFIG_SND_ES1968_RADIO=y +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_LOLA=m +CONFIG_SND_LX6464ES=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MAESTRO3_INPUT=y +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VIRTUOSO=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# HD-Audio +# +CONFIG_SND_HDA=m +CONFIG_SND_HDA_GENERIC_LEDS=y +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDA_HWDEP=y +CONFIG_SND_HDA_RECONFIG=y +CONFIG_SND_HDA_INPUT_BEEP=y +CONFIG_SND_HDA_INPUT_BEEP_MODE=1 +CONFIG_SND_HDA_PATCH_LOADER=y +# CONFIG_SND_HDA_CIRRUS_SCODEC_KUNIT_TEST is not set +CONFIG_SND_HDA_SCODEC_CS35L41=m +CONFIG_SND_HDA_CS_DSP_CONTROLS=m +CONFIG_SND_HDA_SCODEC_CS35L41_I2C=m +CONFIG_SND_HDA_SCODEC_CS35L41_SPI=m +# CONFIG_SND_HDA_SCODEC_CS35L56_I2C is not set +# CONFIG_SND_HDA_SCODEC_CS35L56_SPI is not set +# CONFIG_SND_HDA_SCODEC_TAS2781_I2C is not set +CONFIG_SND_HDA_CODEC_REALTEK=m +CONFIG_SND_HDA_CODEC_ANALOG=m +CONFIG_SND_HDA_CODEC_SIGMATEL=m +CONFIG_SND_HDA_CODEC_VIA=m +CONFIG_SND_HDA_CODEC_HDMI=m +CONFIG_SND_HDA_CODEC_CIRRUS=m +CONFIG_SND_HDA_CODEC_CS8409=m +CONFIG_SND_HDA_CODEC_CONEXANT=m +CONFIG_SND_HDA_CODEC_CA0110=m +CONFIG_SND_HDA_CODEC_CA0132=m +CONFIG_SND_HDA_CODEC_CA0132_DSP=y +CONFIG_SND_HDA_CODEC_CMEDIA=m +CONFIG_SND_HDA_CODEC_SI3054=m +CONFIG_SND_HDA_GENERIC=m +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM=y +# CONFIG_SND_HDA_CTL_DEV_ID is not set +# end of HD-Audio + +CONFIG_SND_HDA_CORE=m +CONFIG_SND_HDA_DSP_LOADER=y +CONFIG_SND_HDA_EXT_CORE=m +CONFIG_SND_HDA_PREALLOC_SIZE=64 +CONFIG_SND_INTEL_NHLT=y +CONFIG_SND_INTEL_DSP_CONFIG=m +CONFIG_SND_INTEL_SOUNDWIRE_ACPI=m +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +# CONFIG_SND_USB_AUDIO_MIDI_V2 is not set +CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER=y +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_6FIRE=m +CONFIG_SND_USB_HIFACE=m +CONFIG_SND_BCD2000=m +CONFIG_SND_USB_LINE6=m +CONFIG_SND_USB_POD=m +CONFIG_SND_USB_PODHD=m +CONFIG_SND_USB_TONEPORT=m +CONFIG_SND_USB_VARIAX=m +CONFIG_SND_SOC=m +CONFIG_SND_SOC_AC97_BUS=y +CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y +CONFIG_SND_SOC_COMPRESS=y +# CONFIG_SND_SOC_TOPOLOGY_BUILD is not set +CONFIG_SND_SOC_UTILS_KUNIT_TEST=m +CONFIG_SND_SOC_ACPI=m +CONFIG_SND_SOC_ADI=m +CONFIG_SND_SOC_ADI_AXI_I2S=m +CONFIG_SND_SOC_ADI_AXI_SPDIF=m +CONFIG_SND_SOC_AMD_ACP=m +CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH=m +CONFIG_SND_SOC_AMD_CZ_RT5645_MACH=m +CONFIG_SND_SOC_AMD_ST_ES8336_MACH=m +# CONFIG_SND_AMD_ACP_CONFIG is not set +CONFIG_SND_ATMEL_SOC=m +CONFIG_SND_SOC_MIKROE_PROTO=m +CONFIG_SND_BCM63XX_I2S_WHISTLER=m +CONFIG_SND_DESIGNWARE_I2S=m +CONFIG_SND_DESIGNWARE_PCM=y + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +CONFIG_SND_SOC_FSL_ASRC=m +CONFIG_SND_SOC_FSL_SAI=m +CONFIG_SND_SOC_FSL_MQS=m +CONFIG_SND_SOC_FSL_AUDMIX=m +CONFIG_SND_SOC_FSL_SSI=m +CONFIG_SND_SOC_FSL_SPDIF=m +CONFIG_SND_SOC_FSL_ESAI=m +CONFIG_SND_SOC_FSL_MICFIL=m +CONFIG_SND_SOC_FSL_EASRC=m +CONFIG_SND_SOC_FSL_XCVR=m +CONFIG_SND_SOC_FSL_UTILS=m +CONFIG_SND_SOC_FSL_RPMSG=m +CONFIG_SND_SOC_IMX_AUDMUX=m +# end of SoC Audio for Freescale CPUs + +# CONFIG_SND_SOC_CHV3_I2S is not set +CONFIG_SND_I2S_HI6210_I2S=m +CONFIG_SND_SOC_IMG=y +CONFIG_SND_SOC_IMG_I2S_IN=m +CONFIG_SND_SOC_IMG_I2S_OUT=m +CONFIG_SND_SOC_IMG_PARALLEL_OUT=m +CONFIG_SND_SOC_IMG_SPDIF_IN=m +CONFIG_SND_SOC_IMG_SPDIF_OUT=m +CONFIG_SND_SOC_IMG_PISTACHIO_INTERNAL_DAC=m +CONFIG_SND_SOC_MTK_BTCVSD=m +CONFIG_SND_SOC_ROCKCHIP=m +CONFIG_SND_SOC_ROCKCHIP_I2S=m +CONFIG_SND_SOC_ROCKCHIP_I2S_TDM=m +CONFIG_SND_SOC_ROCKCHIP_PDM=m +CONFIG_SND_SOC_ROCKCHIP_SPDIF=m +CONFIG_SND_SOC_ROCKCHIP_MAX98090=m +CONFIG_SND_SOC_ROCKCHIP_RT5645=m +CONFIG_SND_SOC_RK3288_HDMI_ANALOG=m +CONFIG_SND_SOC_RK3399_GRU_SOUND=m +CONFIG_SND_SOC_SOF_TOPLEVEL=y +CONFIG_SND_SOC_SOF_PCI=m +CONFIG_SND_SOC_SOF_ACPI=m +CONFIG_SND_SOC_SOF_OF=m +CONFIG_SND_SOC_SOF_IMX_TOPLEVEL=y +# CONFIG_SND_SOC_SOF_MTK_TOPLEVEL is not set + +# +# STMicroelectronics STM32 SOC audio support +# +# end of STMicroelectronics STM32 SOC audio support + +CONFIG_SND_SOC_XILINX_I2S=m +CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER=m +CONFIG_SND_SOC_XILINX_SPDIF=m +CONFIG_SND_SOC_XTFPGA_I2S=m +CONFIG_SND_SOC_I2C_AND_SPI=m + +# +# CODEC drivers +# +CONFIG_SND_SOC_WM_ADSP=m +CONFIG_SND_SOC_AC97_CODEC=m +CONFIG_SND_SOC_ADAU_UTILS=m +CONFIG_SND_SOC_ADAU1372=m +CONFIG_SND_SOC_ADAU1372_I2C=m +CONFIG_SND_SOC_ADAU1372_SPI=m +CONFIG_SND_SOC_ADAU1701=m +CONFIG_SND_SOC_ADAU17X1=m +CONFIG_SND_SOC_ADAU1761=m +CONFIG_SND_SOC_ADAU1761_I2C=m +CONFIG_SND_SOC_ADAU1761_SPI=m +CONFIG_SND_SOC_ADAU7002=m +CONFIG_SND_SOC_ADAU7118=m +CONFIG_SND_SOC_ADAU7118_HW=m +CONFIG_SND_SOC_ADAU7118_I2C=m +CONFIG_SND_SOC_AK4104=m +CONFIG_SND_SOC_AK4118=m +CONFIG_SND_SOC_AK4375=m +CONFIG_SND_SOC_AK4458=m +CONFIG_SND_SOC_AK4554=m +CONFIG_SND_SOC_AK4613=m +CONFIG_SND_SOC_AK4642=m +CONFIG_SND_SOC_AK5386=m +CONFIG_SND_SOC_AK5558=m +CONFIG_SND_SOC_ALC5623=m +# CONFIG_SND_SOC_AUDIO_IIO_AUX is not set +CONFIG_SND_SOC_AW8738=m +# CONFIG_SND_SOC_AW88395 is not set +# CONFIG_SND_SOC_AW88261 is not set +# CONFIG_SND_SOC_AW87390 is not set +# CONFIG_SND_SOC_AW88399 is not set +CONFIG_SND_SOC_BD28623=m +CONFIG_SND_SOC_BT_SCO=m +# CONFIG_SND_SOC_CHV3_CODEC is not set +CONFIG_SND_SOC_CROS_EC_CODEC=m +CONFIG_SND_SOC_CS35L32=m +CONFIG_SND_SOC_CS35L33=m +CONFIG_SND_SOC_CS35L34=m +CONFIG_SND_SOC_CS35L35=m +CONFIG_SND_SOC_CS35L36=m +CONFIG_SND_SOC_CS35L41_LIB=m +CONFIG_SND_SOC_CS35L41=m +CONFIG_SND_SOC_CS35L41_SPI=m +CONFIG_SND_SOC_CS35L41_I2C=m +CONFIG_SND_SOC_CS35L45=m +CONFIG_SND_SOC_CS35L45_SPI=m +CONFIG_SND_SOC_CS35L45_I2C=m +# CONFIG_SND_SOC_CS35L56_I2C is not set +# CONFIG_SND_SOC_CS35L56_SPI is not set +# CONFIG_SND_SOC_CS35L56_SDW is not set +CONFIG_SND_SOC_CS42L42_CORE=m +CONFIG_SND_SOC_CS42L42=m +# CONFIG_SND_SOC_CS42L42_SDW is not set +CONFIG_SND_SOC_CS42L51=m +CONFIG_SND_SOC_CS42L51_I2C=m +CONFIG_SND_SOC_CS42L52=m +CONFIG_SND_SOC_CS42L56=m +CONFIG_SND_SOC_CS42L73=m +CONFIG_SND_SOC_CS42L83=m +CONFIG_SND_SOC_CS4234=m +CONFIG_SND_SOC_CS4265=m +CONFIG_SND_SOC_CS4270=m +CONFIG_SND_SOC_CS4271=m +CONFIG_SND_SOC_CS4271_I2C=m +CONFIG_SND_SOC_CS4271_SPI=m +CONFIG_SND_SOC_CS42XX8=m +CONFIG_SND_SOC_CS42XX8_I2C=m +CONFIG_SND_SOC_CS43130=m +CONFIG_SND_SOC_CS4341=m +CONFIG_SND_SOC_CS4349=m +CONFIG_SND_SOC_CS53L30=m +CONFIG_SND_SOC_CX2072X=m +CONFIG_SND_SOC_DA7213=m +CONFIG_SND_SOC_DA7219=m +CONFIG_SND_SOC_DMIC=m +CONFIG_SND_SOC_HDMI_CODEC=m +CONFIG_SND_SOC_ES7134=m +CONFIG_SND_SOC_ES7241=m +CONFIG_SND_SOC_ES8316=m +CONFIG_SND_SOC_ES8326=m +CONFIG_SND_SOC_ES8328=m +CONFIG_SND_SOC_ES8328_I2C=m +CONFIG_SND_SOC_ES8328_SPI=m +CONFIG_SND_SOC_GTM601=m +CONFIG_SND_SOC_HDA=m +CONFIG_SND_SOC_ICS43432=m +# CONFIG_SND_SOC_IDT821034 is not set +CONFIG_SND_SOC_INNO_RK3036=m +CONFIG_SND_SOC_MAX98088=m +CONFIG_SND_SOC_MAX98090=m +CONFIG_SND_SOC_MAX98357A=m +CONFIG_SND_SOC_MAX98504=m +CONFIG_SND_SOC_MAX9867=m +CONFIG_SND_SOC_MAX98927=m +CONFIG_SND_SOC_MAX98520=m +# CONFIG_SND_SOC_MAX98363 is not set +CONFIG_SND_SOC_MAX98373=m +CONFIG_SND_SOC_MAX98373_I2C=m +CONFIG_SND_SOC_MAX98373_SDW=m +# CONFIG_SND_SOC_MAX98388 is not set +CONFIG_SND_SOC_MAX98390=m +CONFIG_SND_SOC_MAX98396=m +CONFIG_SND_SOC_MAX9860=m +CONFIG_SND_SOC_MSM8916_WCD_ANALOG=m +CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m +CONFIG_SND_SOC_PCM1681=m +CONFIG_SND_SOC_PCM1789=m +CONFIG_SND_SOC_PCM1789_I2C=m +CONFIG_SND_SOC_PCM179X=m +CONFIG_SND_SOC_PCM179X_I2C=m +CONFIG_SND_SOC_PCM179X_SPI=m +CONFIG_SND_SOC_PCM186X=m +CONFIG_SND_SOC_PCM186X_I2C=m +CONFIG_SND_SOC_PCM186X_SPI=m +CONFIG_SND_SOC_PCM3060=m +CONFIG_SND_SOC_PCM3060_I2C=m +CONFIG_SND_SOC_PCM3060_SPI=m +CONFIG_SND_SOC_PCM3168A=m +CONFIG_SND_SOC_PCM3168A_I2C=m +CONFIG_SND_SOC_PCM3168A_SPI=m +CONFIG_SND_SOC_PCM5102A=m +CONFIG_SND_SOC_PCM512x=m +CONFIG_SND_SOC_PCM512x_I2C=m +CONFIG_SND_SOC_PCM512x_SPI=m +# CONFIG_SND_SOC_PEB2466 is not set +CONFIG_SND_SOC_RK3328=m +# CONFIG_SND_SOC_RK817 is not set +CONFIG_SND_SOC_RL6231=m +# CONFIG_SND_SOC_RT1017_SDCA_SDW is not set +CONFIG_SND_SOC_RT1308_SDW=m +CONFIG_SND_SOC_RT1316_SDW=m +# CONFIG_SND_SOC_RT1318_SDW is not set +CONFIG_SND_SOC_RT5514=m +CONFIG_SND_SOC_RT5514_SPI=m +CONFIG_SND_SOC_RT5616=m +CONFIG_SND_SOC_RT5631=m +CONFIG_SND_SOC_RT5640=m +CONFIG_SND_SOC_RT5645=m +CONFIG_SND_SOC_RT5659=m +CONFIG_SND_SOC_RT5682=m +CONFIG_SND_SOC_RT5682_I2C=m +CONFIG_SND_SOC_RT5682_SDW=m +CONFIG_SND_SOC_RT700=m +CONFIG_SND_SOC_RT700_SDW=m +CONFIG_SND_SOC_RT711=m +CONFIG_SND_SOC_RT711_SDW=m +CONFIG_SND_SOC_RT711_SDCA_SDW=m +# CONFIG_SND_SOC_RT712_SDCA_SDW is not set +# CONFIG_SND_SOC_RT712_SDCA_DMIC_SDW is not set +# CONFIG_SND_SOC_RT722_SDCA_SDW is not set +CONFIG_SND_SOC_RT715=m +CONFIG_SND_SOC_RT715_SDW=m +CONFIG_SND_SOC_RT715_SDCA_SDW=m +# CONFIG_SND_SOC_RT9120 is not set +# CONFIG_SND_SOC_RTQ9128 is not set +# CONFIG_SND_SOC_SDW_MOCKUP is not set +CONFIG_SND_SOC_SGTL5000=m +CONFIG_SND_SOC_SIGMADSP=m +CONFIG_SND_SOC_SIGMADSP_I2C=m +CONFIG_SND_SOC_SIGMADSP_REGMAP=m +CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m +CONFIG_SND_SOC_SIMPLE_MUX=m +# CONFIG_SND_SOC_SMA1303 is not set +CONFIG_SND_SOC_SPDIF=m +CONFIG_SND_SOC_SRC4XXX_I2C=m +CONFIG_SND_SOC_SRC4XXX=m +CONFIG_SND_SOC_SSM2305=m +CONFIG_SND_SOC_SSM2518=m +CONFIG_SND_SOC_SSM2602=m +CONFIG_SND_SOC_SSM2602_SPI=m +CONFIG_SND_SOC_SSM2602_I2C=m +# CONFIG_SND_SOC_SSM3515 is not set +CONFIG_SND_SOC_SSM4567=m +CONFIG_SND_SOC_STA32X=m +CONFIG_SND_SOC_STA350=m +CONFIG_SND_SOC_STI_SAS=m +CONFIG_SND_SOC_TAS2552=m +CONFIG_SND_SOC_TAS2562=m +CONFIG_SND_SOC_TAS2764=m +CONFIG_SND_SOC_TAS2770=m +CONFIG_SND_SOC_TAS2780=m +# CONFIG_SND_SOC_TAS2781_I2C is not set +CONFIG_SND_SOC_TAS5086=m +CONFIG_SND_SOC_TAS571X=m +CONFIG_SND_SOC_TAS5720=m +CONFIG_SND_SOC_TAS5805M=m +CONFIG_SND_SOC_TAS6424=m +CONFIG_SND_SOC_TDA7419=m +CONFIG_SND_SOC_TFA9879=m +CONFIG_SND_SOC_TFA989X=m +CONFIG_SND_SOC_TLV320ADC3XXX=m +CONFIG_SND_SOC_TLV320AIC23=m +CONFIG_SND_SOC_TLV320AIC23_I2C=m +CONFIG_SND_SOC_TLV320AIC23_SPI=m +CONFIG_SND_SOC_TLV320AIC31XX=m +CONFIG_SND_SOC_TLV320AIC32X4=m +CONFIG_SND_SOC_TLV320AIC32X4_I2C=m +CONFIG_SND_SOC_TLV320AIC32X4_SPI=m +CONFIG_SND_SOC_TLV320AIC3X=m +CONFIG_SND_SOC_TLV320AIC3X_I2C=m +CONFIG_SND_SOC_TLV320AIC3X_SPI=m +CONFIG_SND_SOC_TLV320ADCX140=m +CONFIG_SND_SOC_TS3A227E=m +CONFIG_SND_SOC_TSCS42XX=m +CONFIG_SND_SOC_TSCS454=m +CONFIG_SND_SOC_UDA1334=m +CONFIG_SND_SOC_WCD_CLASSH=m +CONFIG_SND_SOC_WCD9335=m +CONFIG_SND_SOC_WCD_MBHC=m +CONFIG_SND_SOC_WCD938X=m +CONFIG_SND_SOC_WCD938X_SDW=m +CONFIG_SND_SOC_WM8510=m +CONFIG_SND_SOC_WM8523=m +CONFIG_SND_SOC_WM8524=m +CONFIG_SND_SOC_WM8580=m +CONFIG_SND_SOC_WM8711=m +CONFIG_SND_SOC_WM8728=m +CONFIG_SND_SOC_WM8731=m +CONFIG_SND_SOC_WM8731_I2C=m +CONFIG_SND_SOC_WM8731_SPI=m +CONFIG_SND_SOC_WM8737=m +CONFIG_SND_SOC_WM8741=m +CONFIG_SND_SOC_WM8750=m +CONFIG_SND_SOC_WM8753=m +CONFIG_SND_SOC_WM8770=m +CONFIG_SND_SOC_WM8776=m +CONFIG_SND_SOC_WM8782=m +CONFIG_SND_SOC_WM8804=m +CONFIG_SND_SOC_WM8804_I2C=m +CONFIG_SND_SOC_WM8804_SPI=m +CONFIG_SND_SOC_WM8903=m +CONFIG_SND_SOC_WM8904=m +CONFIG_SND_SOC_WM8940=m +CONFIG_SND_SOC_WM8960=m +# CONFIG_SND_SOC_WM8961 is not set +CONFIG_SND_SOC_WM8962=m +CONFIG_SND_SOC_WM8974=m +CONFIG_SND_SOC_WM8978=m +CONFIG_SND_SOC_WM8985=m +CONFIG_SND_SOC_WSA881X=m +CONFIG_SND_SOC_WSA883X=m +# CONFIG_SND_SOC_WSA884X is not set +CONFIG_SND_SOC_ZL38060=m +CONFIG_SND_SOC_MAX9759=m +CONFIG_SND_SOC_MT6351=m +CONFIG_SND_SOC_MT6358=m +CONFIG_SND_SOC_MT6660=m +CONFIG_SND_SOC_NAU8315=m +CONFIG_SND_SOC_NAU8540=m +CONFIG_SND_SOC_NAU8810=m +CONFIG_SND_SOC_NAU8821=m +CONFIG_SND_SOC_NAU8822=m +CONFIG_SND_SOC_NAU8824=m +CONFIG_SND_SOC_TPA6130A2=m +CONFIG_SND_SOC_LPASS_MACRO_COMMON=m +CONFIG_SND_SOC_LPASS_WSA_MACRO=m +CONFIG_SND_SOC_LPASS_VA_MACRO=m +CONFIG_SND_SOC_LPASS_RX_MACRO=m +CONFIG_SND_SOC_LPASS_TX_MACRO=m +# end of CODEC drivers + +CONFIG_SND_SIMPLE_CARD_UTILS=m +CONFIG_SND_SIMPLE_CARD=m +CONFIG_SND_AUDIO_GRAPH_CARD=m +CONFIG_SND_AUDIO_GRAPH_CARD2=m +CONFIG_SND_AUDIO_GRAPH_CARD2_CUSTOM_SAMPLE=m +CONFIG_SND_TEST_COMPONENT=m +CONFIG_SND_SYNTH_EMUX=m +CONFIG_SND_XEN_FRONTEND=m +CONFIG_SND_VIRTIO=m +CONFIG_AC97_BUS=m +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_BATTERY_STRENGTH=y +CONFIG_HIDRAW=y +CONFIG_UHID=m +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=m +CONFIG_HID_ACCUTOUCH=m +CONFIG_HID_ACRUX=m +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=m +CONFIG_HID_APPLEIR=m +CONFIG_HID_ASUS=m +CONFIG_HID_AUREAL=m +CONFIG_HID_BELKIN=m +CONFIG_HID_BETOP_FF=m +CONFIG_HID_BIGBEN_FF=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CORSAIR=m +CONFIG_HID_COUGAR=m +CONFIG_HID_MACALLY=m +CONFIG_HID_PRODIKEYS=m +CONFIG_HID_CMEDIA=m +CONFIG_HID_CP2112=m +CONFIG_HID_CREATIVE_SB0540=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELAN=m +CONFIG_HID_ELECOM=m +CONFIG_HID_ELO=m +# CONFIG_HID_EVISION is not set +CONFIG_HID_EZKEY=m +CONFIG_HID_FT260=m +CONFIG_HID_GEMBIRD=m +CONFIG_HID_GFRM=m +CONFIG_HID_GLORIOUS=m +CONFIG_HID_HOLTEK=m +CONFIG_HOLTEK_FF=y +CONFIG_HID_VIVALDI_COMMON=m +CONFIG_HID_GOOGLE_HAMMER=m +# CONFIG_HID_GOOGLE_STADIA_FF is not set +CONFIG_HID_VIVALDI=m +CONFIG_HID_GT683R=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_VIEWSONIC=m +CONFIG_HID_VRC2=m +CONFIG_HID_XIAOMI=m +CONFIG_HID_GYRATION=m +CONFIG_HID_ICADE=m +CONFIG_HID_ITE=m +CONFIG_HID_JABRA=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LED=m +CONFIG_HID_LENOVO=m +# CONFIG_HID_LETSKETCH is not set +CONFIG_HID_LOGITECH=m +CONFIG_HID_LOGITECH_DJ=m +CONFIG_HID_LOGITECH_HIDPP=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_LOGIWHEELS_FF=y +CONFIG_HID_MAGICMOUSE=m +CONFIG_HID_MALTRON=m +CONFIG_HID_MAYFLASH=m +CONFIG_HID_MEGAWORLD_FF=m +CONFIG_HID_REDRAGON=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NINTENDO=m +# CONFIG_NINTENDO_FF is not set +CONFIG_HID_NTI=m +CONFIG_HID_NTRIG=m +# CONFIG_HID_NVIDIA_SHIELD is not set +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PENMOUNT=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_PICOLCD_FB=y +CONFIG_HID_PICOLCD_BACKLIGHT=y +CONFIG_HID_PICOLCD_LCD=y +CONFIG_HID_PICOLCD_LEDS=y +CONFIG_HID_PICOLCD_CIR=y +CONFIG_HID_PLANTRONICS=m +CONFIG_HID_PXRC=m +# CONFIG_HID_RAZER is not set +CONFIG_HID_PRIMAX=m +CONFIG_HID_RETRODE=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAITEK=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SEMITEK=m +# CONFIG_HID_SIGMAMICRO is not set +CONFIG_HID_SONY=m +CONFIG_SONY_FF=y +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_STEAM=m +# CONFIG_STEAM_FF is not set +CONFIG_HID_STEELSERIES=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_RMI=m +CONFIG_HID_GREENASIA=m +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TIVO=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_TOPRE=m +CONFIG_HID_THINGM=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_THRUSTMASTER_FF=y +CONFIG_HID_UDRAW_PS3=m +CONFIG_HID_U2FZERO=m +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_XINMO=m +CONFIG_HID_ZEROPLUS=m +CONFIG_ZEROPLUS_FF=y +CONFIG_HID_ZYDACRON=m +CONFIG_HID_SENSOR_HUB=m +CONFIG_HID_SENSOR_CUSTOM_SENSOR=m +CONFIG_HID_ALPS=m +# CONFIG_HID_MCP2200 is not set +CONFIG_HID_MCP2221=m +# CONFIG_HID_KUNIT_TEST is not set +# end of Special HID drivers + +# +# HID-BPF support +# +# end of HID-BPF support + +# +# USB HID support +# +CONFIG_USB_HID=y +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y +# end of USB HID support + +CONFIG_I2C_HID=y +CONFIG_I2C_HID_ACPI=m +CONFIG_I2C_HID_OF=m +CONFIG_I2C_HID_OF_ELAN=m +CONFIG_I2C_HID_OF_GOODIX=m +CONFIG_I2C_HID_CORE=m +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_LED_TRIG=y +CONFIG_USB_ULPI_BUS=y +CONFIG_USB_CONN_GPIO=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_PCI=y +# CONFIG_USB_PCI_AMD is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_FEW_INIT_RETRIES is not set +CONFIG_USB_DYNAMIC_MINORS=y +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_PRODUCTLIST is not set +# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set +CONFIG_USB_OTG_FSM=m +CONFIG_USB_LEDS_TRIGGER_USBPORT=y +CONFIG_USB_AUTOSUSPEND_DELAY=2 +CONFIG_USB_MON=m + +# +# USB Host Controller Drivers +# +CONFIG_USB_C67X00_HCD=m +CONFIG_USB_XHCI_HCD=y +# CONFIG_USB_XHCI_DBGCAP is not set +CONFIG_USB_XHCI_PCI=y +# CONFIG_USB_XHCI_PCI_RENESAS is not set +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_EHCI_FSL=m +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_OXU210HP_HCD=m +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_MAX3421_HCD=m +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PCI=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_HCD_ISO=y +CONFIG_USB_R8A66597_HCD=m +CONFIG_USB_HCD_BCMA=m +CONFIG_USB_HCD_SSB=m +CONFIG_USB_HCD_TEST_MODE=y +# CONFIG_USB_XEN_HCD is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=m +CONFIG_USB_TMC=m + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_REALTEK_AUTOPM=y +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_ENE_UB6250=m +CONFIG_USB_UAS=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USBIP_CORE=m +CONFIG_USBIP_VHCI_HCD=m +CONFIG_USBIP_VHCI_HC_PORTS=8 +CONFIG_USBIP_VHCI_NR_HCS=1 +CONFIG_USBIP_HOST=m +CONFIG_USBIP_VUDC=m +# CONFIG_USBIP_DEBUG is not set + +# +# USB dual-mode controller drivers +# +CONFIG_USB_CDNS_SUPPORT=m +CONFIG_USB_CDNS_HOST=y +CONFIG_USB_CDNS3=m +# CONFIG_USB_CDNS3_GADGET is not set +# CONFIG_USB_CDNS3_HOST is not set +CONFIG_USB_CDNS3_PCI_WRAP=m +CONFIG_USB_CDNSP_PCI=m +CONFIG_USB_CDNSP_GADGET=y +CONFIG_USB_CDNSP_HOST=y +CONFIG_USB_MUSB_HDRC=y +# CONFIG_USB_MUSB_HOST is not set +# CONFIG_USB_MUSB_GADGET is not set +CONFIG_USB_MUSB_DUAL_ROLE=y + +# +# Platform Glue Layer +# + +# +# MUSB DMA mode +# +# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_ULPI=y +# CONFIG_USB_DWC3_HOST is not set +# CONFIG_USB_DWC3_GADGET is not set +CONFIG_USB_DWC3_DUAL_ROLE=y + +# +# Platform Glue Driver Support +# +CONFIG_USB_DWC3_PCI=y +CONFIG_USB_DWC3_HAPS=y +CONFIG_USB_DWC3_OF_SIMPLE=y +CONFIG_USB_DWC2=y +# CONFIG_USB_DWC2_HOST is not set + +# +# Gadget/Dual-role mode requires USB Gadget support to be enabled +# +# CONFIG_USB_DWC2_PERIPHERAL is not set +CONFIG_USB_DWC2_DUAL_ROLE=y +CONFIG_USB_DWC2_PCI=m +# CONFIG_USB_DWC2_DEBUG is not set +# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_CHIPIDEA_PCI=y +CONFIG_USB_CHIPIDEA_MSM=y +CONFIG_USB_CHIPIDEA_NPCM=y +CONFIG_USB_CHIPIDEA_IMX=y +CONFIG_USB_CHIPIDEA_GENERIC=y +CONFIG_USB_CHIPIDEA_TEGRA=y +CONFIG_USB_ISP1760=y +CONFIG_USB_ISP1760_HCD=y +CONFIG_USB_ISP1761_UDC=y +# CONFIG_USB_ISP1760_HOST_ROLE is not set +# CONFIG_USB_ISP1760_GADGET_ROLE is not set +CONFIG_USB_ISP1760_DUAL_ROLE=y + +# +# USB port drivers +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F81232=m +CONFIG_USB_SERIAL_F8153X=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_METRO=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MXUPORT=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_UPD78F0730=m +CONFIG_USB_SERIAL_XR=m +CONFIG_USB_SERIAL_DEBUG=m + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_APPLE_MFI_FASTCHARGE=m +# CONFIG_USB_LJCA is not set +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_TEST=m +CONFIG_USB_EHSET_TEST_FIXTURE=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_YUREX=m +CONFIG_USB_EZUSB_FX2=m +CONFIG_USB_HUB_USB251XB=m +CONFIG_USB_HSIC_USB3503=y +CONFIG_USB_HSIC_USB4604=m +CONFIG_USB_LINK_LAYER_TEST=m +CONFIG_USB_CHAOSKEY=m +CONFIG_USB_ONBOARD_HUB=m +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_ISP1301=m +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +# end of USB Physical Layer drivers + +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_U_SERIAL_CONSOLE=y + +# +# USB Peripheral Controller +# +CONFIG_USB_GR_UDC=m +CONFIG_USB_R8A66597=m +CONFIG_USB_PXA27X=m +CONFIG_USB_MV_UDC=m +CONFIG_USB_MV_U3D=m +CONFIG_USB_SNP_CORE=m +CONFIG_USB_SNP_UDC_PLAT=m +CONFIG_USB_M66592=m +CONFIG_USB_BDC_UDC=m +CONFIG_USB_AMD5536UDC=m +CONFIG_USB_NET2272=m +# CONFIG_USB_NET2272_DMA is not set +CONFIG_USB_NET2280=m +CONFIG_USB_GOKU=m +CONFIG_USB_EG20T=m +CONFIG_USB_GADGET_XILINX=m +CONFIG_USB_MAX3420_UDC=m +# CONFIG_USB_CDNS2_UDC is not set +CONFIG_USB_DUMMY_HCD=m +# end of USB Peripheral Controller + +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_F_ACM=m +CONFIG_USB_F_SS_LB=m +CONFIG_USB_U_SERIAL=m +CONFIG_USB_U_ETHER=m +CONFIG_USB_U_AUDIO=m +CONFIG_USB_F_SERIAL=m +CONFIG_USB_F_OBEX=m +CONFIG_USB_F_NCM=m +CONFIG_USB_F_ECM=m +CONFIG_USB_F_PHONET=m +CONFIG_USB_F_EEM=m +CONFIG_USB_F_SUBSET=m +CONFIG_USB_F_RNDIS=m +CONFIG_USB_F_MASS_STORAGE=m +CONFIG_USB_F_FS=m +CONFIG_USB_F_UAC1=m +CONFIG_USB_F_UAC1_LEGACY=m +CONFIG_USB_F_UAC2=m +CONFIG_USB_F_UVC=m +CONFIG_USB_F_MIDI=m +CONFIG_USB_F_HID=m +CONFIG_USB_F_PRINTER=m +CONFIG_USB_F_TCM=m +CONFIG_USB_CONFIGFS=m +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +# CONFIG_USB_CONFIGFS_PHONET is not set +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_LB_SS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_UAC1=y +CONFIG_USB_CONFIGFS_F_UAC1_LEGACY=y +CONFIG_USB_CONFIGFS_F_UAC2=y +CONFIG_USB_CONFIGFS_F_MIDI=y +# CONFIG_USB_CONFIGFS_F_MIDI2 is not set +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_CONFIGFS_F_UVC=y +CONFIG_USB_CONFIGFS_F_PRINTER=y +CONFIG_USB_CONFIGFS_F_TCM=y + +# +# USB Gadget precomposed configurations +# +CONFIG_USB_ZERO=m +# CONFIG_USB_ZERO_HNPTEST is not set +CONFIG_USB_AUDIO=m +CONFIG_GADGET_UAC1=y +# CONFIG_GADGET_UAC1_LEGACY is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_ETH_EEM=y +CONFIG_USB_G_NCM=m +CONFIG_USB_GADGETFS=m +CONFIG_USB_FUNCTIONFS=m +CONFIG_USB_FUNCTIONFS_ETH=y +CONFIG_USB_FUNCTIONFS_RNDIS=y +CONFIG_USB_FUNCTIONFS_GENERIC=y +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_GADGET_TARGET=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_MIDI_GADGET=m +CONFIG_USB_G_PRINTER=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_G_NOKIA=m +CONFIG_USB_G_ACM_MS=m +CONFIG_USB_G_MULTI=m +CONFIG_USB_G_MULTI_RNDIS=y +CONFIG_USB_G_MULTI_CDC=y +CONFIG_USB_G_HID=m +# CONFIG_USB_G_DBGP is not set +CONFIG_USB_G_WEBCAM=m +CONFIG_USB_RAW_GADGET=m +# end of USB Gadget precomposed configurations + +CONFIG_TYPEC=y +CONFIG_TYPEC_TCPM=m +CONFIG_TYPEC_TCPCI=m +CONFIG_TYPEC_RT1711H=m +CONFIG_TYPEC_TCPCI_MT6370=m +CONFIG_TYPEC_TCPCI_MAXIM=m +CONFIG_TYPEC_FUSB302=m +CONFIG_TYPEC_UCSI=m +CONFIG_UCSI_CCG=m +CONFIG_UCSI_ACPI=m +CONFIG_UCSI_STM32G0=m +CONFIG_TYPEC_TPS6598X=m +CONFIG_TYPEC_ANX7411=m +CONFIG_TYPEC_RT1719=m +CONFIG_TYPEC_HD3SS3220=m +CONFIG_TYPEC_STUSB160X=m +CONFIG_TYPEC_WUSB3801=m + +# +# USB Type-C Multiplexer/DeMultiplexer Switch support +# +CONFIG_TYPEC_MUX_FSA4480=m +# CONFIG_TYPEC_MUX_GPIO_SBU is not set +CONFIG_TYPEC_MUX_PI3USB30532=m +# CONFIG_TYPEC_MUX_NB7VPQ904M is not set +# CONFIG_TYPEC_MUX_PTN36502 is not set +# CONFIG_TYPEC_MUX_WCD939X_USBSS is not set +# end of USB Type-C Multiplexer/DeMultiplexer Switch support + +# +# USB Type-C Alternate Mode drivers +# +CONFIG_TYPEC_DP_ALTMODE=m +CONFIG_TYPEC_NVIDIA_ALTMODE=m +# end of USB Type-C Alternate Mode drivers + +CONFIG_USB_ROLE_SWITCH=y +CONFIG_MMC=y +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SD8787=m +CONFIG_PWRSEQ_SIMPLE=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_SDIO_UART=m +CONFIG_MMC_TEST=y + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_ARMMMCI=y +CONFIG_MMC_STM32_SDMMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_ACPI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_OF_ARASAN=y +CONFIG_MMC_SDHCI_OF_AT91=m +CONFIG_MMC_SDHCI_OF_DWCMSHC=y +CONFIG_MMC_SDHCI_CADENCE=y +CONFIG_MMC_SDHCI_F_SDH30=y +CONFIG_MMC_SDHCI_MILBEAUT=m +CONFIG_MMC_ALCOR=m +CONFIG_MMC_TIFM_SD=m +CONFIG_MMC_SPI=y +# CONFIG_MMC_CB710 is not set +CONFIG_MMC_VIA_SDMMC=m +CONFIG_MMC_DW=y +CONFIG_MMC_DW_PLTFM=y +CONFIG_MMC_DW_BLUEFIELD=m +CONFIG_MMC_DW_EXYNOS=y +CONFIG_MMC_DW_HI3798CV200=y +CONFIG_MMC_DW_K3=y +# CONFIG_MMC_DW_PCI is not set +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_MMC_VUB300=m +CONFIG_MMC_USHC=m +CONFIG_MMC_USDHI6ROL0=m +CONFIG_MMC_REALTEK_PCI=m +CONFIG_MMC_REALTEK_USB=m +CONFIG_MMC_CQHCI=y +CONFIG_MMC_HSQ=m +# CONFIG_MMC_TOSHIBA_PCI is not set +CONFIG_MMC_MTK=m +CONFIG_MMC_SDHCI_XENON=y +# CONFIG_MMC_LITEX is not set +CONFIG_SCSI_UFSHCD=y +# CONFIG_SCSI_UFS_BSG is not set +CONFIG_SCSI_UFS_HWMON=y +CONFIG_SCSI_UFSHCD_PCI=m +# CONFIG_SCSI_UFS_DWC_TC_PCI is not set +CONFIG_SCSI_UFSHCD_PLATFORM=y +# CONFIG_SCSI_UFS_CDNS_PLATFORM is not set +# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_CLASS_FLASH=m +# CONFIG_LEDS_CLASS_MULTICOLOR is not set +# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set + +# +# LED drivers +# +CONFIG_LEDS_AN30259A=m +# CONFIG_LEDS_AW200XX is not set +# CONFIG_LEDS_AW2013 is not set +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +CONFIG_LEDS_CR0014114=m +CONFIG_LEDS_EL15203000=m +# CONFIG_LEDS_LM3530 is not set +CONFIG_LEDS_LM3532=m +# CONFIG_LEDS_LM3642 is not set +CONFIG_LEDS_LM3692X=m +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP3952 is not set +# CONFIG_LEDS_LP50XX is not set +# CONFIG_LEDS_LP55XX_COMMON is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_PCA995X is not set +# CONFIG_LEDS_DAC124S085 is not set +CONFIG_LEDS_PWM=m +CONFIG_LEDS_REGULATOR=m +# CONFIG_LEDS_BD2606MVV is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_IS31FL319X is not set +# CONFIG_LEDS_IS31FL32XX is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +CONFIG_LEDS_SYSCON=y +CONFIG_LEDS_MLXREG=m +CONFIG_LEDS_USER=y +CONFIG_LEDS_SPI_BYTE=m +CONFIG_LEDS_TI_LMU_COMMON=m +CONFIG_LEDS_LM3697=m + +# +# Flash and Torch LED drivers +# +# CONFIG_LEDS_AAT1290 is not set +# CONFIG_LEDS_AS3645A is not set +# CONFIG_LEDS_KTD2692 is not set +# CONFIG_LEDS_LM3601X is not set +# CONFIG_LEDS_MT6370_FLASH is not set +# CONFIG_LEDS_RT4505 is not set +# CONFIG_LEDS_RT8515 is not set +# CONFIG_LEDS_SGM3140 is not set + +# +# RGB LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_ONESHOT=m +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LEDS_TRIGGER_MTD=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=m +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_ACTIVITY=y +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=m +CONFIG_LEDS_TRIGGER_PATTERN=m +CONFIG_LEDS_TRIGGER_AUDIO=m +CONFIG_LEDS_TRIGGER_TTY=m + +# +# Simple LED drivers +# +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_EDAC_SUPPORT=y +CONFIG_EDAC=y +CONFIG_EDAC_LEGACY_SYSFS=y +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_GHES=y +# CONFIG_EDAC_THUNDERX is not set +# CONFIG_EDAC_XGENE is not set +CONFIG_EDAC_DMC520=m +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set +CONFIG_RTC_LIB_KUNIT_TEST=m +CONFIG_RTC_NVMEM=y + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABEOZ9 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +CONFIG_RTC_DRV_HYM8563=y +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_MAX31335 is not set +# CONFIG_RTC_DRV_NCT3018Y is not set +CONFIG_RTC_DRV_RK808=m +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12026 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF85363 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8010 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3028 is not set +# CONFIG_RTC_DRV_RV3032 is not set +# CONFIG_RTC_DRV_RV8803 is not set +# CONFIG_RTC_DRV_SD3078 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_MCP795 is not set +CONFIG_RTC_I2C_AND_SPI=y + +# +# SPI and I2C RTC drivers +# +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_RX6110 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_EFI is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +CONFIG_RTC_DRV_OPTEE=m +# CONFIG_RTC_DRV_ZYNQMP is not set +# CONFIG_RTC_DRV_CROS_EC is not set +# CONFIG_RTC_DRV_NTXEC is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_CADENCE is not set +# CONFIG_RTC_DRV_FTRTC010 is not set +# CONFIG_RTC_DRV_R7301 is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +# CONFIG_RTC_DRV_GOLDFISH is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DMA_ACPI=y +CONFIG_DMA_OF=y +CONFIG_ALTERA_MSGDMA=m +# CONFIG_AMBA_PL08X is not set +CONFIG_BCM_SBA_RAID=m +CONFIG_DW_AXI_DMAC=m +CONFIG_FSL_EDMA=y +CONFIG_FSL_QDMA=m +# CONFIG_INTEL_IDMA64 is not set +CONFIG_MV_XOR_V2=y +CONFIG_PL330_DMA=y +CONFIG_PLX_DMA=m +# CONFIG_XILINX_DMA is not set +# CONFIG_XILINX_XDMA is not set +# CONFIG_XILINX_ZYNQMP_DMA is not set +# CONFIG_XILINX_ZYNQMP_DPDMA is not set +CONFIG_QCOM_HIDMA_MGMT=y +CONFIG_QCOM_HIDMA=y +CONFIG_DW_DMAC_CORE=m +CONFIG_DW_DMAC=m +CONFIG_DW_DMAC_PCI=m +CONFIG_DW_EDMA=m +CONFIG_DW_EDMA_PCIE=m +CONFIG_SF_PDMA=m + +# +# DMA Clients +# +CONFIG_ASYNC_TX_DMA=y +# CONFIG_DMATEST is not set +CONFIG_DMA_ENGINE_RAID=y + +# +# DMABUF options +# +CONFIG_SYNC_FILE=y +# CONFIG_SW_SYNC is not set +CONFIG_UDMABUF=y +# CONFIG_DMABUF_MOVE_NOTIFY is not set +# CONFIG_DMABUF_DEBUG is not set +CONFIG_DMABUF_SELFTESTS=m +CONFIG_DMABUF_HEAPS=y +CONFIG_DMABUF_SYSFS_STATS=y +CONFIG_DMABUF_HEAPS_SYSTEM=y +CONFIG_DMABUF_HEAPS_CMA=y +# end of DMABUF options + +CONFIG_UIO=m +CONFIG_UIO_CIF=m +# CONFIG_UIO_PDRV_GENIRQ is not set +# CONFIG_UIO_DMEM_GENIRQ is not set +CONFIG_UIO_AEC=m +CONFIG_UIO_SERCOS3=m +CONFIG_UIO_PCI_GENERIC=m +# CONFIG_UIO_NETX is not set +# CONFIG_UIO_PRUSS is not set +# CONFIG_UIO_MF624 is not set +CONFIG_VFIO=y +CONFIG_VFIO_GROUP=y +CONFIG_VFIO_CONTAINER=y +CONFIG_VFIO_IOMMU_TYPE1=y +# CONFIG_VFIO_NOIOMMU is not set +CONFIG_VFIO_VIRQFD=y +# CONFIG_VFIO_DEBUGFS is not set + +# +# VFIO support for PCI devices +# +CONFIG_VFIO_PCI_CORE=y +CONFIG_VFIO_PCI_MMAP=y +CONFIG_VFIO_PCI_INTX=y +CONFIG_VFIO_PCI=y +CONFIG_MLX5_VFIO_PCI=m +# CONFIG_HISI_ACC_VFIO_PCI is not set +# end of VFIO support for PCI devices + +# +# VFIO support for platform devices +# +# CONFIG_VFIO_PLATFORM is not set +# CONFIG_VFIO_AMBA is not set +# end of VFIO support for platform devices + +CONFIG_IRQ_BYPASS_MANAGER=y +CONFIG_VIRT_DRIVERS=y +CONFIG_VMGENID=y +CONFIG_NITRO_ENCLAVES=m +CONFIG_VIRTIO_ANCHOR=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_PCI_LIB=y +CONFIG_VIRTIO_PCI_LIB_LEGACY=y +CONFIG_VIRTIO_MENU=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_PCI_LEGACY=y +CONFIG_VIRTIO_VDPA=m +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_INPUT=m +CONFIG_VIRTIO_MMIO=y +# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set +CONFIG_VIRTIO_DMA_SHARED_BUFFER=m +CONFIG_VDPA=m +CONFIG_VDPA_SIM=m +CONFIG_VDPA_SIM_NET=m +CONFIG_VDPA_SIM_BLOCK=m +CONFIG_VDPA_USER=m +CONFIG_IFCVF=m +CONFIG_MLX5_VDPA=y +CONFIG_MLX5_VDPA_NET=m +# CONFIG_MLX5_VDPA_STEERING_DEBUG is not set +CONFIG_VP_VDPA=m +# CONFIG_SNET_VDPA is not set +CONFIG_VHOST_IOTLB=m +CONFIG_VHOST_RING=m +CONFIG_VHOST_TASK=y +CONFIG_VHOST=m +CONFIG_VHOST_MENU=y +CONFIG_VHOST_NET=m +CONFIG_VHOST_SCSI=m +# CONFIG_VHOST_VSOCK is not set +CONFIG_VHOST_VDPA=m +# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set + +# +# Microsoft Hyper-V guest support +# +# CONFIG_HYPERV is not set +# end of Microsoft Hyper-V guest support + +# +# Xen driver support +# +CONFIG_XEN_BALLOON=y +CONFIG_XEN_SCRUB_PAGES_DEFAULT=y +CONFIG_XEN_DEV_EVTCHN=y +CONFIG_XEN_BACKEND=y +CONFIG_XENFS=y +CONFIG_XEN_COMPAT_XENFS=y +CONFIG_XEN_SYS_HYPERVISOR=y +CONFIG_XEN_XENBUS_FRONTEND=y +CONFIG_XEN_GNTDEV=y +CONFIG_XEN_GRANT_DEV_ALLOC=y +# CONFIG_XEN_GRANT_DMA_ALLOC is not set +CONFIG_SWIOTLB_XEN=y +CONFIG_XEN_PCI_STUB=y +CONFIG_XEN_PCIDEV_STUB=m +# CONFIG_XEN_PVCALLS_FRONTEND is not set +# CONFIG_XEN_PVCALLS_BACKEND is not set +CONFIG_XEN_SCSI_BACKEND=m +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_EFI=y +CONFIG_XEN_AUTO_XLATE=y +CONFIG_XEN_FRONT_PGDIR_SHBUF=m +# CONFIG_XEN_VIRTIO is not set +# end of Xen driver support + +# CONFIG_GREYBUS is not set +# CONFIG_COMEDI is not set +CONFIG_STAGING=y +# CONFIG_PRISM2_USB is not set +CONFIG_RTLLIB=m +CONFIG_RTLLIB_CRYPTO_CCMP=m +CONFIG_RTLLIB_CRYPTO_TKIP=m +CONFIG_RTLLIB_CRYPTO_WEP=m +CONFIG_RTL8192E=m +CONFIG_RTL8723BS=m +CONFIG_R8712U=m +CONFIG_RTS5208=m +CONFIG_VT6655=m +CONFIG_VT6656=m + +# +# IIO staging drivers +# + +# +# Accelerometers +# +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16240 is not set +# end of Accelerometers + +# +# Analog to digital converters +# +# CONFIG_AD7816 is not set +# end of Analog to digital converters + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set +# end of Analog digital bi-direction converters + +# +# Direct Digital Synthesis +# +CONFIG_AD9832=m +CONFIG_AD9834=m +# end of Direct Digital Synthesis + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set +# end of Network Analyzer, Impedance Converters +# end of IIO staging drivers + +CONFIG_FB_SM750=m +CONFIG_STAGING_MEDIA=y +CONFIG_DVB_AV7110_IR=y +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET_PATCH=m +CONFIG_DVB_SP8870=m +# CONFIG_VIDEO_MAX96712 is not set +CONFIG_VIDEO_ROCKCHIP_VDEC=m + +# +# StarFive media platform drivers +# +CONFIG_STAGING_MEDIA_DEPRECATED=y + +# +# Atmel media platform drivers +# +# CONFIG_STAGING_BOARD is not set +# CONFIG_LTE_GDM724X is not set +CONFIG_FB_TFT=m +CONFIG_FB_TFT_AGM1264K_FL=m +CONFIG_FB_TFT_BD663474=m +CONFIG_FB_TFT_HX8340BN=m +CONFIG_FB_TFT_HX8347D=m +CONFIG_FB_TFT_HX8353D=m +CONFIG_FB_TFT_HX8357D=m +CONFIG_FB_TFT_ILI9163=m +CONFIG_FB_TFT_ILI9320=m +CONFIG_FB_TFT_ILI9325=m +CONFIG_FB_TFT_ILI9340=m +CONFIG_FB_TFT_ILI9341=m +CONFIG_FB_TFT_ILI9481=m +CONFIG_FB_TFT_ILI9486=m +CONFIG_FB_TFT_PCD8544=m +CONFIG_FB_TFT_RA8875=m +CONFIG_FB_TFT_S6D02A1=m +CONFIG_FB_TFT_S6D1121=m +CONFIG_FB_TFT_SEPS525=m +CONFIG_FB_TFT_SH1106=m +CONFIG_FB_TFT_SSD1289=m +CONFIG_FB_TFT_SSD1305=m +CONFIG_FB_TFT_SSD1306=m +CONFIG_FB_TFT_SSD1331=m +CONFIG_FB_TFT_SSD1351=m +CONFIG_FB_TFT_ST7735R=m +CONFIG_FB_TFT_ST7789V=m +CONFIG_FB_TFT_TINYLCD=m +CONFIG_FB_TFT_TLS8204=m +CONFIG_FB_TFT_UC1611=m +CONFIG_FB_TFT_UC1701=m +CONFIG_FB_TFT_UPD161704=m +# CONFIG_MOST_COMPONENTS is not set +# CONFIG_KS7010 is not set +# CONFIG_PI433 is not set +# CONFIG_XIL_AXIS_FIFO is not set +CONFIG_FIELDBUS_DEV=m +CONFIG_HMS_ANYBUSS_BUS=m +# CONFIG_ARCX_ANYBUS_CONTROLLER is not set +# CONFIG_HMS_PROFINET is not set +# CONFIG_VME_BUS is not set +# CONFIG_RTL8723CS is not set +# CONFIG_GOLDFISH is not set +CONFIG_CHROME_PLATFORMS=y +CONFIG_CHROMEOS_ACPI=m +# CONFIG_CHROMEOS_TBMC is not set +CONFIG_CROS_EC=y +CONFIG_CROS_EC_I2C=y +# CONFIG_CROS_EC_RPMSG is not set +CONFIG_CROS_EC_SPI=y +# CONFIG_CROS_EC_UART is not set +CONFIG_CROS_EC_PROTO=y +# CONFIG_CROS_KBD_LED_BACKLIGHT is not set +CONFIG_CROS_EC_CHARDEV=y +CONFIG_CROS_EC_LIGHTBAR=y +CONFIG_CROS_EC_VBC=y +CONFIG_CROS_EC_DEBUGFS=y +CONFIG_CROS_EC_SENSORHUB=y +CONFIG_CROS_EC_SYSFS=y +CONFIG_CROS_EC_TYPEC=m +# CONFIG_CROS_HPS_I2C is not set +CONFIG_CROS_USBPD_NOTIFY=y +# CONFIG_CHROMEOS_PRIVACY_SCREEN is not set +CONFIG_CROS_TYPEC_SWITCH=m +# CONFIG_CROS_KUNIT_EC_PROTO_TEST is not set +# CONFIG_MELLANOX_PLATFORM is not set +CONFIG_SURFACE_PLATFORMS=y +# CONFIG_SURFACE_3_POWER_OPREGION is not set +# CONFIG_SURFACE_GPE is not set +# CONFIG_SURFACE_HOTPLUG is not set +# CONFIG_SURFACE_PRO3_BUTTON is not set +# CONFIG_SURFACE_AGGREGATOR is not set +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Clock driver for ARM Reference designs +# +# CONFIG_CLK_ICST is not set +# CONFIG_CLK_SP810 is not set +# CONFIG_CLK_VEXPRESS_OSC is not set +# end of Clock driver for ARM Reference designs + +# CONFIG_LMK04832 is not set +# CONFIG_COMMON_CLK_MAX9485 is not set +CONFIG_COMMON_CLK_RK808=m +CONFIG_COMMON_CLK_SCMI=y +# CONFIG_COMMON_CLK_SCPI is not set +# CONFIG_COMMON_CLK_SI5341 is not set +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI544 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE706 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set +# CONFIG_COMMON_CLK_AXI_CLKGEN is not set +# CONFIG_COMMON_CLK_XGENE is not set +CONFIG_COMMON_CLK_PWM=y +# CONFIG_COMMON_CLK_RS9_PCIE is not set +# CONFIG_COMMON_CLK_SI521XX is not set +# CONFIG_COMMON_CLK_VC3 is not set +# CONFIG_COMMON_CLK_VC5 is not set +# CONFIG_COMMON_CLK_VC7 is not set +# CONFIG_COMMON_CLK_FIXED_MMIO is not set +CONFIG_COMMON_CLK_ROCKCHIP=y +CONFIG_CLK_PX30=y +CONFIG_CLK_RK3308=y +CONFIG_CLK_RK3328=y +CONFIG_CLK_RK3368=y +CONFIG_CLK_RK3399=y +CONFIG_CLK_RK3568=y +CONFIG_CLK_RK3588=y +# CONFIG_XILINX_VCU is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +# CONFIG_CLK_KUNIT_TEST is not set +# CONFIG_CLK_GATE_KUNIT_TEST is not set +# CONFIG_CLK_FD_KUNIT_TEST is not set +# CONFIG_HWSPINLOCK is not set + +# +# Clock Source drivers +# +CONFIG_TIMER_OF=y +CONFIG_TIMER_ACPI=y +CONFIG_TIMER_PROBE=y +CONFIG_CLKSRC_MMIO=y +CONFIG_ROCKCHIP_TIMER=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_FSL_ERRATUM_A008585=y +CONFIG_HISILICON_ERRATUM_161010101=y +CONFIG_ARM64_ERRATUM_858921=y +# end of Clock Source drivers + +CONFIG_MAILBOX=y +CONFIG_ARM_MHU=y +CONFIG_ARM_MHU_V2=m +CONFIG_PLATFORM_MHU=y +# CONFIG_PL320_MBOX is not set +CONFIG_ROCKCHIP_MBOX=y +CONFIG_PCC=y +# CONFIG_ALTERA_MBOX is not set +# CONFIG_MAILBOX_TEST is not set +CONFIG_IOMMU_IOVA=y +CONFIG_IOMMU_API=y +CONFIG_IOMMUFD_DRIVER=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +CONFIG_IOMMU_IO_PGTABLE=y +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S_SELFTEST is not set +# CONFIG_IOMMU_IO_PGTABLE_DART is not set +# end of Generic IOMMU Pagetable Support + +# CONFIG_IOMMU_DEBUGFS is not set +CONFIG_IOMMU_DEFAULT_DMA_STRICT=y +# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set +CONFIG_OF_IOMMU=y +CONFIG_IOMMU_DMA=y +CONFIG_IOMMU_SVA=y +# CONFIG_IOMMUFD is not set +CONFIG_ROCKCHIP_IOMMU=y +CONFIG_ARM_SMMU=y +# CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS is not set +CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y +CONFIG_ARM_SMMU_V3=y +CONFIG_ARM_SMMU_V3_SVA=y +CONFIG_VIRTIO_IOMMU=m + +# +# Remoteproc drivers +# +CONFIG_REMOTEPROC=y +# CONFIG_REMOTEPROC_CDEV is not set +# end of Remoteproc drivers + +# +# Rpmsg drivers +# +CONFIG_RPMSG=y +# CONFIG_RPMSG_CHAR is not set +# CONFIG_RPMSG_CTRL is not set +CONFIG_RPMSG_NS=m +CONFIG_RPMSG_QCOM_GLINK=y +CONFIG_RPMSG_QCOM_GLINK_RPM=y +# CONFIG_RPMSG_VIRTIO is not set +# end of Rpmsg drivers + +CONFIG_SOUNDWIRE=m + +# +# SoundWire Devices +# +# CONFIG_SOUNDWIRE_AMD is not set +# CONFIG_SOUNDWIRE_INTEL is not set +CONFIG_SOUNDWIRE_QCOM=m + +# +# SOC (System On Chip) specific Drivers +# + +# +# Amlogic SoC drivers +# +# end of Amlogic SoC drivers + +# +# Broadcom SoC drivers +# +# end of Broadcom SoC drivers + +# +# NXP/Freescale QorIQ SoC drivers +# +# CONFIG_QUICC_ENGINE is not set +# CONFIG_FSL_RCPM is not set +# end of NXP/Freescale QorIQ SoC drivers + +# +# fujitsu SoC drivers +# +# CONFIG_A64FX_DIAG is not set +# end of fujitsu SoC drivers + +# +# i.MX SoC drivers +# +# end of i.MX SoC drivers + +# +# Enable LiteX SoC Builder specific drivers +# +CONFIG_LITEX=y +CONFIG_LITEX_SOC_CONTROLLER=m +# end of Enable LiteX SoC Builder specific drivers + +# CONFIG_WPCM450_SOC is not set + +# +# Qualcomm SoC drivers +# +# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set +# CONFIG_QCOM_PMIC_GLINK is not set +CONFIG_QCOM_QMI_HELPERS=m +# end of Qualcomm SoC drivers + +CONFIG_ROCKCHIP_GRF=y +CONFIG_ROCKCHIP_IODOMAIN=y +CONFIG_SOC_TI=y + +# +# Xilinx SoC drivers +# +# end of Xilinx SoC drivers +# end of SOC (System On Chip) specific Drivers + +# +# PM Domains +# + +# +# Amlogic PM Domains +# +# end of Amlogic PM Domains + +CONFIG_ARM_SCMI_PERF_DOMAIN=y +CONFIG_ARM_SCMI_POWER_DOMAIN=y +CONFIG_ARM_SCPI_POWER_DOMAIN=y + +# +# Broadcom PM Domains +# +# end of Broadcom PM Domains + +# +# i.MX PM Domains +# +# end of i.MX PM Domains + +# +# Qualcomm PM Domains +# +# end of Qualcomm PM Domains + +CONFIG_ROCKCHIP_PM_DOMAINS=y +# end of PM Domains + +CONFIG_PM_DEVFREQ=y + +# +# DEVFREQ Governors +# +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=m +CONFIG_DEVFREQ_GOV_POWERSAVE=m +CONFIG_DEVFREQ_GOV_USERSPACE=m +CONFIG_DEVFREQ_GOV_PASSIVE=m + +# +# DEVFREQ Drivers +# +CONFIG_ARM_RK3399_DMC_DEVFREQ=y +CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +CONFIG_EXTCON=y + +# +# Extcon Device Drivers +# +CONFIG_EXTCON_ADC_JACK=m +# CONFIG_EXTCON_FSA9480 is not set +CONFIG_EXTCON_GPIO=y +# CONFIG_EXTCON_MAX3355 is not set +CONFIG_EXTCON_PTN5150=m +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +CONFIG_EXTCON_USB_GPIO=y +CONFIG_EXTCON_USBC_CROS_EC=y +CONFIG_EXTCON_USBC_TUSB320=m +CONFIG_MEMORY=y +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_BUFFER_CB=m +# CONFIG_IIO_BUFFER_DMA is not set +# CONFIG_IIO_BUFFER_DMAENGINE is not set +CONFIG_IIO_BUFFER_HW_CONSUMER=m +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGERED_BUFFER=y +CONFIG_IIO_CONFIGFS=m +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 +CONFIG_IIO_SW_DEVICE=m +CONFIG_IIO_SW_TRIGGER=m +CONFIG_IIO_TRIGGERED_EVENT=m + +# +# Accelerometers +# +CONFIG_ADIS16201=m +CONFIG_ADIS16209=m +CONFIG_ADXL313=m +CONFIG_ADXL313_I2C=m +CONFIG_ADXL313_SPI=m +CONFIG_ADXL345=m +CONFIG_ADXL345_I2C=m +CONFIG_ADXL345_SPI=m +CONFIG_ADXL355=m +CONFIG_ADXL355_I2C=m +CONFIG_ADXL355_SPI=m +CONFIG_ADXL367=m +CONFIG_ADXL367_SPI=m +CONFIG_ADXL367_I2C=m +CONFIG_ADXL372=m +CONFIG_ADXL372_SPI=m +CONFIG_ADXL372_I2C=m +CONFIG_BMA180=m +CONFIG_BMA220=m +CONFIG_BMA400=m +CONFIG_BMA400_I2C=m +CONFIG_BMA400_SPI=m +CONFIG_BMC150_ACCEL=m +CONFIG_BMC150_ACCEL_I2C=m +CONFIG_BMC150_ACCEL_SPI=m +CONFIG_BMI088_ACCEL=m +CONFIG_BMI088_ACCEL_SPI=m +CONFIG_DA280=m +CONFIG_DA311=m +CONFIG_DMARD06=m +CONFIG_DMARD09=m +CONFIG_DMARD10=m +CONFIG_FXLS8962AF=m +CONFIG_FXLS8962AF_I2C=m +CONFIG_FXLS8962AF_SPI=m +CONFIG_HID_SENSOR_ACCEL_3D=m +CONFIG_IIO_CROS_EC_ACCEL_LEGACY=m +CONFIG_IIO_ST_ACCEL_3AXIS=m +CONFIG_IIO_ST_ACCEL_I2C_3AXIS=m +CONFIG_IIO_ST_ACCEL_SPI_3AXIS=m +# CONFIG_IIO_KX022A_SPI is not set +# CONFIG_IIO_KX022A_I2C is not set +CONFIG_KXSD9=m +CONFIG_KXSD9_SPI=m +CONFIG_KXSD9_I2C=m +CONFIG_KXCJK1013=m +CONFIG_MC3230=m +CONFIG_MMA7455=m +CONFIG_MMA7455_I2C=m +CONFIG_MMA7455_SPI=m +CONFIG_MMA7660=m +CONFIG_MMA8452=m +CONFIG_MMA9551_CORE=m +CONFIG_MMA9551=m +CONFIG_MMA9553=m +# CONFIG_MSA311 is not set +CONFIG_MXC4005=m +CONFIG_MXC6255=m +CONFIG_SCA3000=m +CONFIG_SCA3300=m +CONFIG_STK8312=m +CONFIG_STK8BA50=m +# end of Accelerometers + +# +# Analog to digital converters +# +CONFIG_AD_SIGMA_DELTA=m +# CONFIG_AD4130 is not set +CONFIG_AD7091R=m +CONFIG_AD7091R5=m +# CONFIG_AD7091R8 is not set +CONFIG_AD7124=m +# CONFIG_AD7192 is not set +CONFIG_AD7266=m +# CONFIG_AD7280 is not set +CONFIG_AD7291=m +CONFIG_AD7292=m +CONFIG_AD7298=m +CONFIG_AD7476=m +CONFIG_AD7606=m +CONFIG_AD7606_IFACE_PARALLEL=m +CONFIG_AD7606_IFACE_SPI=m +CONFIG_AD7766=m +CONFIG_AD7768_1=m +# CONFIG_AD7780 is not set +CONFIG_AD7791=m +CONFIG_AD7793=m +CONFIG_AD7887=m +CONFIG_AD7923=m +CONFIG_AD7949=m +CONFIG_AD799X=m +# CONFIG_ADI_AXI_ADC is not set +# CONFIG_CC10001_ADC is not set +# CONFIG_ENVELOPE_DETECTOR is not set +# CONFIG_HI8435 is not set +# CONFIG_HX711 is not set +# CONFIG_INA2XX_ADC is not set +# CONFIG_LTC2309 is not set +# CONFIG_LTC2471 is not set +# CONFIG_LTC2485 is not set +CONFIG_LTC2496=m +# CONFIG_LTC2497 is not set +# CONFIG_MAX1027 is not set +# CONFIG_MAX11100 is not set +# CONFIG_MAX1118 is not set +CONFIG_MAX11205=m +# CONFIG_MAX11410 is not set +# CONFIG_MAX1241 is not set +CONFIG_MAX1363=m +# CONFIG_MAX34408 is not set +CONFIG_MAX9611=m +CONFIG_MCP320X=m +CONFIG_MCP3422=m +# CONFIG_MCP3564 is not set +CONFIG_MCP3911=m +# CONFIG_MEDIATEK_MT6370_ADC is not set +# CONFIG_NAU7802 is not set +# CONFIG_QCOM_SPMI_IADC is not set +# CONFIG_QCOM_SPMI_VADC is not set +# CONFIG_QCOM_SPMI_ADC5 is not set +CONFIG_ROCKCHIP_SARADC=y +CONFIG_RICHTEK_RTQ6056=m +# CONFIG_SD_ADC_MODULATOR is not set +CONFIG_TI_ADC081C=m +CONFIG_TI_ADC0832=m +CONFIG_TI_ADC084S021=m +CONFIG_TI_ADC12138=m +CONFIG_TI_ADC108S102=m +CONFIG_TI_ADC128S052=m +CONFIG_TI_ADC161S626=m +CONFIG_TI_ADS1015=m +# CONFIG_TI_ADS7924 is not set +# CONFIG_TI_ADS1100 is not set +CONFIG_TI_ADS7950=m +CONFIG_TI_ADS8344=m +CONFIG_TI_ADS8688=m +CONFIG_TI_ADS124S08=m +CONFIG_TI_ADS131E08=m +# CONFIG_TI_LMP92064 is not set +# CONFIG_TI_TLC4541 is not set +CONFIG_TI_TSC2046=m +# CONFIG_VF610_ADC is not set +CONFIG_XILINX_XADC=m +# end of Analog to digital converters + +# +# Analog to digital and digital to analog converters +# +# CONFIG_AD74115 is not set +# CONFIG_AD74413R is not set +# end of Analog to digital and digital to analog converters + +# +# Analog Front Ends +# +# CONFIG_IIO_RESCALE is not set +# end of Analog Front Ends + +# +# Amplifiers +# +# CONFIG_AD8366 is not set +# CONFIG_ADA4250 is not set +CONFIG_HMC425=m +# end of Amplifiers + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7746 is not set +# end of Capacitance to digital converters + +# +# Chemical Sensors +# +# CONFIG_AOSONG_AGS02MA is not set +# CONFIG_ATLAS_PH_SENSOR is not set +# CONFIG_ATLAS_EZO_SENSOR is not set +CONFIG_BME680=m +CONFIG_BME680_I2C=m +CONFIG_BME680_SPI=m +# CONFIG_CCS811 is not set +# CONFIG_IAQCORE is not set +CONFIG_PMS7003=m +# CONFIG_SCD30_CORE is not set +CONFIG_SCD4X=m +CONFIG_SENSIRION_SGP30=m +CONFIG_SENSIRION_SGP40=m +CONFIG_SPS30=m +CONFIG_SPS30_I2C=m +CONFIG_SPS30_SERIAL=m +CONFIG_SENSEAIR_SUNRISE_CO2=m +# CONFIG_VZ89X is not set +# end of Chemical Sensors + +CONFIG_IIO_CROS_EC_SENSORS_CORE=m +CONFIG_IIO_CROS_EC_SENSORS=m +# CONFIG_IIO_CROS_EC_SENSORS_LID_ANGLE is not set + +# +# Hid Sensor IIO Common +# +CONFIG_HID_SENSOR_IIO_COMMON=m +CONFIG_HID_SENSOR_IIO_TRIGGER=m +# end of Hid Sensor IIO Common + +CONFIG_IIO_MS_SENSORS_I2C=m + +# +# IIO SCMI Sensors +# +CONFIG_IIO_SCMI=m +# end of IIO SCMI Sensors + +# +# SSP Sensor Common +# +# CONFIG_IIO_SSP_SENSORHUB is not set +# end of SSP Sensor Common + +CONFIG_IIO_ST_SENSORS_I2C=m +CONFIG_IIO_ST_SENSORS_SPI=m +CONFIG_IIO_ST_SENSORS_CORE=m + +# +# Digital to analog converters +# +# CONFIG_AD3552R is not set +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5592R is not set +# CONFIG_AD5593R is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_LTC2688 is not set +CONFIG_AD5686=m +CONFIG_AD5686_SPI=m +CONFIG_AD5696_I2C=m +# CONFIG_AD5755 is not set +CONFIG_AD5758=m +# CONFIG_AD5761 is not set +# CONFIG_AD5764 is not set +CONFIG_AD5766=m +CONFIG_AD5770R=m +# CONFIG_AD5791 is not set +# CONFIG_AD7293 is not set +# CONFIG_AD7303 is not set +# CONFIG_AD8801 is not set +# CONFIG_DPOT_DAC is not set +# CONFIG_DS4424 is not set +CONFIG_LTC1660=m +# CONFIG_LTC2632 is not set +# CONFIG_M62332 is not set +# CONFIG_MAX517 is not set +# CONFIG_MAX5522 is not set +# CONFIG_MAX5821 is not set +# CONFIG_MCP4725 is not set +# CONFIG_MCP4728 is not set +# CONFIG_MCP4821 is not set +# CONFIG_MCP4922 is not set +# CONFIG_TI_DAC082S085 is not set +CONFIG_TI_DAC5571=m +CONFIG_TI_DAC7311=m +CONFIG_TI_DAC7612=m +# CONFIG_VF610_DAC is not set +# end of Digital to analog converters + +# +# IIO dummy driver +# +CONFIG_IIO_SIMPLE_DUMMY=m +# CONFIG_IIO_SIMPLE_DUMMY_EVENTS is not set +# CONFIG_IIO_SIMPLE_DUMMY_BUFFER is not set +# end of IIO dummy driver + +# +# Filters +# +# CONFIG_ADMV8818 is not set +# end of Filters + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +CONFIG_AD9523=m +# end of Clock Generator/Distribution + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set +CONFIG_ADF4371=m +# CONFIG_ADF4377 is not set +# CONFIG_ADMV1013 is not set +# CONFIG_ADMV1014 is not set +# CONFIG_ADMV4420 is not set +CONFIG_ADRF6780=m +# end of Phase-Locked Loop (PLL) frequency synthesizers +# end of Frequency Synthesizers DDS/PLL + +# +# Digital gyroscope sensors +# +CONFIG_ADIS16080=m +CONFIG_ADIS16130=m +CONFIG_ADIS16136=m +CONFIG_ADIS16260=m +# CONFIG_ADXRS290 is not set +CONFIG_ADXRS450=m +CONFIG_BMG160=m +CONFIG_BMG160_I2C=m +CONFIG_BMG160_SPI=m +CONFIG_FXAS21002C=m +CONFIG_FXAS21002C_I2C=m +CONFIG_FXAS21002C_SPI=m +CONFIG_HID_SENSOR_GYRO_3D=m +CONFIG_MPU3050=m +CONFIG_MPU3050_I2C=m +CONFIG_IIO_ST_GYRO_3AXIS=m +CONFIG_IIO_ST_GYRO_I2C_3AXIS=m +CONFIG_IIO_ST_GYRO_SPI_3AXIS=m +CONFIG_ITG3200=m +# end of Digital gyroscope sensors + +# +# Health Sensors +# + +# +# Heart Rate Monitors +# +CONFIG_AFE4403=m +CONFIG_AFE4404=m +CONFIG_MAX30100=m +CONFIG_MAX30102=m +# end of Heart Rate Monitors +# end of Health Sensors + +# +# Humidity sensors +# +CONFIG_AM2315=m +CONFIG_DHT11=m +CONFIG_HDC100X=m +# CONFIG_HDC2010 is not set +# CONFIG_HDC3020 is not set +CONFIG_HID_SENSOR_HUMIDITY=m +CONFIG_HTS221=m +CONFIG_HTS221_I2C=m +CONFIG_HTS221_SPI=m +CONFIG_HTU21=m +CONFIG_SI7005=m +CONFIG_SI7020=m +# end of Humidity sensors + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set +CONFIG_ADIS16460=m +# CONFIG_ADIS16475 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_BMI160_I2C is not set +# CONFIG_BMI160_SPI is not set +# CONFIG_BMI323_I2C is not set +# CONFIG_BMI323_SPI is not set +# CONFIG_BOSCH_BNO055_SERIAL is not set +# CONFIG_BOSCH_BNO055_I2C is not set +CONFIG_FXOS8700=m +CONFIG_FXOS8700_I2C=m +CONFIG_FXOS8700_SPI=m +# CONFIG_KMX61 is not set +# CONFIG_INV_ICM42600_I2C is not set +# CONFIG_INV_ICM42600_SPI is not set +# CONFIG_INV_MPU6050_I2C is not set +# CONFIG_INV_MPU6050_SPI is not set +# CONFIG_IIO_ST_LSM6DSX is not set +CONFIG_IIO_ST_LSM9DS0=m +CONFIG_IIO_ST_LSM9DS0_I2C=m +CONFIG_IIO_ST_LSM9DS0_SPI=m +# end of Inertial measurement units + +CONFIG_IIO_ADIS_LIB=m +CONFIG_IIO_ADIS_LIB_BUFFER=y + +# +# Light sensors +# +CONFIG_ACPI_ALS=m +CONFIG_ADJD_S311=m +CONFIG_ADUX1020=m +CONFIG_AL3010=m +CONFIG_AL3320A=m +CONFIG_APDS9300=m +CONFIG_APDS9960=m +# CONFIG_AS73211 is not set +CONFIG_BH1750=m +CONFIG_BH1780=m +CONFIG_CM32181=m +CONFIG_CM3232=m +CONFIG_CM3323=m +CONFIG_CM3605=m +CONFIG_CM36651=m +CONFIG_IIO_CROS_EC_LIGHT_PROX=m +CONFIG_GP2AP002=m +CONFIG_GP2AP020A00F=m +CONFIG_SENSORS_ISL29018=m +CONFIG_SENSORS_ISL29028=m +CONFIG_ISL29125=m +# CONFIG_ISL76682 is not set +CONFIG_HID_SENSOR_ALS=m +CONFIG_HID_SENSOR_PROX=m +CONFIG_JSA1212=m +# CONFIG_ROHM_BU27008 is not set +# CONFIG_ROHM_BU27034 is not set +CONFIG_RPR0521=m +# CONFIG_LTR390 is not set +CONFIG_LTR501=m +# CONFIG_LTRF216A is not set +CONFIG_LV0104CS=m +CONFIG_MAX44000=m +CONFIG_MAX44009=m +CONFIG_NOA1305=m +CONFIG_OPT3001=m +# CONFIG_OPT4001 is not set +CONFIG_PA12203001=m +CONFIG_SI1133=m +CONFIG_SI1145=m +CONFIG_STK3310=m +CONFIG_ST_UVIS25=m +CONFIG_ST_UVIS25_I2C=m +CONFIG_ST_UVIS25_SPI=m +CONFIG_TCS3414=m +CONFIG_TCS3472=m +CONFIG_SENSORS_TSL2563=m +CONFIG_TSL2583=m +CONFIG_TSL2591=m +CONFIG_TSL2772=m +CONFIG_TSL4531=m +CONFIG_US5182D=m +CONFIG_VCNL4000=m +CONFIG_VCNL4035=m +CONFIG_VEML6030=m +CONFIG_VEML6070=m +# CONFIG_VEML6075 is not set +CONFIG_VL6180=m +CONFIG_ZOPT2201=m +# end of Light sensors + +# +# Magnetometer sensors +# +CONFIG_AK8974=m +CONFIG_AK8975=m +CONFIG_AK09911=m +CONFIG_BMC150_MAGN=m +CONFIG_BMC150_MAGN_I2C=m +CONFIG_BMC150_MAGN_SPI=m +CONFIG_MAG3110=m +CONFIG_HID_SENSOR_MAGNETOMETER_3D=m +CONFIG_MMC35240=m +CONFIG_IIO_ST_MAGN_3AXIS=m +CONFIG_IIO_ST_MAGN_I2C_3AXIS=m +CONFIG_IIO_ST_MAGN_SPI_3AXIS=m +CONFIG_SENSORS_HMC5843=m +CONFIG_SENSORS_HMC5843_I2C=m +CONFIG_SENSORS_HMC5843_SPI=m +CONFIG_SENSORS_RM3100=m +CONFIG_SENSORS_RM3100_I2C=m +CONFIG_SENSORS_RM3100_SPI=m +# CONFIG_TI_TMAG5273 is not set +CONFIG_YAMAHA_YAS530=m +# end of Magnetometer sensors + +# +# Multiplexers +# +# CONFIG_IIO_MUX is not set +# end of Multiplexers + +# +# Inclinometer sensors +# +CONFIG_HID_SENSOR_INCLINOMETER_3D=m +CONFIG_HID_SENSOR_DEVICE_ROTATION=m +# end of Inclinometer sensors + +CONFIG_IIO_FORMAT_KUNIT_TEST=m + +# +# Triggers - standalone +# +CONFIG_IIO_HRTIMER_TRIGGER=m +CONFIG_IIO_INTERRUPT_TRIGGER=m +CONFIG_IIO_TIGHTLOOP_TRIGGER=m +CONFIG_IIO_SYSFS_TRIGGER=m +# end of Triggers - standalone + +# +# Linear and angular position sensors +# +CONFIG_HID_SENSOR_CUSTOM_INTEL_HINGE=m +# end of Linear and angular position sensors + +# +# Digital potentiometers +# +CONFIG_AD5110=m +CONFIG_AD5272=m +CONFIG_DS1803=m +CONFIG_MAX5432=m +# CONFIG_MAX5481 is not set +# CONFIG_MAX5487 is not set +CONFIG_MCP4018=m +# CONFIG_MCP4131 is not set +# CONFIG_MCP4531 is not set +CONFIG_MCP41010=m +# CONFIG_TPL0102 is not set +# CONFIG_X9250 is not set +# end of Digital potentiometers + +# +# Digital potentiostats +# +# CONFIG_LMP91000 is not set +# end of Digital potentiostats + +# +# Pressure sensors +# +# CONFIG_ABP060MG is not set +# CONFIG_ROHM_BM1390 is not set +CONFIG_BMP280=m +CONFIG_BMP280_I2C=m +CONFIG_BMP280_SPI=m +# CONFIG_IIO_CROS_EC_BARO is not set +CONFIG_DLHL60D=m +CONFIG_DPS310=m +CONFIG_HID_SENSOR_PRESS=m +# CONFIG_HP03 is not set +# CONFIG_HSC030PA is not set +CONFIG_ICP10100=m +# CONFIG_MPL115_I2C is not set +# CONFIG_MPL115_SPI is not set +CONFIG_MPL3115=m +# CONFIG_MPRLS0025PA is not set +# CONFIG_MS5611 is not set +# CONFIG_MS5637 is not set +# CONFIG_IIO_ST_PRESS is not set +# CONFIG_T5403 is not set +# CONFIG_HP206C is not set +# CONFIG_ZPA2326 is not set +# end of Pressure sensors + +# +# Lightning sensors +# +# CONFIG_AS3935 is not set +# end of Lightning sensors + +# +# Proximity and distance sensors +# +CONFIG_CROS_EC_MKBP_PROXIMITY=m +# CONFIG_IRSD200 is not set +CONFIG_ISL29501=m +# CONFIG_LIDAR_LITE_V2 is not set +CONFIG_MB1232=m +CONFIG_PING=m +# CONFIG_RFD77402 is not set +# CONFIG_SRF04 is not set +# CONFIG_SX9310 is not set +# CONFIG_SX9324 is not set +# CONFIG_SX9360 is not set +# CONFIG_SX9500 is not set +# CONFIG_SRF08 is not set +# CONFIG_VCNL3020 is not set +CONFIG_VL53L0X_I2C=m +# end of Proximity and distance sensors + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set +# end of Resolver to digital converters + +# +# Temperature sensors +# +CONFIG_LTC2983=m +CONFIG_MAXIM_THERMOCOUPLE=m +CONFIG_HID_SENSOR_TEMP=m +CONFIG_MLX90614=m +CONFIG_MLX90632=m +# CONFIG_MLX90635 is not set +CONFIG_TMP006=m +CONFIG_TMP007=m +CONFIG_TMP117=m +CONFIG_TSYS01=m +CONFIG_TSYS02D=m +# CONFIG_MAX30208 is not set +CONFIG_MAX31856=m +CONFIG_MAX31865=m +# CONFIG_MCP9600 is not set +# end of Temperature sensors + +# CONFIG_NTB is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +# CONFIG_PWM_DEBUG is not set +CONFIG_PWM_ATMEL_TCB=m +CONFIG_PWM_CLK=m +CONFIG_PWM_CROS_EC=m +CONFIG_PWM_DWC_CORE=m +CONFIG_PWM_DWC=m +# CONFIG_PWM_FSL_FTM is not set +CONFIG_PWM_NTXEC=m +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWM_ROCKCHIP=y +CONFIG_PWM_XILINX=m + +# +# IRQ chip support +# +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_MAX_NR=1 +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +# CONFIG_AL_FIC is not set +# CONFIG_XILINX_INTC is not set +CONFIG_PARTITION_PERCPU=y +# end of IRQ chip support + +# CONFIG_IPACK_BUS is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_SCMI=y +# CONFIG_RESET_SIMPLE is not set +# CONFIG_RESET_TI_SYSCON is not set +CONFIG_RESET_TI_TPS380X=m + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PHY_MIPI_DPHY=y +CONFIG_PHY_CAN_TRANSCEIVER=m + +# +# PHY drivers for Broadcom platforms +# +CONFIG_BCM_KONA_USB2_PHY=m +# end of PHY drivers for Broadcom platforms + +CONFIG_PHY_CADENCE_TORRENT=m +CONFIG_PHY_CADENCE_DPHY=m +# CONFIG_PHY_CADENCE_DPHY_RX is not set +CONFIG_PHY_CADENCE_SIERRA=m +# CONFIG_PHY_CADENCE_SALVO is not set +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_PHY_LAN966X_SERDES is not set +# CONFIG_PHY_CPCAP_USB is not set +CONFIG_PHY_MAPPHONE_MDM6600=m +# CONFIG_PHY_OCELOT_SERDES is not set +CONFIG_PHY_QCOM_USB_HS=y +CONFIG_PHY_QCOM_USB_HSIC=y +CONFIG_PHY_ROCKCHIP_DP=y +CONFIG_PHY_ROCKCHIP_DPHY_RX0=m +CONFIG_PHY_ROCKCHIP_EMMC=y +CONFIG_PHY_ROCKCHIP_INNO_HDMI=y +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY=m +CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y +CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=y +CONFIG_PHY_ROCKCHIP_PCIE=y +CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX=m +CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=m +CONFIG_PHY_ROCKCHIP_TYPEC=y +CONFIG_PHY_ROCKCHIP_USB=y +CONFIG_PHY_ROCKCHIP_USBDP=y +CONFIG_PHY_SAMSUNG_USB2=y +# CONFIG_PHY_TUSB1210 is not set +# end of PHY Subsystem + +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set + +# +# Performance monitor support +# +CONFIG_ARM_CCI_PMU=y +CONFIG_ARM_CCI400_PMU=y +CONFIG_ARM_CCI5xx_PMU=y +CONFIG_ARM_CCN=y +# CONFIG_ARM_CMN is not set +CONFIG_ARM_PMU=y +CONFIG_ARM_PMU_ACPI=y +CONFIG_ARM_SMMU_V3_PMU=m +CONFIG_ARM_PMUV3=y +# CONFIG_ARM_DSU_PMU is not set +# CONFIG_ARM_SPE_PMU is not set +CONFIG_ARM_DMC620_PMU=m +CONFIG_ALIBABA_UNCORE_DRW_PMU=m +CONFIG_HISI_PMU=y +# CONFIG_HISI_PCIE_PMU is not set +CONFIG_HNS3_PMU=m +# CONFIG_DWC_PCIE_PMU is not set +# CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU is not set +# end of Performance monitor support + +CONFIG_RAS=y +# CONFIG_USB4 is not set + +# +# Android +# +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y +CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder,vndbinder,anbox-binder,anbox-hwbinder,anbox-vndbinder" +# CONFIG_ANDROID_BINDER_IPC_SELFTEST is not set +# end of Android + +# CONFIG_LIBNVDIMM is not set +CONFIG_DAX=y +CONFIG_DEV_DAX=m +CONFIG_DEV_DAX_HMEM=m +CONFIG_DEV_DAX_CXL=m +CONFIG_DEV_DAX_HMEM_DEVICES=y +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y +CONFIG_NVMEM_LAYOUTS=y + +# +# Layout Types +# +# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set +# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set +# end of Layout Types + +CONFIG_NVMEM_RMEM=m +CONFIG_NVMEM_ROCKCHIP_EFUSE=m +CONFIG_NVMEM_ROCKCHIP_OTP=m +CONFIG_NVMEM_SPMI_SDAM=m +CONFIG_NVMEM_U_BOOT_ENV=m + +# +# HW tracing support +# +# CONFIG_STM is not set +# CONFIG_INTEL_TH is not set +CONFIG_HISI_PTT=m +# end of HW tracing support + +CONFIG_FPGA=y +# CONFIG_ALTERA_PR_IP_CORE is not set +# CONFIG_FPGA_MGR_ALTERA_PS_SPI is not set +# CONFIG_FPGA_MGR_ALTERA_CVP is not set +# CONFIG_FPGA_MGR_XILINX_SPI is not set +# CONFIG_FPGA_MGR_ICE40_SPI is not set +# CONFIG_FPGA_MGR_MACHXO2_SPI is not set +CONFIG_FPGA_BRIDGE=m +CONFIG_ALTERA_FREEZE_BRIDGE=m +# CONFIG_XILINX_PR_DECOUPLER is not set +CONFIG_FPGA_REGION=m +CONFIG_OF_FPGA_REGION=m +# CONFIG_FPGA_DFL is not set +CONFIG_FPGA_MGR_MICROCHIP_SPI=m +# CONFIG_FPGA_MGR_LATTICE_SYSCONFIG_SPI is not set +# CONFIG_FSI is not set +CONFIG_TEE=y +CONFIG_OPTEE=y +# CONFIG_OPTEE_INSECURE_LOAD_IMAGE is not set +CONFIG_MULTIPLEXER=y + +# +# Multiplexer drivers +# +CONFIG_MUX_ADG792A=m +CONFIG_MUX_ADGS1408=m +CONFIG_MUX_GPIO=m +CONFIG_MUX_MMIO=m +# end of Multiplexer drivers + +CONFIG_PM_OPP=y +# CONFIG_SIOX is not set +CONFIG_SLIMBUS=m +CONFIG_SLIM_QCOM_CTRL=m +CONFIG_INTERCONNECT=y +CONFIG_COUNTER=m +CONFIG_INTERRUPT_CNT=m +CONFIG_MOST=m +# CONFIG_MOST_USB_HDM is not set +# CONFIG_MOST_CDEV is not set +CONFIG_MOST_SND=m +# CONFIG_PECI is not set +# CONFIG_HTE is not set +# CONFIG_CDX_BUS is not set +CONFIG_DPLL=y +# end of Device Drivers + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_VALIDATE_FS_PARSER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_STACK=y +CONFIG_BUFFER_HEAD=y +CONFIG_LEGACY_DIRECT_IO=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_EXT4_KUNIT_TESTS=m +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +CONFIG_JFS_STATISTICS=y +CONFIG_XFS_FS=m +CONFIG_XFS_SUPPORT_V4=y +CONFIG_XFS_SUPPORT_ASCII_CI=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +# CONFIG_XFS_ONLINE_SCRUB is not set +# CONFIG_XFS_WARN is not set +# CONFIG_XFS_DEBUG is not set +CONFIG_GFS2_FS=m +CONFIG_GFS2_FS_LOCKING_DLM=y +CONFIG_OCFS2_FS=m +CONFIG_OCFS2_FS_O2CB=m +CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +CONFIG_OCFS2_FS_STATS=y +CONFIG_OCFS2_DEBUG_MASKLOG=y +# CONFIG_OCFS2_DEBUG_FS is not set +CONFIG_BTRFS_FS=y +CONFIG_BTRFS_FS_POSIX_ACL=y +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set +# CONFIG_BTRFS_ASSERT is not set +# CONFIG_BTRFS_FS_REF_VERIFY is not set +CONFIG_NILFS2_FS=m +CONFIG_F2FS_FS=y +CONFIG_F2FS_STAT_FS=y +CONFIG_F2FS_FS_XATTR=y +CONFIG_F2FS_FS_POSIX_ACL=y +CONFIG_F2FS_FS_SECURITY=y +CONFIG_F2FS_CHECK_FS=y +# CONFIG_F2FS_FAULT_INJECTION is not set +CONFIG_F2FS_FS_COMPRESSION=y +CONFIG_F2FS_FS_LZO=y +CONFIG_F2FS_FS_LZORLE=y +CONFIG_F2FS_FS_LZ4=y +CONFIG_F2FS_FS_LZ4HC=y +CONFIG_F2FS_FS_ZSTD=y +CONFIG_F2FS_IOSTAT=y +# CONFIG_F2FS_UNFAIR_RWSEM is not set +CONFIG_BCACHEFS_FS=m +CONFIG_BCACHEFS_QUOTA=y +CONFIG_BCACHEFS_ERASURE_CODING=y +CONFIG_BCACHEFS_POSIX_ACL=y +# CONFIG_BCACHEFS_DEBUG is not set +# CONFIG_BCACHEFS_TESTS is not set +# CONFIG_BCACHEFS_LOCK_TIME_STATS is not set +# CONFIG_BCACHEFS_NO_LATENCY_ACCT is not set +CONFIG_BCACHEFS_SIX_OPTIMISTIC_SPIN=y +# CONFIG_MEAN_AND_VARIANCE_UNIT_TEST is not set +CONFIG_ZONEFS_FS=m +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +CONFIG_EXPORTFS_BLOCK_OPS=y +CONFIG_FILE_LOCKING=y +CONFIG_FS_ENCRYPTION=y +CONFIG_FS_ENCRYPTION_ALGS=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_FANOTIFY=y +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=m +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_QUOTACTL=y +CONFIG_AUTOFS_FS=m +CONFIG_FUSE_FS=y +CONFIG_CUSE=m +CONFIG_VIRTIO_FS=m +CONFIG_OVERLAY_FS=y +# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set +CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y +# CONFIG_OVERLAY_FS_INDEX is not set +CONFIG_OVERLAY_FS_XINO_AUTO=y +# CONFIG_OVERLAY_FS_METACOPY is not set +# CONFIG_OVERLAY_FS_DEBUG is not set + +# +# Caches +# +CONFIG_NETFS_SUPPORT=m +CONFIG_NETFS_STATS=y +CONFIG_FSCACHE=y +CONFIG_FSCACHE_STATS=y +# CONFIG_FSCACHE_DEBUG is not set +CONFIG_CACHEFILES=m +# CONFIG_CACHEFILES_DEBUG is not set +# CONFIG_CACHEFILES_ERROR_INJECTION is not set +# CONFIG_CACHEFILES_ONDEMAND is not set +# end of Caches + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +# end of CD-ROM/DVD Filesystems + +# +# DOS/FAT/EXFAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=936 +CONFIG_FAT_DEFAULT_IOCHARSET="utf8" +# CONFIG_FAT_DEFAULT_UTF8 is not set +# CONFIG_FAT_KUNIT_TEST is not set +CONFIG_EXFAT_FS=y +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y +CONFIG_NTFS3_FS=y +# CONFIG_NTFS3_64BIT_CLUSTER is not set +CONFIG_NTFS3_LZX_XPRESS=y +CONFIG_NTFS3_FS_POSIX_ACL=y +# end of DOS/FAT/EXFAT/NT Filesystems + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_PROC_CHILDREN=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_TMPFS_INODE64 is not set +# CONFIG_TMPFS_QUOTA is not set +CONFIG_ARCH_SUPPORTS_HUGETLBFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_ARCH_HAS_GIGANTIC_PAGE=y +CONFIG_CONFIGFS_FS=y +CONFIG_EFIVAR_FS=y +# end of Pseudo filesystems + +CONFIG_MISC_FILESYSTEMS=y +CONFIG_ORANGEFS_FS=m +CONFIG_ADFS_FS=m +# CONFIG_ADFS_FS_RW is not set +CONFIG_AFFS_FS=m +CONFIG_ECRYPT_FS=y +CONFIG_ECRYPT_FS_MESSAGING=y +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_LZO=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +# CONFIG_JFFS2_CMODE_PRIORITY is not set +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_CMODE_FAVOURLZO=y +CONFIG_UBIFS_FS=m +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UBIFS_FS_ZSTD=y +# CONFIG_UBIFS_ATIME_SUPPORT is not set +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_SECURITY=y +# CONFIG_UBIFS_FS_AUTHENTICATION is not set +CONFIG_CRAMFS=m +CONFIG_CRAMFS_BLOCKDEV=y +CONFIG_CRAMFS_MTD=y +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_CHOICE_DECOMP_BY_MOUNT is not set +CONFIG_SQUASHFS_COMPILE_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU is not set +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_ZLIB=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZSTD=y +CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y +CONFIG_SQUASHFS_EMBEDDED=y +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +CONFIG_VXFS_FS=m +CONFIG_MINIX_FS=m +CONFIG_OMFS_FS=m +CONFIG_HPFS_FS=m +CONFIG_QNX4FS_FS=m +CONFIG_QNX6FS_FS=m +# CONFIG_QNX6FS_DEBUG is not set +CONFIG_ROMFS_FS=m +CONFIG_ROMFS_BACKED_BY_BLOCK=y +# CONFIG_ROMFS_BACKED_BY_MTD is not set +# CONFIG_ROMFS_BACKED_BY_BOTH is not set +CONFIG_ROMFS_ON_BLOCK=y +CONFIG_PSTORE=y +CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 +CONFIG_PSTORE_COMPRESS=y +# CONFIG_PSTORE_CONSOLE is not set +# CONFIG_PSTORE_PMSG is not set +CONFIG_PSTORE_RAM=m +CONFIG_PSTORE_ZONE=m +CONFIG_PSTORE_BLK=m +CONFIG_PSTORE_BLK_BLKDEV="" +CONFIG_PSTORE_BLK_KMSG_SIZE=64 +CONFIG_PSTORE_BLK_MAX_REASON=2 +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +CONFIG_UFS_FS_WRITE=y +# CONFIG_UFS_DEBUG is not set +CONFIG_EROFS_FS=m +# CONFIG_EROFS_FS_DEBUG is not set +CONFIG_EROFS_FS_XATTR=y +CONFIG_EROFS_FS_POSIX_ACL=y +CONFIG_EROFS_FS_SECURITY=y +# CONFIG_EROFS_FS_ZIP is not set +# CONFIG_EROFS_FS_ONDEMAND is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V2=m +CONFIG_NFS_V3=m +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=m +CONFIG_NFS_SWAP=y +CONFIG_NFS_V4_1=y +CONFIG_NFS_V4_2=y +CONFIG_PNFS_FILE_LAYOUT=m +CONFIG_PNFS_BLOCK=m +CONFIG_PNFS_FLEXFILE_LAYOUT=m +CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" +CONFIG_NFS_V4_1_MIGRATION=y +CONFIG_NFS_V4_SECURITY_LABEL=y +CONFIG_NFS_FSCACHE=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +CONFIG_NFS_DEBUG=y +CONFIG_NFS_DISABLE_UDP_SUPPORT=y +CONFIG_NFS_V4_2_READ_PLUS=y +CONFIG_NFSD=m +# CONFIG_NFSD_V2 is not set +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_PNFS=y +CONFIG_NFSD_BLOCKLAYOUT=y +CONFIG_NFSD_SCSILAYOUT=y +CONFIG_NFSD_FLEXFILELAYOUT=y +# CONFIG_NFSD_V4_2_INTER_SSC is not set +CONFIG_NFSD_V4_SECURITY_LABEL=y +# CONFIG_NFSD_LEGACY_CLIENT_TRACKING is not set +CONFIG_GRACE_PERIOD=m +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_NFS_V4_2_SSC_HELPER=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_SUNRPC_BACKCHANNEL=y +CONFIG_SUNRPC_SWAP=y +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1=y +# CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA is not set +# CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2 is not set +# CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST is not set +CONFIG_SUNRPC_DEBUG=y +CONFIG_CEPH_FS=m +CONFIG_CEPH_FSCACHE=y +CONFIG_CEPH_FS_POSIX_ACL=y +CONFIG_CEPH_FS_SECURITY_LABEL=y +CONFIG_CIFS=m +CONFIG_CIFS_STATS2=y +CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_CIFS_DEBUG=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_DEBUG_DUMP_KEYS is not set +CONFIG_CIFS_DFS_UPCALL=y +# CONFIG_CIFS_SWN_UPCALL is not set +CONFIG_CIFS_FSCACHE=y +CONFIG_SMB_SERVER=m +CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN=y +CONFIG_SMB_SERVER_KERBEROS5=y +CONFIG_SMBFS=m +CONFIG_CODA_FS=m +CONFIG_AFS_FS=m +# CONFIG_AFS_DEBUG is not set +CONFIG_AFS_FSCACHE=y +# CONFIG_AFS_DEBUG_CURSOR is not set +CONFIG_9P_FS=m +CONFIG_9P_FSCACHE=y +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_9P_FS_SECURITY=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_MAC_ROMAN=m +CONFIG_NLS_MAC_CELTIC=m +CONFIG_NLS_MAC_CENTEURO=m +CONFIG_NLS_MAC_CROATIAN=m +CONFIG_NLS_MAC_CYRILLIC=m +CONFIG_NLS_MAC_GAELIC=m +CONFIG_NLS_MAC_GREEK=m +CONFIG_NLS_MAC_ICELAND=m +CONFIG_NLS_MAC_INUIT=m +CONFIG_NLS_MAC_ROMANIAN=m +CONFIG_NLS_MAC_TURKISH=m +CONFIG_NLS_UTF8=m +CONFIG_NLS_UCS2_UTILS=m +CONFIG_DLM=m +# CONFIG_DLM_DEBUG is not set +CONFIG_UNICODE=y +# CONFIG_UNICODE_NORMALIZATION_SELFTEST is not set +CONFIG_IO_WQ=y +# end of File systems + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_REQUEST_CACHE=y +CONFIG_PERSISTENT_KEYRINGS=y +CONFIG_TRUSTED_KEYS=y +CONFIG_TRUSTED_KEYS_TPM=y +CONFIG_TRUSTED_KEYS_TEE=y +CONFIG_ENCRYPTED_KEYS=y +# CONFIG_USER_DECRYPTED_DATA is not set +CONFIG_KEY_DH_OPERATIONS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SECURITY=y +CONFIG_SECURITYFS=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_NETWORK_XFRM=y +CONFIG_SECURITY_PATH=y +CONFIG_LSM_MMAP_MIN_ADDR=0 +CONFIG_HARDENED_USERCOPY=y +CONFIG_FORTIFY_SOURCE=y +# CONFIG_STATIC_USERMODEHELPER is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS=9 +CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE=256 +# CONFIG_SECURITY_SELINUX_DEBUG is not set +CONFIG_SECURITY_SMACK=y +# CONFIG_SECURITY_SMACK_BRINGUP is not set +CONFIG_SECURITY_SMACK_NETFILTER=y +CONFIG_SECURITY_SMACK_APPEND_SIGNALS=y +CONFIG_SECURITY_TOMOYO=y +CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY=2048 +CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG=1024 +# CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER is not set +CONFIG_SECURITY_TOMOYO_POLICY_LOADER="/sbin/tomoyo-init" +CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER="/sbin/init" +# CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING is not set +CONFIG_SECURITY_APPARMOR=y +# CONFIG_SECURITY_APPARMOR_DEBUG is not set +CONFIG_SECURITY_APPARMOR_INTROSPECT_POLICY=y +CONFIG_SECURITY_APPARMOR_HASH=y +CONFIG_SECURITY_APPARMOR_HASH_DEFAULT=y +CONFIG_SECURITY_APPARMOR_EXPORT_BINARY=y +CONFIG_SECURITY_APPARMOR_PARANOID_LOAD=y +# CONFIG_SECURITY_APPARMOR_KUNIT_TEST is not set +# CONFIG_SECURITY_LOADPIN is not set +CONFIG_SECURITY_YAMA=y +CONFIG_SECURITY_SAFESETID=y +# CONFIG_SECURITY_LOCKDOWN_LSM is not set +# CONFIG_SECURITY_LANDLOCK is not set +CONFIG_INTEGRITY=y +CONFIG_INTEGRITY_SIGNATURE=y +CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y +CONFIG_INTEGRITY_TRUSTED_KEYRING=y +CONFIG_INTEGRITY_PLATFORM_KEYRING=y +# CONFIG_INTEGRITY_MACHINE_KEYRING is not set +CONFIG_LOAD_UEFI_KEYS=y +CONFIG_INTEGRITY_AUDIT=y +CONFIG_IMA=y +# CONFIG_IMA_KEXEC is not set +CONFIG_IMA_MEASURE_PCR_IDX=10 +CONFIG_IMA_LSM_RULES=y +CONFIG_IMA_NG_TEMPLATE=y +# CONFIG_IMA_SIG_TEMPLATE is not set +CONFIG_IMA_DEFAULT_TEMPLATE="ima-ng" +CONFIG_IMA_DEFAULT_HASH_SHA1=y +# CONFIG_IMA_DEFAULT_HASH_SHA256 is not set +# CONFIG_IMA_DEFAULT_HASH_SHA512 is not set +CONFIG_IMA_DEFAULT_HASH="sha1" +# CONFIG_IMA_WRITE_POLICY is not set +# CONFIG_IMA_READ_POLICY is not set +CONFIG_IMA_APPRAISE=y +# CONFIG_IMA_ARCH_POLICY is not set +# CONFIG_IMA_APPRAISE_BUILD_POLICY is not set +CONFIG_IMA_APPRAISE_BOOTPARAM=y +# CONFIG_IMA_APPRAISE_MODSIG is not set +# CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY is not set +# CONFIG_IMA_BLACKLIST_KEYRING is not set +# CONFIG_IMA_LOAD_X509 is not set +CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS=y +CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS=y +# CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT is not set +# CONFIG_IMA_DISABLE_HTABLE is not set +CONFIG_EVM=y +CONFIG_EVM_ATTR_FSUUID=y +CONFIG_EVM_EXTRA_SMACK_XATTRS=y +# CONFIG_EVM_ADD_XATTRS is not set +# CONFIG_EVM_LOAD_X509 is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_APPARMOR=y +# CONFIG_DEFAULT_SECURITY_DAC is not set +CONFIG_LSM="lockdown,yama,integrity,apparmor" + +# +# Kernel hardening options +# + +# +# Memory initialization +# +CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y +CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO_BARE=y +CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y +CONFIG_INIT_STACK_NONE=y +# CONFIG_INIT_STACK_ALL_PATTERN is not set +# CONFIG_INIT_STACK_ALL_ZERO is not set +CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y +# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set +CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y +# CONFIG_ZERO_CALL_USED_REGS is not set +# end of Memory initialization + +# +# Hardening of kernel data structures +# +# CONFIG_LIST_HARDENED is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# end of Hardening of kernel data structures + +CONFIG_RANDSTRUCT_NONE=y +# end of Kernel hardening options +# end of Security options + +CONFIG_XOR_BLOCKS=y +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y +CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_SIG=y +CONFIG_CRYPTO_SIG2=y +CONFIG_CRYPTO_SKCIPHER=y +CONFIG_CRYPTO_SKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_AKCIPHER=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_KPP=y +CONFIG_CRYPTO_ACOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_USER=m +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +CONFIG_CRYPTO_PCRYPT=m +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_ENGINE=m +# end of Crypto core or helper + +# +# Public-key cryptography +# +CONFIG_CRYPTO_RSA=y +CONFIG_CRYPTO_DH=y +CONFIG_CRYPTO_DH_RFC7919_GROUPS=y +CONFIG_CRYPTO_ECC=m +CONFIG_CRYPTO_ECDH=m +CONFIG_CRYPTO_ECDSA=m +CONFIG_CRYPTO_ECRDSA=m +# CONFIG_CRYPTO_SM2 is not set +CONFIG_CRYPTO_CURVE25519=m +# end of Public-key cryptography + +# +# Block ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_TI=m +CONFIG_CRYPTO_ANUBIS=m +# CONFIG_CRYPTO_ARIA is not set +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_BLOWFISH_COMMON=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST_COMMON=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_SM4=m +CONFIG_CRYPTO_SM4_GENERIC=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m +# end of Block ciphers + +# +# Length-preserving ciphers and modes +# +CONFIG_CRYPTO_ADIANTUM=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_CHACHA20=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_HCTR2 is not set +CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=y +CONFIG_CRYPTO_NHPOLY1305=y +# end of Length-preserving ciphers and modes + +# +# AEAD (authenticated encryption with associated data) ciphers +# +CONFIG_CRYPTO_AEGIS128=m +CONFIG_CRYPTO_AEGIS128_SIMD=y +CONFIG_CRYPTO_CHACHA20POLY1305=m +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_GENIV=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_ECHAINIV=m +CONFIG_CRYPTO_ESSIV=m +# end of AEAD (authenticated encryption with associated data) ciphers + +# +# Hashes, digests, and MACs +# +CONFIG_CRYPTO_BLAKE2B=y +CONFIG_CRYPTO_CMAC=m +CONFIG_CRYPTO_GHASH=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_POLY1305=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_SHA3=y +CONFIG_CRYPTO_SM3=m +CONFIG_CRYPTO_SM3_GENERIC=m +CONFIG_CRYPTO_STREEBOG=m +CONFIG_CRYPTO_VMAC=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_XXHASH=y +# end of Hashes, digests, and MACs + +# +# CRCs (cyclic redundancy checks) +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_CRC64_ROCKSOFT=y +# end of CRCs (cyclic redundancy checks) + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_842=m +CONFIG_CRYPTO_LZ4=m +CONFIG_CRYPTO_LZ4HC=m +CONFIG_CRYPTO_ZSTD=y +# end of Compression + +# +# Random number generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64 +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32 +CONFIG_CRYPTO_JITTERENTROPY_OSR=1 +CONFIG_CRYPTO_KDF800108_CTR=y +# end of Random number generation + +# +# Userspace interface +# +CONFIG_CRYPTO_USER_API=m +CONFIG_CRYPTO_USER_API_HASH=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +CONFIG_CRYPTO_USER_API_RNG=m +# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set +CONFIG_CRYPTO_USER_API_AEAD=m +CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE=y +# CONFIG_CRYPTO_STATS is not set +# end of Userspace interface + +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_NHPOLY1305_NEON=y +CONFIG_CRYPTO_CHACHA20_NEON=y + +# +# Accelerated Cryptographic Algorithms for CPU (arm64) +# +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_POLY1305_NEON=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA256_ARM64=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_SHA512_ARM64=y +CONFIG_CRYPTO_SHA512_ARM64_CE=m +CONFIG_CRYPTO_SHA3_ARM64=m +# CONFIG_CRYPTO_SM3_NEON is not set +CONFIG_CRYPTO_SM3_ARM64_CE=m +# CONFIG_CRYPTO_POLYVAL_ARM64_CE is not set +CONFIG_CRYPTO_AES_ARM64=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_CRYPTO_AES_ARM64_BS=y +CONFIG_CRYPTO_SM4_ARM64_CE=m +# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set +# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +# CONFIG_CRYPTO_SM4_ARM64_CE_CCM is not set +# CONFIG_CRYPTO_SM4_ARM64_CE_GCM is not set +CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=m +# end of Accelerated Cryptographic Algorithms for CPU (arm64) + +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_ATMEL_I2C=m +CONFIG_CRYPTO_DEV_ATMEL_ECC=m +CONFIG_CRYPTO_DEV_ATMEL_SHA204A=m +# CONFIG_CRYPTO_DEV_CCP is not set +CONFIG_CRYPTO_DEV_NITROX=m +CONFIG_CRYPTO_DEV_NITROX_CNN55XX=m +# CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set +# CONFIG_CRYPTO_DEV_QAT_C62X is not set +# CONFIG_CRYPTO_DEV_QAT_4XXX is not set +# CONFIG_CRYPTO_DEV_QAT_420XX is not set +# CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set +# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set +CONFIG_CRYPTO_DEV_CAVIUM_ZIP=m +CONFIG_CRYPTO_DEV_ROCKCHIP=m +# CONFIG_CRYPTO_DEV_ROCKCHIP_DEBUG is not set +CONFIG_CRYPTO_DEV_ROCKCHIP2=m +# CONFIG_CRYPTO_DEV_ROCKCHIP2_DEBUG is not set +CONFIG_CRYPTO_DEV_VIRTIO=m +CONFIG_CRYPTO_DEV_SAFEXCEL=m +CONFIG_CRYPTO_DEV_CCREE=m +CONFIG_CRYPTO_DEV_HISI_SEC=m +CONFIG_CRYPTO_DEV_HISI_SEC2=m +CONFIG_CRYPTO_DEV_HISI_QM=m +CONFIG_CRYPTO_DEV_HISI_ZIP=m +CONFIG_CRYPTO_DEV_HISI_HPRE=m +CONFIG_CRYPTO_DEV_HISI_TRNG=m +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_X509_CERTIFICATE_PARSER=y +# CONFIG_PKCS8_PRIVATE_KEY_PARSER is not set +CONFIG_PKCS7_MESSAGE_PARSER=y +CONFIG_PKCS7_TEST_KEY=m +CONFIG_SIGNED_PE_FILE_VERIFICATION=y +# CONFIG_FIPS_SIGNATURE_SELFTEST is not set + +# +# Certificates for signature checking +# +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +CONFIG_SYSTEM_EXTRA_CERTIFICATE=y +CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE=4096 +CONFIG_SECONDARY_TRUSTED_KEYRING=y +# CONFIG_SECONDARY_TRUSTED_KEYRING_SIGNED_BY_BUILTIN is not set +CONFIG_SYSTEM_BLACKLIST_KEYRING=y +CONFIG_SYSTEM_BLACKLIST_HASH_LIST="" +# CONFIG_SYSTEM_REVOCATION_LIST is not set +# CONFIG_SYSTEM_BLACKLIST_AUTH_UPDATE is not set +# end of Certificates for signature checking + +CONFIG_BINARY_PRINTF=y + +# +# Library routines +# +CONFIG_RAID6_PQ=y +CONFIG_RAID6_PQ_BENCHMARK=y +CONFIG_LINEAR_RANGES=y +CONFIG_PACKING=y +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_CORDIC=m +CONFIG_PRIME_NUMBERS=m +CONFIG_RATIONAL=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_ARCH_HAS_FAST_MULTIPLIER=y +CONFIG_ARCH_USE_SYM_ANNOTATIONS=y +CONFIG_INDIRECT_PIO=y +# CONFIG_TRACE_MMIO_ACCESS is not set + +# +# Crypto library routines +# +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LIB_AES=y +CONFIG_CRYPTO_LIB_ARC4=m +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA=y +CONFIG_CRYPTO_LIB_CHACHA_GENERIC=y +CONFIG_CRYPTO_LIB_CHACHA=m +CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=m +CONFIG_CRYPTO_LIB_CURVE25519=m +CONFIG_CRYPTO_LIB_DES=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=9 +CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305=y +CONFIG_CRYPTO_LIB_POLY1305_GENERIC=y +CONFIG_CRYPTO_LIB_POLY1305=m +CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +# end of Crypto library routines + +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC_T10DIF=y +CONFIG_CRC64_ROCKSOFT=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC64=y +CONFIG_CRC4=m +CONFIG_CRC7=y +CONFIG_LIBCRC32C=y +CONFIG_CRC8=m +CONFIG_XXHASH=y +CONFIG_AUDIT_GENERIC=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_AUDIT_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_842_COMPRESS=m +CONFIG_842_DECOMPRESS=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_LZ4_COMPRESS=y +CONFIG_LZ4HC_COMPRESS=y +CONFIG_LZ4_DECOMPRESS=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y +CONFIG_XZ_DEC=y +CONFIG_XZ_DEC_X86=y +CONFIG_XZ_DEC_POWERPC=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_SPARC=y +CONFIG_XZ_DEC_MICROLZMA=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_XZ_DEC_TEST=m +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_XZ=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DECOMPRESS_LZ4=y +CONFIG_DECOMPRESS_ZSTD=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_REED_SOLOMON_ENC16=y +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_BTREE=y +CONFIG_INTERVAL_TREE=y +CONFIG_XARRAY_MULTI=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_CLOSURES=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_DMA_OPS=y +CONFIG_NEED_SG_DMA_FLAGS=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_DMA_DECLARE_COHERENT=y +CONFIG_ARCH_HAS_SETUP_DMA_OPS=y +CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS=y +CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y +CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y +CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y +CONFIG_SWIOTLB=y +# CONFIG_SWIOTLB_DYNAMIC is not set +CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_RESTRICTED_POOL=y +CONFIG_DMA_NONCOHERENT_MMAP=y +CONFIG_DMA_COHERENT_POOL=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_CMA=y +# CONFIG_DMA_NUMA_CMA is not set + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=384 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_DMA_MAP_BENCHMARK is not set +CONFIG_SGL_ALLOC=y +CONFIG_CHECK_SIGNATURE=y +# CONFIG_FORCE_NR_CPUS is not set +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_GLOB=y +CONFIG_GLOB_SELFTEST=m +CONFIG_NLATTR=y +CONFIG_LRU_CACHE=m +CONFIG_CLZ_TAB=y +CONFIG_IRQ_POLL=y +CONFIG_MPILIB=y +CONFIG_SIGNATURE=y +CONFIG_DIMLIB=y +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_UCS2_STRING=y +CONFIG_HAVE_GENERIC_VDSO=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_VDSO_TIME_NS=y +CONFIG_FONT_SUPPORT=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +CONFIG_FONT_ACORN_8x8=y +# CONFIG_FONT_MINI_4x6 is not set +CONFIG_FONT_6x10=y +# CONFIG_FONT_10x18 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +CONFIG_FONT_TER16x32=y +# CONFIG_FONT_6x8 is not set +CONFIG_SG_SPLIT=y +CONFIG_SG_POOL=y +CONFIG_MEMREGION=y +CONFIG_ARCH_STACKWALK=y +CONFIG_STACKDEPOT=y +CONFIG_STACKDEPOT_MAX_FRAMES=64 +CONFIG_SBITMAP=y +# CONFIG_LWQ_TEST is not set +# end of Library routines + +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_ASN1_ENCODER=y +CONFIG_POLYNOMIAL=m +CONFIG_FIRMWARE_TABLE=y + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +# CONFIG_PRINTK_CALLER is not set +# CONFIG_STACKTRACE_BUILD_ID is not set +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_CONSOLE_LOGLEVEL_QUIET=4 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DYNAMIC_DEBUG_CORE=y +CONFIG_SYMBOLIC_ERRNAME=y +CONFIG_DEBUG_BUGVERBOSE=y +# end of printk and dmesg options + +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_MISC=y + +# +# Compile-time checks and compiler options +# +CONFIG_AS_HAS_NON_CONST_ULEB128=y +CONFIG_DEBUG_INFO_NONE=y +# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_DEBUG_INFO_DWARF5 is not set +CONFIG_FRAME_WARN=2048 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_HEADERS_INSTALL is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_VMLINUX_MAP is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# end of Compile-time checks and compiler options + +# +# Generic Kernel Debugging Instruments +# +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_MAGIC_SYSRQ_SERIAL=y +CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_FS_ALLOW_ALL=y +# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set +# CONFIG_DEBUG_FS_ALLOW_NONE is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y +# CONFIG_UBSAN is not set +CONFIG_HAVE_ARCH_KCSAN=y +CONFIG_HAVE_KCSAN_COMPILER=y +# CONFIG_KCSAN is not set +# end of Generic Kernel Debugging Instruments + +# +# Networking Debugging +# +# CONFIG_NET_DEV_REFCNT_TRACKER is not set +# CONFIG_NET_NS_REFCNT_TRACKER is not set +# CONFIG_DEBUG_NET is not set +# end of Networking Debugging + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_SLUB_DEBUG=y +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_PAGE_TABLE_CHECK is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_PAGE_REF is not set +# CONFIG_DEBUG_RODATA_TEST is not set +CONFIG_ARCH_HAS_DEBUG_WX=y +# CONFIG_DEBUG_WX is not set +CONFIG_GENERIC_PTDUMP=y +# CONFIG_PTDUMP_DEBUGFS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_PER_VMA_LOCK_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SHRINKER_DEBUG is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_VM_PGTABLE is not set +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +# CONFIG_DEBUG_VIRTUAL is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_HAVE_ARCH_KASAN=y +CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y +CONFIG_HAVE_ARCH_KASAN_HW_TAGS=y +CONFIG_HAVE_ARCH_KASAN_VMALLOC=y +CONFIG_CC_HAS_KASAN_GENERIC=y +CONFIG_CC_HAS_KASAN_SW_TAGS=y +CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y +# CONFIG_KASAN is not set +CONFIG_HAVE_ARCH_KFENCE=y +# CONFIG_KFENCE is not set +# end of Memory Debugging + +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Oops, Lockups and Hangs +# +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SOFTLOCKUP_DETECTOR is not set +CONFIG_HAVE_HARDLOCKUP_DETECTOR_BUDDY=y +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set +# CONFIG_WQ_CPU_INTENSIVE_REPORT is not set +CONFIG_TEST_LOCKUP=m +# end of Debug Oops, Lockups and Hangs + +# +# Scheduler Debugging +# +CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_INFO=y +# CONFIG_SCHEDSTATS is not set +# end of Scheduler Debugging + +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_DEBUG_PREEMPT is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +CONFIG_LOCK_DEBUGGING_SUPPORT=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_WW_MUTEX_SELFTEST is not set +# CONFIG_SCF_TORTURE_TEST is not set +# CONFIG_CSD_LOCK_WAIT_DEBUG is not set +# end of Lock Debugging (spinlocks, mutexes, etc...) + +# CONFIG_DEBUG_IRQFLAGS is not set +CONFIG_STACKTRACE=y +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +# CONFIG_DEBUG_KOBJECT is not set + +# +# Debug kernel data structures +# +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PLIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CLOSURES is not set +# CONFIG_DEBUG_MAPLE_TREE is not set +# end of Debug kernel data structures + +# +# RCU Debugging +# +# CONFIG_RCU_SCALE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_REF_SCALE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0 +# CONFIG_RCU_CPU_STALL_CPUTIME is not set +CONFIG_RCU_TRACE=y +# CONFIG_RCU_EQS_DEBUG is not set +# end of RCU Debugging + +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_DEBUG_CGROUP_REF is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_RETVAL=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACE_CLOCK=y +CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_TRACING=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_BOOTTIME_TRACING is not set +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_HWLAT_TRACER is not set +# CONFIG_OSNOISE_TRACER is not set +# CONFIG_TIMERLAT_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_FTRACE_SYSCALLS is not set +# CONFIG_TRACER_SNAPSHOT is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_KPROBE_EVENTS=y +CONFIG_UPROBE_EVENTS=y +CONFIG_BPF_EVENTS=y +CONFIG_DYNAMIC_EVENTS=y +CONFIG_PROBE_EVENTS=y +# CONFIG_BPF_KPROBE_OVERRIDE is not set +# CONFIG_SYNTH_EVENTS is not set +# CONFIG_USER_EVENTS is not set +# CONFIG_HIST_TRIGGERS is not set +# CONFIG_TRACE_EVENT_INJECT is not set +# CONFIG_TRACEPOINT_BENCHMARK is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_TRACE_EVAL_MAP_FILE is not set +# CONFIG_RING_BUFFER_STARTUP_TEST is not set +# CONFIG_RING_BUFFER_VALIDATE_TIME_DELTAS is not set +# CONFIG_PREEMPTIRQ_DELAY_TEST is not set +# CONFIG_KPROBE_EVENT_GEN_TEST is not set +# CONFIG_RV is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_SAMPLE_FTRACE_DIRECT=y +CONFIG_HAVE_SAMPLE_FTRACE_DIRECT_MULTI=y +CONFIG_STRICT_DEVMEM=y +# CONFIG_IO_STRICT_DEVMEM is not set + +# +# arm64 Debugging +# +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RELOC_TEST is not set +# CONFIG_CORESIGHT is not set +# end of arm64 Debugging + +# +# Kernel Testing and Coverage +# +CONFIG_KUNIT=m +# CONFIG_KUNIT_DEBUGFS is not set +# CONFIG_KUNIT_TEST is not set +# CONFIG_KUNIT_EXAMPLE_TEST is not set +# CONFIG_KUNIT_ALL_TESTS is not set +# CONFIG_KUNIT_DEFAULT_ENABLED is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +CONFIG_FUNCTION_ERROR_INJECTION=y +# CONFIG_FAULT_INJECTION is not set +CONFIG_ARCH_HAS_KCOV=y +CONFIG_CC_HAS_SANCOV_TRACE_PC=y +# CONFIG_KCOV is not set +CONFIG_RUNTIME_TESTING_MENU=y +# CONFIG_TEST_DHRY is not set +# CONFIG_LKDTM is not set +# CONFIG_CPUMASK_KUNIT_TEST is not set +# CONFIG_TEST_LIST_SORT is not set +CONFIG_TEST_MIN_HEAP=m +# CONFIG_TEST_SORT is not set +CONFIG_TEST_DIV64=m +# CONFIG_TEST_IOV_ITER is not set +# CONFIG_KPROBES_SANITY_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_TEST_REF_TRACKER is not set +# CONFIG_RBTREE_TEST is not set +CONFIG_REED_SOLOMON_TEST=m +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +CONFIG_ASYNC_RAID6_TEST=m +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_STRING_SELFTEST is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_PRINTF is not set +CONFIG_TEST_SCANF=m +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_UUID is not set +CONFIG_TEST_XARRAY=m +# CONFIG_TEST_MAPLE_TREE is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_IDA is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_BITOPS is not set +CONFIG_TEST_VMALLOC=m +# CONFIG_TEST_USER_COPY is not set +CONFIG_TEST_BPF=m +CONFIG_TEST_BLACKHOLE_DEV=m +# CONFIG_FIND_BIT_BENCHMARK is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_SYSCTL is not set +# CONFIG_BITFIELD_KUNIT is not set +# CONFIG_CHECKSUM_KUNIT is not set +# CONFIG_HASH_KUNIT_TEST is not set +CONFIG_RESOURCE_KUNIT_TEST=m +# CONFIG_SYSCTL_KUNIT_TEST is not set +# CONFIG_LIST_KUNIT_TEST is not set +# CONFIG_HASHTABLE_KUNIT_TEST is not set +# CONFIG_LINEAR_RANGES_TEST is not set +CONFIG_CMDLINE_KUNIT_TEST=m +# CONFIG_BITS_TEST is not set +CONFIG_SLUB_KUNIT_TEST=m +CONFIG_RATIONAL_KUNIT_TEST=m +CONFIG_MEMCPY_KUNIT_TEST=m +CONFIG_MEMCPY_SLOW_KUNIT_TEST=y +# CONFIG_IS_SIGNED_TYPE_KUNIT_TEST is not set +# CONFIG_OVERFLOW_KUNIT_TEST is not set +# CONFIG_STACKINIT_KUNIT_TEST is not set +# CONFIG_FORTIFY_KUNIT_TEST is not set +# CONFIG_STRCAT_KUNIT_TEST is not set +# CONFIG_STRSCPY_KUNIT_TEST is not set +# CONFIG_SIPHASH_KUNIT_TEST is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_DYNAMIC_DEBUG is not set +# CONFIG_TEST_KMOD is not set +CONFIG_TEST_MEMCAT_P=m +# CONFIG_TEST_MEMINIT is not set +# CONFIG_TEST_FREE_PAGES is not set +# CONFIG_TEST_OBJPOOL is not set +CONFIG_ARCH_USE_MEMTEST=y +CONFIG_MEMTEST=y +# end of Kernel Testing and Coverage + +# +# Rust hacking +# +# end of Rust hacking +# end of Kernel hacking diff --git a/config/sources/families/rockchip-rk3588.conf b/config/sources/families/rockchip-rk3588.conf index 0c6436e7c926..7b05e7208712 100644 --- a/config/sources/families/rockchip-rk3588.conf +++ b/config/sources/families/rockchip-rk3588.conf @@ -39,7 +39,16 @@ case $BRANCH in LINUXFAMILY=rk35xx ;; + current) + # Branch based on a stable kernel release (will stay on the next LTS kernel release once released, 6.12? LTS) + LINUXFAMILY=rockchip-rk3588 + KERNEL_MAJOR_MINOR="6.8" # Major and minor versions of this kernel. + LINUXCONFIG="linux-rockchip-rk3588-${KERNEL_MAJOR_MINOR}" # Attention: not -${BRANCH} (edge/current/legacy), but -${KERNEL_MAJOR_MINOR} thus 6.8 / 6.10 etc + # No need to set KERNELPATCHDIR, since default is: KERNELPATCHDIR='archive/rockchip-rk3588-6.8' + ;; + edge) + # Branch based on the latest kernel release including RC releases, to benefit from the latest RK3588 mainline advancements. Might be unstable! LINUXFAMILY=rockchip-rk3588 LINUXCONFIG='linux-rockchip-rk3588-'$BRANCH KERNEL_MAJOR_MINOR="6.10" # Major and minor versions of this kernel. @@ -53,7 +62,7 @@ case $BRANCH in KERNEL_MAJOR_MINOR="6.9" # Major and minor versions of this kernel. KERNELPATCHDIR='rockchip-rk3588-collabora' KERNELSOURCE='https://gitlab.collabora.com/hardware-enablement/rockchip-3588/linux.git' - KERNELBRANCH='branch:rk3588-v6.9' # Rolling kernel branch, will be rebased + KERNELBRANCH='branch:rk3588-v6.9' # Rolling kernel branch, will be rebased KERNEL_DRIVERS_SKIP+=(driver_rtw88) # This is a custom kernel, while the rtw88 driver patching expects pure mainline ;; esac diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0000.patching_config.yaml b/patch/kernel/archive/rockchip-rk3588-6.8/0000.patching_config.yaml new file mode 100644 index 000000000000..742379d54b3b --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0000.patching_config.yaml @@ -0,0 +1,46 @@ +config: # This is file 'patch/kernel/rockchip-rk3588-edge/0000.patching_config.yaml' + + # PATCH NUMBERING INFO + # + # Patch numbers in this folder are sorted by category: + # + # 000* for general patches + # 01** for GPU/HDMI related patches + # 08** for wireless patches + # 1*** for board patches + # 101* for Rock-5B, 1012* for Rock-5A and so on + + # Just some info stuff; not used by the patching scripts + name: rockchip-rk3588-edge + kind: kernel + type: mainline # or: vendor + branch: linux-6.8.y + last-known-good-tag: v6.8.3 + maintainers: + - { github: rpardini, name: Ricardo Pardini, email: ricardo@pardini.net, armbian-forum: rpardini } + + # .dts files in these directories will be copied as-is to the build tree; later ones overwrite earlier ones. + # This is meant to provide a way to "add a board DTS" without having to null-patch them in. + dts-directories: + - { source: "dt", target: "arch/arm64/boot/dts/rockchip" } + + # every file in these directories will be copied as-is to the build tree; later ones overwrite earlier ones + # This is meant as a way to have overlays, bare, in a directory, without having to null-patch them in. + # @TODO need a solution to auto-Makefile the overlays as well + overlay-directories: + - { source: "overlay", target: "arch/arm64/boot/dts/rockchip/overlay" } + + # the Makefile in each of these directories will be magically patched to include the dts files copied + # or patched-in; overlay subdir will be included "-y" if it exists. + # No more Makefile patching needed, yay! + auto-patch-dt-makefile: + - { directory: "arch/arm64/boot/dts/rockchip", config-var: "CONFIG_ARCH_ROCKCHIP" } + + # configuration for when applying patches to git / auto-rewriting patches (development cycle helpers) + patches-to-git: + do-not-commit-files: + - "MAINTAINERS" # constant churn, drop them. sorry. + - "Documentation/devicetree/bindings/arm/rockchip.yaml" # constant churn, conflicts on every bump, drop it. sorry. + do-not-commit-regexes: # Python-style regexes + - "^arch/([a-zA-Z0-9]+)/boot/dts/([a-zA-Z0-9]+)/Makefile$" # ignore DT Makefile patches, we've an auto-patcher now + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0001-general-add-overlay-support.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0001-general-add-overlay-support.patch new file mode 100644 index 000000000000..450fc85b5500 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0001-general-add-overlay-support.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: zador-blood-stained +Date: Sat, 11 Feb 2017 20:32:53 +0300 +Subject: add overlay support + +- rpardini: real overlays are now bare in "overlay" directory and are handled + directly by the patching scripts. No more null-patching of overlays. +- no readme, no fixups +--- + scripts/Makefile.dtbinst | 6 +++- + scripts/Makefile.lib | 17 ++++++++++ + 2 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst +index 111111111111..222222222222 100644 +--- a/scripts/Makefile.dtbinst ++++ b/scripts/Makefile.dtbinst +@@ -18,9 +18,10 @@ include $(srctree)/scripts/Kbuild.include + include $(kbuild-file) + + dtbs := $(addprefix $(dst)/, $(dtb-y) $(if $(CONFIG_OF_ALL_DTBS),$(dtb-))) ++dtbos := $(addprefix $(dst)/, $(dtbo-y)) + subdirs := $(addprefix $(obj)/, $(subdir-y) $(subdir-m)) + +-__dtbs_install: $(dtbs) $(subdirs) ++__dtbs_install: $(dtbs) $(dtbos) $(subdirs) + @: + + quiet_cmd_dtb_install = INSTALL $@ +@@ -32,6 +33,9 @@ $(dst)/%.dtb: $(obj)/%.dtb + $(dst)/%.dtbo: $(obj)/%.dtbo + $(call cmd,dtb_install) + ++$(dst)/%.dtbo: $(obj)/%.dtbo ++ $(call cmd,dtb_install) ++ + PHONY += $(subdirs) + $(subdirs): + $(Q)$(MAKE) $(dtbinst)=$@ dst=$(if $(CONFIG_ARCH_WANT_FLAT_DTB_INSTALL),$(dst),$(patsubst $(obj)/%,$(dst)/%,$@)) +diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib +index 111111111111..222222222222 100644 +--- a/scripts/Makefile.lib ++++ b/scripts/Makefile.lib +@@ -88,6 +88,9 @@ base-dtb-y := $(filter %.dtb, $(call real-search, $(multi-dtb-y), .dtb, -dtbs)) + + always-y += $(dtb-y) + ++# Overlay targets ++extra-y += $(dtbo-y) ++ + # Add subdir path + + ifneq ($(obj),.) +@@ -343,6 +346,9 @@ DTC ?= $(objtree)/scripts/dtc/dtc + DTC_FLAGS += -Wno-interrupt_provider \ + -Wno-unique_unit_address + ++# Overlay support ++DTC_FLAGS += -@ -Wno-unit_address_format -Wno-simple_bus_reg ++ + # Disable noisy checks by default + ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),) + DTC_FLAGS += -Wno-unit_address_vs_reg \ +@@ -421,6 +427,17 @@ $(obj)/%.dtb: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE + $(obj)/%.dtbo: $(src)/%.dtso $(DTC) 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) ++ + dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) + + # Bzip2 +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0005-tools-Makefile-delete-missing-cgroup_clean.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0005-tools-Makefile-delete-missing-cgroup_clean.patch new file mode 100644 index 000000000000..7e8c7050540c --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0005-tools-Makefile-delete-missing-cgroup_clean.patch @@ -0,0 +1,34 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Wed, 24 Jan 2024 18:03:52 +0800 +Subject: tools/Makefile: delete missing cgroup_clean + +--- + tools/Makefile | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/Makefile b/tools/Makefile +index 111111111111..222222222222 100644 +--- a/tools/Makefile ++++ b/tools/Makefile +@@ -169,7 +169,7 @@ acpi_clean: + cpupower_clean: + $(call descend,power/cpupower,clean) + +-cgroup_clean counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean mm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: ++counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean mm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: + $(call descend,$(@:_clean=),clean) + + libapi_clean: +@@ -209,7 +209,7 @@ freefall_clean: + build_clean: + $(call descend,build,clean) + +-clean: acpi_clean cgroup_clean counter_clean cpupower_clean hv_clean firewire_clean \ ++clean: acpi_clean counter_clean cpupower_clean hv_clean firewire_clean \ + perf_clean selftests_clean turbostat_clean bootconfig_clean spi_clean usb_clean virtio_clean \ + mm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ + freefall_clean build_clean libbpf_clean libsubcmd_clean \ +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0010-fix-clk-divisions.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0010-fix-clk-divisions.patch new file mode 100644 index 000000000000..25c4a67db09b --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0010-fix-clk-divisions.patch @@ -0,0 +1,142 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Tue, 24 Oct 2023 16:09:35 +0200 +Subject: math.h: add DIV_ROUND_UP_NO_OVERFLOW + +Add a new DIV_ROUND_UP helper, which cannot overflow when +big numbers are being used. + +Signed-off-by: Sebastian Reichel +--- + include/linux/math.h | 11 ++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/include/linux/math.h b/include/linux/math.h +index 111111111111..222222222222 100644 +--- a/include/linux/math.h ++++ b/include/linux/math.h +@@ -36,6 +36,17 @@ + + #define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP + ++/** ++ * DIV_ROUND_UP_NO_OVERFLOW - divide two numbers and always round up ++ * @n: numerator / dividend ++ * @d: denominator / divisor ++ * ++ * This functions does the same as DIV_ROUND_UP, but internally uses a ++ * division and a modulo operation instead of math tricks. This way it ++ * avoids overflowing when handling big numbers. ++ */ ++#define DIV_ROUND_UP_NO_OVERFLOW(n, d) (((n) / (d)) + !!((n) % (d))) ++ + #define DIV_ROUND_DOWN_ULL(ll, d) \ + ({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; }) + +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Tue, 24 Oct 2023 16:13:50 +0200 +Subject: clk: divider: Fix divisor masking on 64 bit platforms + +The clock framework handles clock rates as "unsigned long", so u32 on +32-bit architectures and u64 on 64-bit architectures. + +The current code casts the dividend to u64 on 32-bit to avoid a +potential overflow. For example DIV_ROUND_UP(3000000000, 1500000000) += (3.0G + 1.5G - 1) / 1.5G = = OVERFLOW / 1.5G, which has been +introduced in commit 9556f9dad8f5 ("clk: divider: handle integer overflow +when dividing large clock rates"). + +On 64 bit platforms this masks the divisor, so that only the lower +32 bit are used. Thus requesting a frequency >= 4.3GHz results +in incorrect values. For example requesting 4300000000 (4.3 GHz) will +effectively request ca. 5 MHz. Requesting clk_round_rate(clk, ULONG_MAX) +is a bit of a special case, since that still returns correct values as +long as the parent clock is below 8.5 GHz. + +Fix this by switching to DIV_ROUND_UP_NO_OVERFLOW, which cannot +overflow. This avoids any requirements on the arguments (except +that divisor should not be 0 obviously). + +Signed-off-by: Sebastian Reichel +--- + drivers/clk/clk-divider.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c +index 111111111111..222222222222 100644 +--- a/drivers/clk/clk-divider.c ++++ b/drivers/clk/clk-divider.c +@@ -220,7 +220,7 @@ static int _div_round_up(const struct clk_div_table *table, + unsigned long parent_rate, unsigned long rate, + unsigned long flags) + { +- int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); ++ int div = DIV_ROUND_UP_NO_OVERFLOW(parent_rate, rate); + + if (flags & CLK_DIVIDER_POWER_OF_TWO) + div = __roundup_pow_of_two(div); +@@ -237,7 +237,7 @@ static int _div_round_closest(const struct clk_div_table *table, + int up, down; + unsigned long up_rate, down_rate; + +- up = DIV_ROUND_UP_ULL((u64)parent_rate, rate); ++ up = DIV_ROUND_UP_NO_OVERFLOW(parent_rate, rate); + down = parent_rate / rate; + + if (flags & CLK_DIVIDER_POWER_OF_TWO) { +@@ -473,7 +473,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate, + { + unsigned int div, value; + +- div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); ++ div = DIV_ROUND_UP_NO_OVERFLOW(parent_rate, rate); + + if (!_is_valid_div(table, div, flags)) + return -EINVAL; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Tue, 24 Oct 2023 18:09:57 +0200 +Subject: clk: composite: replace open-coded abs_diff() + +Replace the open coded abs_diff() with the existing helper function. + +Suggested-by: Andy Shevchenko +Signed-off-by: Sebastian Reichel +--- + drivers/clk/clk-composite.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c +index 111111111111..222222222222 100644 +--- a/drivers/clk/clk-composite.c ++++ b/drivers/clk/clk-composite.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include + + static u8 clk_composite_get_parent(struct clk_hw *hw) +@@ -119,10 +120,7 @@ static int clk_composite_determine_rate(struct clk_hw *hw, + if (ret) + continue; + +- if (req->rate >= tmp_req.rate) +- rate_diff = req->rate - tmp_req.rate; +- else +- rate_diff = tmp_req.rate - req->rate; ++ rate_diff = abs_diff(req->rate, tmp_req.rate); + + if (!rate_diff || !req->best_parent_hw + || best_rate_diff > rate_diff) { +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0011-irqchip-fix-its-timeout-issue.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0011-irqchip-fix-its-timeout-issue.patch new file mode 100644 index 000000000000..0bf20f445e2e --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0011-irqchip-fix-its-timeout-issue.patch @@ -0,0 +1,214 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Fri, 11 Aug 2023 17:56:00 +0300 +Subject: irqchip/irq-gic-v3-its: fix its timeout issue for rk35xx boards + +--- + drivers/irqchip/irq-gic-v3-its.c | 79 +++++++++- + 1 file changed, 72 insertions(+), 7 deletions(-) + +diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c +index 111111111111..222222222222 100644 +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -163,6 +163,7 @@ struct its_device { + struct its_node *its; + struct event_lpi_map event_map; + void *itt; ++ u32 itt_sz; + u32 nr_ites; + u32 device_id; + bool shared; +@@ -2205,6 +2206,9 @@ static void gic_reset_prop_table(void *va) + static struct page *its_allocate_prop_table(gfp_t gfp_flags) + { + struct page *prop_page; ++ ++ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588")) ++ gfp_flags |= GFP_DMA32; + + prop_page = alloc_pages(gfp_flags, get_order(LPI_PROPBASE_SZ)); + if (!prop_page) +@@ -2329,6 +2333,7 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, + u32 alloc_pages, psz; + struct page *page; + void *base; ++ gfp_t gfp_flags; + + psz = baser->psz; + alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz); +@@ -2340,7 +2345,11 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, + order = get_order(GITS_BASER_PAGES_MAX * psz); + } + +- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, order); ++ gfp_flags = GFP_KERNEL | __GFP_ZERO; ++ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588")) ++ gfp_flags |= GFP_DMA32; ++ ++ page = alloc_pages_node(its->numa_node, gfp_flags, order); + if (!page) + return -ENOMEM; + +@@ -2390,6 +2399,15 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, + its_write_baser(its, baser, val); + tmp = baser->val; + ++ if (of_machine_is_compatible("rockchip,rk3568") || ++ of_machine_is_compatible("rockchip,rk3566") || ++ of_machine_is_compatible("rockchip,rk3588")) { ++ if (tmp & GITS_BASER_SHAREABILITY_MASK) ++ tmp &= ~GITS_BASER_SHAREABILITY_MASK; ++ else ++ gic_flush_dcache_to_poc(base, PAGE_ORDER_TO_SIZE(order)); ++ } ++ + if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) { + /* + * Shareability didn't stick. Just use +@@ -2979,7 +2997,9 @@ static int its_alloc_collections(struct its_node *its) + static struct page *its_allocate_pending_table(gfp_t gfp_flags) + { + struct page *pend_page; +- ++ ++ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588")) ++ gfp_flags |= GFP_DMA32; + pend_page = alloc_pages(gfp_flags | __GFP_ZERO, + get_order(LPI_PENDBASE_SZ)); + if (!pend_page) +@@ -3138,6 +3158,11 @@ static void its_cpu_init_lpis(void) + if (!rdists_support_shareable()) + tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK; + ++ if (of_machine_is_compatible("rockchip,rk3568") || ++ of_machine_is_compatible("rockchip,rk3566") || ++ of_machine_is_compatible("rockchip,rk3588")) ++ tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK; ++ + if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) { + if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) { + /* +@@ -3165,6 +3190,11 @@ static void its_cpu_init_lpis(void) + if (!rdists_support_shareable()) + tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK; + ++ if (of_machine_is_compatible("rockchip,rk3568") || ++ of_machine_is_compatible("rockchip,rk3566") || ++ of_machine_is_compatible("rockchip,rk3588")) ++ tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK; ++ + if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) { + /* + * The HW reports non-shareable, we must remove the +@@ -3328,7 +3358,11 @@ static bool its_alloc_table_entry(struct its_node *its, + + /* Allocate memory for 2nd level table */ + if (!table[idx]) { +- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, ++ gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO; ++ ++ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588")) ++ gfp_flags |= GFP_DMA32; ++ page = alloc_pages_node(its->numa_node, gfp_flags, + get_order(baser->psz)); + if (!page) + return false; +@@ -3417,6 +3451,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, + int nr_lpis; + int nr_ites; + int sz; ++ gfp_t gfp_flags; + + if (!its_alloc_device_table(its, dev_id)) + return NULL; +@@ -3432,7 +3467,15 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, + nr_ites = max(2, nvecs); + sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1); + sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; +- itt = kzalloc_node(sz, GFP_KERNEL, its->numa_node); ++ gfp_flags = GFP_KERNEL; ++ ++ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588")) { ++ gfp_flags |= GFP_DMA32; ++ itt = (void *)__get_free_pages(gfp_flags, get_order(sz)); ++ } else { ++ itt = kzalloc_node(sz, gfp_flags, its->numa_node); ++ } ++ + if (alloc_lpis) { + lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis); + if (lpi_map) +@@ -3446,7 +3489,13 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, + + if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) { + kfree(dev); +- kfree(itt); ++ ++ if (of_machine_is_compatible("rockchip,rk3568") || ++ of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588")) ++ free_pages((unsigned long)itt, get_order(sz)); ++ else ++ kfree(itt); ++ + bitmap_free(lpi_map); + kfree(col_map); + return NULL; +@@ -3456,6 +3505,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, + + dev->its = its; + dev->itt = itt; ++ dev->itt_sz = sz; + dev->nr_ites = nr_ites; + dev->event_map.lpi_map = lpi_map; + dev->event_map.col_map = col_map; +@@ -3483,7 +3533,13 @@ static void its_free_device(struct its_device *its_dev) + list_del(&its_dev->entry); + raw_spin_unlock_irqrestore(&its_dev->its->lock, flags); + kfree(its_dev->event_map.col_map); +- kfree(its_dev->itt); ++ ++ if (of_machine_is_compatible("rockchip,rk3568") || ++ of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588")) ++ free_pages((unsigned long)its_dev->itt, get_order(its_dev->itt_sz)); ++ else ++ kfree(its_dev->itt); ++ + kfree(its_dev); + } + +@@ -5089,6 +5145,7 @@ static int __init its_probe_one(struct its_node *its) + struct page *page; + u32 ctlr; + int err; ++ gfp_t gfp_flags; + + its_enable_quirks(its); + +@@ -5122,7 +5179,10 @@ static int __init its_probe_one(struct its_node *its) + } + } + +- page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, ++ gfp_flags = GFP_KERNEL | __GFP_ZERO; ++ if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566") || of_machine_is_compatible("rockchip,rk3588")) ++ gfp_flags |= GFP_DMA32; ++ page = alloc_pages_node(its->numa_node, gfp_flags, + get_order(ITS_CMD_QUEUE_SZ)); + if (!page) { + err = -ENOMEM; +@@ -5151,6 +5211,11 @@ static int __init its_probe_one(struct its_node *its) + if (its->flags & ITS_FLAGS_FORCE_NON_SHAREABLE) + tmp &= ~GITS_CBASER_SHAREABILITY_MASK; + ++ if (of_machine_is_compatible("rockchip,rk3568") || ++ of_machine_is_compatible("rockchip,rk3566") || ++ of_machine_is_compatible("rockchip,rk3588")) ++ tmp &= ~GITS_CBASER_SHAREABILITY_MASK; ++ + if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) { + if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) { + /* +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0021-RK3588-Add-USB3-DRD-Support.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0021-RK3588-Add-USB3-DRD-Support.patch new file mode 100644 index 000000000000..384e73ce4294 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0021-RK3588-Add-USB3-DRD-Support.patch @@ -0,0 +1,2602 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Fri, 16 Feb 2024 18:01:16 +0100 +Subject: dt-bindings: phy: add rockchip usbdp combo phy document + +Add device tree binding document for Rockchip USBDP Combo PHY +with Samsung IP block. + +Co-developed-by: Frank Wang +Signed-off-by: Frank Wang +Reviewed-by: Conor Dooley +Signed-off-by: Sebastian Reichel +--- + Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml | 148 ++++++++++ + 1 file changed, 148 insertions(+) + +diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml +@@ -0,0 +1,148 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/phy/phy-rockchip-usbdp.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Rockchip USBDP Combo PHY with Samsung IP block ++ ++maintainers: ++ - Frank Wang ++ - Zhang Yubing ++ ++properties: ++ compatible: ++ enum: ++ - rockchip,rk3588-usbdp-phy ++ ++ reg: ++ maxItems: 1 ++ ++ "#phy-cells": ++ description: | ++ Cell allows setting the type of the PHY. Possible values are: ++ - PHY_TYPE_USB3 ++ - PHY_TYPE_DP ++ const: 1 ++ ++ clocks: ++ maxItems: 4 ++ ++ clock-names: ++ items: ++ - const: refclk ++ - const: immortal ++ - const: pclk ++ - const: utmi ++ ++ resets: ++ maxItems: 5 ++ ++ reset-names: ++ items: ++ - const: init ++ - const: cmn ++ - const: lane ++ - const: pcs_apb ++ - const: pma_apb ++ ++ rockchip,dp-lane-mux: ++ $ref: /schemas/types.yaml#/definitions/uint32-array ++ minItems: 2 ++ maxItems: 4 ++ items: ++ maximum: 3 ++ description: ++ An array of physical Type-C lanes indexes. Position of an entry ++ determines the DisplayPort (DP) lane index, while the value of an entry ++ indicates physical Type-C lane. The supported DP lanes number are 2 or 4. ++ e.g. for 2 lanes DP lanes map, we could have "rockchip,dp-lane-mux = <2, ++ 3>;", assuming DP lane0 on Type-C phy lane2, DP lane1 on Type-C phy ++ lane3. For 4 lanes DP lanes map, we could have "rockchip,dp-lane-mux = ++ <0, 1, 2, 3>;", assuming DP lane0 on Type-C phy lane0, DP lane1 on Type-C ++ phy lane1, DP lane2 on Type-C phy lane2, DP lane3 on Type-C phy lane3. If ++ DP lanes are mapped by DisplayPort Alt mode, this property is not needed. ++ ++ rockchip,u2phy-grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ Phandle to the syscon managing the 'usb2 phy general register files'. ++ ++ rockchip,usb-grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ Phandle to the syscon managing the 'usb general register files'. ++ ++ rockchip,usbdpphy-grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ Phandle to the syscon managing the 'usbdp phy general register files'. ++ ++ rockchip,vo-grf: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ Phandle to the syscon managing the 'video output general register files'. ++ When select the DP lane mapping will request its phandle. ++ ++ sbu1-dc-gpios: ++ description: ++ GPIO connected to the SBU1 line of the USB-C connector via a big resistor ++ (~100K) to apply a DC offset for signalling the connector orientation. ++ maxItems: 1 ++ ++ sbu2-dc-gpios: ++ description: ++ GPIO connected to the SBU2 line of the USB-C connector via a big resistor ++ (~100K) to apply a DC offset for signalling the connector orientation. ++ maxItems: 1 ++ ++ orientation-switch: ++ description: Flag the port as possible handler of orientation switching ++ type: boolean ++ ++ mode-switch: ++ description: Flag the port as possible handler of altmode switching ++ type: boolean ++ ++ port: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: ++ A port node to link the PHY to a TypeC controller for the purpose of ++ handling orientation switching. ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - resets ++ - reset-names ++ - "#phy-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ ++ usbdp_phy0: phy@fed80000 { ++ compatible = "rockchip,rk3588-usbdp-phy"; ++ reg = <0xfed80000 0x10000>; ++ #phy-cells = <1>; ++ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>, ++ <&cru CLK_USBDP_PHY0_IMMORTAL>, ++ <&cru PCLK_USBDPPHY0>, ++ <&u2phy0>; ++ clock-names = "refclk", "immortal", "pclk", "utmi"; ++ resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>, ++ <&cru SRST_USBDP_COMBO_PHY0_CMN>, ++ <&cru SRST_USBDP_COMBO_PHY0_LANE>, ++ <&cru SRST_USBDP_COMBO_PHY0_PCS>, ++ <&cru SRST_P_USBDPPHY0>; ++ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb"; ++ rockchip,u2phy-grf = <&usb2phy0_grf>; ++ rockchip,usb-grf = <&usb_grf>; ++ rockchip,usbdpphy-grf = <&usbdpphy0_grf>; ++ rockchip,vo-grf = <&vo0_grf>; ++ }; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Fri, 16 Feb 2024 18:01:17 +0100 +Subject: phy: rockchip: add usbdp combo phy driver + +This adds a new USBDP combo PHY with Samsung IP block driver. + +The driver get lane mux and mapping info in 2 ways, supporting +DisplayPort alternate mode or parsing from DT. When parsing from DT, +the property "rockchip,dp-lane-mux" provide the DP mux and mapping +info. This is needed when the PHY is not used with TypeC Alt-Mode. +For example if the USB3 interface of the PHY is connected to a USB +Type A connector and the DP interface is connected to a DisplayPort +connector. + +When do DP link training, need to set lane number, link rate, swing, +and pre-emphasis via PHY configure interface. + +Co-developed-by: Heiko Stuebner +Signed-off-by: Heiko Stuebner +Co-developed-by: Zhang Yubing +Signed-off-by: Zhang Yubing +Co-developed-by: Frank Wang +Signed-off-by: Frank Wang +Signed-off-by: Sebastian Reichel +--- + drivers/phy/rockchip/Kconfig | 12 + + drivers/phy/rockchip/Makefile | 1 + + drivers/phy/rockchip/phy-rockchip-usbdp.c | 1612 ++++++++++ + 3 files changed, 1625 insertions(+) + +diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/phy/rockchip/Kconfig ++++ b/drivers/phy/rockchip/Kconfig +@@ -107,3 +107,15 @@ config PHY_ROCKCHIP_USB + select GENERIC_PHY + help + Enable this to support the Rockchip USB 2.0 PHY. ++ ++config PHY_ROCKCHIP_USBDP ++ tristate "Rockchip USBDP COMBO PHY Driver" ++ depends on ARCH_ROCKCHIP && OF ++ select GENERIC_PHY ++ select TYPEC ++ help ++ Enable this to support the Rockchip USB3.0/DP combo PHY with ++ Samsung IP block. This is required for USB3 support on RK3588. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called phy-rockchip-usbdp +diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/phy/rockchip/Makefile ++++ b/drivers/phy/rockchip/Makefile +@@ -11,3 +11,4 @@ obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o + obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o + obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o + obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o ++obj-$(CONFIG_PHY_ROCKCHIP_USBDP) += phy-rockchip-usbdp.o +diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c +@@ -0,0 +1,1612 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Rockchip USBDP Combo PHY with Samsung IP block driver ++ * ++ * Copyright (C) 2021 Rockchip Electronics Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* USBDP PHY Register Definitions */ ++#define UDPHY_PCS 0x4000 ++#define UDPHY_PMA 0x8000 ++ ++/* VO0 GRF Registers */ ++#define DP_SINK_HPD_CFG BIT(11) ++#define DP_SINK_HPD_SEL BIT(10) ++#define DP_AUX_DIN_SEL BIT(9) ++#define DP_AUX_DOUT_SEL BIT(8) ++#define DP_LANE_SEL_N(n) GENMASK(2 * (n) + 1, 2 * (n)) ++#define DP_LANE_SEL_ALL GENMASK(7, 0) ++ ++/* PMA CMN Registers */ ++#define CMN_LANE_MUX_AND_EN_OFFSET 0x0288 /* cmn_reg00A2 */ ++#define CMN_DP_LANE_MUX_N(n) BIT((n) + 4) ++#define CMN_DP_LANE_EN_N(n) BIT(n) ++#define CMN_DP_LANE_MUX_ALL GENMASK(7, 4) ++#define CMN_DP_LANE_EN_ALL GENMASK(3, 0) ++ ++#define CMN_DP_LINK_OFFSET 0x28c /* cmn_reg00A3 */ ++#define CMN_DP_TX_LINK_BW GENMASK(6, 5) ++#define CMN_DP_TX_LANE_SWAP_EN BIT(2) ++ ++#define CMN_SSC_EN_OFFSET 0x2d0 /* cmn_reg00B4 */ ++#define CMN_ROPLL_SSC_EN BIT(1) ++#define CMN_LCPLL_SSC_EN BIT(0) ++ ++#define CMN_ANA_LCPLL_DONE_OFFSET 0x0350 /* cmn_reg00D4 */ ++#define CMN_ANA_LCPLL_LOCK_DONE BIT(7) ++#define CMN_ANA_LCPLL_AFC_DONE BIT(6) ++ ++#define CMN_ANA_ROPLL_DONE_OFFSET 0x0354 /* cmn_reg00D5 */ ++#define CMN_ANA_ROPLL_LOCK_DONE BIT(1) ++#define CMN_ANA_ROPLL_AFC_DONE BIT(0) ++ ++#define CMN_DP_RSTN_OFFSET 0x038c /* cmn_reg00E3 */ ++#define CMN_DP_INIT_RSTN BIT(3) ++#define CMN_DP_CMN_RSTN BIT(2) ++#define CMN_CDR_WTCHDG_EN BIT(1) ++#define CMN_CDR_WTCHDG_MSK_CDR_EN BIT(0) ++ ++#define TRSV_ANA_TX_CLK_OFFSET_N(n) (0x854 + (n) * 0x800) /* trsv_reg0215 */ ++#define LN_ANA_TX_SER_TXCLK_INV BIT(1) ++ ++#define TRSV_LN0_MON_RX_CDR_DONE_OFFSET 0x0b84 /* trsv_reg02E1 */ ++#define TRSV_LN0_MON_RX_CDR_LOCK_DONE BIT(0) ++ ++#define TRSV_LN2_MON_RX_CDR_DONE_OFFSET 0x1b84 /* trsv_reg06E1 */ ++#define TRSV_LN2_MON_RX_CDR_LOCK_DONE BIT(0) ++ ++#define BIT_WRITEABLE_SHIFT 16 ++#define PHY_AUX_DP_DATA_POL_NORMAL 0 ++#define PHY_AUX_DP_DATA_POL_INVERT 1 ++#define PHY_LANE_MUX_USB 0 ++#define PHY_LANE_MUX_DP 1 ++ ++enum { ++ DP_BW_RBR, ++ DP_BW_HBR, ++ DP_BW_HBR2, ++ DP_BW_HBR3, ++}; ++ ++enum { ++ UDPHY_MODE_NONE = 0, ++ UDPHY_MODE_USB = BIT(0), ++ UDPHY_MODE_DP = BIT(1), ++ UDPHY_MODE_DP_USB = BIT(1) | BIT(0), ++}; ++ ++struct rk_udphy_grf_reg { ++ unsigned int offset; ++ unsigned int disable; ++ unsigned int enable; ++}; ++ ++#define _RK_UDPHY_GEN_GRF_REG(offset, mask, disable, enable) \ ++{\ ++ offset, \ ++ FIELD_PREP_CONST(mask, disable) | (mask << BIT_WRITEABLE_SHIFT), \ ++ FIELD_PREP_CONST(mask, enable) | (mask << BIT_WRITEABLE_SHIFT), \ ++} ++ ++#define RK_UDPHY_GEN_GRF_REG(offset, bitend, bitstart, disable, enable) \ ++ _RK_UDPHY_GEN_GRF_REG(offset, GENMASK(bitend, bitstart), disable, enable) ++ ++struct rk_udphy_grf_cfg { ++ /* u2phy-grf */ ++ struct rk_udphy_grf_reg bvalid_phy_con; ++ struct rk_udphy_grf_reg bvalid_grf_con; ++ ++ /* usb-grf */ ++ struct rk_udphy_grf_reg usb3otg0_cfg; ++ struct rk_udphy_grf_reg usb3otg1_cfg; ++ ++ /* usbdpphy-grf */ ++ struct rk_udphy_grf_reg low_pwrn; ++ struct rk_udphy_grf_reg rx_lfps; ++}; ++ ++struct rk_udphy_vogrf_cfg { ++ /* vo-grf */ ++ struct rk_udphy_grf_reg hpd_trigger; ++ u32 dp_lane_reg; ++}; ++ ++struct rk_udphy_dp_tx_drv_ctrl { ++ u32 trsv_reg0204; ++ u32 trsv_reg0205; ++ u32 trsv_reg0206; ++ u32 trsv_reg0207; ++}; ++ ++struct rk_udphy_cfg { ++ unsigned int num_phys; ++ unsigned int phy_ids[2]; ++ /* resets to be requested */ ++ const char * const *rst_list; ++ int num_rsts; ++ ++ struct rk_udphy_grf_cfg grfcfg; ++ struct rk_udphy_vogrf_cfg vogrfcfg[2]; ++ const struct rk_udphy_dp_tx_drv_ctrl (*dp_tx_ctrl_cfg[4])[4]; ++ const struct rk_udphy_dp_tx_drv_ctrl (*dp_tx_ctrl_cfg_typec[4])[4]; ++}; ++ ++struct rk_udphy { ++ struct device *dev; ++ struct regmap *pma_regmap; ++ struct regmap *u2phygrf; ++ struct regmap *udphygrf; ++ struct regmap *usbgrf; ++ struct regmap *vogrf; ++ struct typec_switch_dev *sw; ++ struct typec_mux_dev *mux; ++ struct mutex mutex; /* mutex to protect access to individual PHYs */ ++ ++ /* clocks and rests */ ++ int num_clks; ++ struct clk_bulk_data *clks; ++ struct clk *refclk; ++ int num_rsts; ++ struct reset_control_bulk_data *rsts; ++ ++ /* PHY status management */ ++ bool flip; ++ bool mode_change; ++ u8 mode; ++ u8 status; ++ ++ /* utilized for USB */ ++ bool hs; /* flag for high-speed */ ++ ++ /* utilized for DP */ ++ struct gpio_desc *sbu1_dc_gpio; ++ struct gpio_desc *sbu2_dc_gpio; ++ u32 lane_mux_sel[4]; ++ u32 dp_lane_sel[4]; ++ u32 dp_aux_dout_sel; ++ u32 dp_aux_din_sel; ++ bool dp_sink_hpd_sel; ++ bool dp_sink_hpd_cfg; ++ u8 bw; ++ int id; ++ ++ bool dp_in_use; ++ ++ /* PHY const config */ ++ const struct rk_udphy_cfg *cfgs; ++ ++ /* PHY devices */ ++ struct phy *phy_dp; ++ struct phy *phy_u3; ++}; ++ ++static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr[4][4] = { ++ /* voltage swing 0, pre-emphasis 0->3 */ ++ { ++ { 0x20, 0x10, 0x42, 0xe5 }, ++ { 0x26, 0x14, 0x42, 0xe5 }, ++ { 0x29, 0x18, 0x42, 0xe5 }, ++ { 0x2b, 0x1c, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 1, pre-emphasis 0->2 */ ++ { ++ { 0x23, 0x10, 0x42, 0xe7 }, ++ { 0x2a, 0x17, 0x43, 0xe7 }, ++ { 0x2b, 0x1a, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 2, pre-emphasis 0->1 */ ++ { ++ { 0x27, 0x10, 0x42, 0xe7 }, ++ { 0x2b, 0x17, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 3, pre-emphasis 0 */ ++ { ++ { 0x29, 0x10, 0x43, 0xe7 }, ++ }, ++}; ++ ++static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr_typec[4][4] = { ++ /* voltage swing 0, pre-emphasis 0->3 */ ++ { ++ { 0x20, 0x10, 0x42, 0xe5 }, ++ { 0x26, 0x14, 0x42, 0xe5 }, ++ { 0x29, 0x18, 0x42, 0xe5 }, ++ { 0x2b, 0x1c, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 1, pre-emphasis 0->2 */ ++ { ++ { 0x23, 0x10, 0x42, 0xe7 }, ++ { 0x2a, 0x17, 0x43, 0xe7 }, ++ { 0x2b, 0x1a, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 2, pre-emphasis 0->1 */ ++ { ++ { 0x27, 0x10, 0x43, 0x67 }, ++ { 0x2b, 0x17, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 3, pre-emphasis 0 */ ++ { ++ { 0x29, 0x10, 0x43, 0xe7 }, ++ }, ++}; ++ ++static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr2[4][4] = { ++ /* voltage swing 0, pre-emphasis 0->3 */ ++ { ++ { 0x21, 0x10, 0x42, 0xe5 }, ++ { 0x26, 0x14, 0x42, 0xe5 }, ++ { 0x26, 0x16, 0x43, 0xe5 }, ++ { 0x2a, 0x19, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 1, pre-emphasis 0->2 */ ++ { ++ { 0x24, 0x10, 0x42, 0xe7 }, ++ { 0x2a, 0x17, 0x43, 0xe7 }, ++ { 0x2b, 0x1a, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 2, pre-emphasis 0->1 */ ++ { ++ { 0x28, 0x10, 0x42, 0xe7 }, ++ { 0x2b, 0x17, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 3, pre-emphasis 0 */ ++ { ++ { 0x28, 0x10, 0x43, 0xe7 }, ++ }, ++}; ++ ++static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr3[4][4] = { ++ /* voltage swing 0, pre-emphasis 0->3 */ ++ { ++ { 0x21, 0x10, 0x42, 0xe5 }, ++ { 0x26, 0x14, 0x42, 0xe5 }, ++ { 0x26, 0x16, 0x43, 0xe5 }, ++ { 0x29, 0x18, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 1, pre-emphasis 0->2 */ ++ { ++ { 0x24, 0x10, 0x42, 0xe7 }, ++ { 0x2a, 0x18, 0x43, 0xe7 }, ++ { 0x2b, 0x1b, 0x43, 0xe7 } ++ }, ++ ++ /* voltage swing 2, pre-emphasis 0->1 */ ++ { ++ { 0x27, 0x10, 0x42, 0xe7 }, ++ { 0x2b, 0x18, 0x43, 0xe7 } ++ }, ++ ++ /* voltage swing 3, pre-emphasis 0 */ ++ { ++ { 0x28, 0x10, 0x43, 0xe7 }, ++ }, ++}; ++ ++static const struct reg_sequence rk_udphy_24m_refclk_cfg[] = { ++ {0x0090, 0x68}, {0x0094, 0x68}, ++ {0x0128, 0x24}, {0x012c, 0x44}, ++ {0x0130, 0x3f}, {0x0134, 0x44}, ++ {0x015c, 0xa9}, {0x0160, 0x71}, ++ {0x0164, 0x71}, {0x0168, 0xa9}, ++ {0x0174, 0xa9}, {0x0178, 0x71}, ++ {0x017c, 0x71}, {0x0180, 0xa9}, ++ {0x018c, 0x41}, {0x0190, 0x00}, ++ {0x0194, 0x05}, {0x01ac, 0x2a}, ++ {0x01b0, 0x17}, {0x01b4, 0x17}, ++ {0x01b8, 0x2a}, {0x01c8, 0x04}, ++ {0x01cc, 0x08}, {0x01d0, 0x08}, ++ {0x01d4, 0x04}, {0x01d8, 0x20}, ++ {0x01dc, 0x01}, {0x01e0, 0x09}, ++ {0x01e4, 0x03}, {0x01f0, 0x29}, ++ {0x01f4, 0x02}, {0x01f8, 0x02}, ++ {0x01fc, 0x29}, {0x0208, 0x2a}, ++ {0x020c, 0x17}, {0x0210, 0x17}, ++ {0x0214, 0x2a}, {0x0224, 0x20}, ++ {0x03f0, 0x0a}, {0x03f4, 0x07}, ++ {0x03f8, 0x07}, {0x03fc, 0x0c}, ++ {0x0404, 0x12}, {0x0408, 0x1a}, ++ {0x040c, 0x1a}, {0x0410, 0x3f}, ++ {0x0ce0, 0x68}, {0x0ce8, 0xd0}, ++ {0x0cf0, 0x87}, {0x0cf8, 0x70}, ++ {0x0d00, 0x70}, {0x0d08, 0xa9}, ++ {0x1ce0, 0x68}, {0x1ce8, 0xd0}, ++ {0x1cf0, 0x87}, {0x1cf8, 0x70}, ++ {0x1d00, 0x70}, {0x1d08, 0xa9}, ++ {0x0a3c, 0xd0}, {0x0a44, 0xd0}, ++ {0x0a48, 0x01}, {0x0a4c, 0x0d}, ++ {0x0a54, 0xe0}, {0x0a5c, 0xe0}, ++ {0x0a64, 0xa8}, {0x1a3c, 0xd0}, ++ {0x1a44, 0xd0}, {0x1a48, 0x01}, ++ {0x1a4c, 0x0d}, {0x1a54, 0xe0}, ++ {0x1a5c, 0xe0}, {0x1a64, 0xa8} ++}; ++ ++static const struct reg_sequence rk_udphy_26m_refclk_cfg[] = { ++ {0x0830, 0x07}, {0x085c, 0x80}, ++ {0x1030, 0x07}, {0x105c, 0x80}, ++ {0x1830, 0x07}, {0x185c, 0x80}, ++ {0x2030, 0x07}, {0x205c, 0x80}, ++ {0x0228, 0x38}, {0x0104, 0x44}, ++ {0x0248, 0x44}, {0x038c, 0x02}, ++ {0x0878, 0x04}, {0x1878, 0x04}, ++ {0x0898, 0x77}, {0x1898, 0x77}, ++ {0x0054, 0x01}, {0x00e0, 0x38}, ++ {0x0060, 0x24}, {0x0064, 0x77}, ++ {0x0070, 0x76}, {0x0234, 0xe8}, ++ {0x0af4, 0x15}, {0x1af4, 0x15}, ++ {0x081c, 0xe5}, {0x181c, 0xe5}, ++ {0x099c, 0x48}, {0x199c, 0x48}, ++ {0x09a4, 0x07}, {0x09a8, 0x22}, ++ {0x19a4, 0x07}, {0x19a8, 0x22}, ++ {0x09b8, 0x3e}, {0x19b8, 0x3e}, ++ {0x09e4, 0x02}, {0x19e4, 0x02}, ++ {0x0a34, 0x1e}, {0x1a34, 0x1e}, ++ {0x0a98, 0x2f}, {0x1a98, 0x2f}, ++ {0x0c30, 0x0e}, {0x0c48, 0x06}, ++ {0x1c30, 0x0e}, {0x1c48, 0x06}, ++ {0x028c, 0x18}, {0x0af0, 0x00}, ++ {0x1af0, 0x00} ++}; ++ ++static const struct reg_sequence rk_udphy_init_sequence[] = { ++ {0x0104, 0x44}, {0x0234, 0xe8}, ++ {0x0248, 0x44}, {0x028c, 0x18}, ++ {0x081c, 0xe5}, {0x0878, 0x00}, ++ {0x0994, 0x1c}, {0x0af0, 0x00}, ++ {0x181c, 0xe5}, {0x1878, 0x00}, ++ {0x1994, 0x1c}, {0x1af0, 0x00}, ++ {0x0428, 0x60}, {0x0d58, 0x33}, ++ {0x1d58, 0x33}, {0x0990, 0x74}, ++ {0x0d64, 0x17}, {0x08c8, 0x13}, ++ {0x1990, 0x74}, {0x1d64, 0x17}, ++ {0x18c8, 0x13}, {0x0d90, 0x40}, ++ {0x0da8, 0x40}, {0x0dc0, 0x40}, ++ {0x0dd8, 0x40}, {0x1d90, 0x40}, ++ {0x1da8, 0x40}, {0x1dc0, 0x40}, ++ {0x1dd8, 0x40}, {0x03c0, 0x30}, ++ {0x03c4, 0x06}, {0x0e10, 0x00}, ++ {0x1e10, 0x00}, {0x043c, 0x0f}, ++ {0x0d2c, 0xff}, {0x1d2c, 0xff}, ++ {0x0d34, 0x0f}, {0x1d34, 0x0f}, ++ {0x08fc, 0x2a}, {0x0914, 0x28}, ++ {0x0a30, 0x03}, {0x0e38, 0x03}, ++ {0x0ecc, 0x27}, {0x0ed0, 0x22}, ++ {0x0ed4, 0x26}, {0x18fc, 0x2a}, ++ {0x1914, 0x28}, {0x1a30, 0x03}, ++ {0x1e38, 0x03}, {0x1ecc, 0x27}, ++ {0x1ed0, 0x22}, {0x1ed4, 0x26}, ++ {0x0048, 0x0f}, {0x0060, 0x3c}, ++ {0x0064, 0xf7}, {0x006c, 0x20}, ++ {0x0070, 0x7d}, {0x0074, 0x68}, ++ {0x0af4, 0x1a}, {0x1af4, 0x1a}, ++ {0x0440, 0x3f}, {0x10d4, 0x08}, ++ {0x20d4, 0x08}, {0x00d4, 0x30}, ++ {0x0024, 0x6e}, ++}; ++ ++static inline int rk_udphy_grfreg_write(struct regmap *base, ++ const struct rk_udphy_grf_reg *reg, bool en) ++{ ++ return regmap_write(base, reg->offset, en ? reg->enable : reg->disable); ++} ++ ++static int rk_udphy_clk_init(struct rk_udphy *udphy, struct device *dev) ++{ ++ int i; ++ ++ udphy->num_clks = devm_clk_bulk_get_all(dev, &udphy->clks); ++ if (udphy->num_clks < 1) ++ return -ENODEV; ++ ++ /* used for configure phy reference clock frequency */ ++ for (i = 0; i < udphy->num_clks; i++) { ++ if (!strncmp(udphy->clks[i].id, "refclk", 6)) { ++ udphy->refclk = udphy->clks[i].clk; ++ break; ++ } ++ } ++ ++ if (!udphy->refclk) ++ return dev_err_probe(udphy->dev, -EINVAL, "no refclk found\n"); ++ ++ return 0; ++} ++ ++static int rk_udphy_reset_assert_all(struct rk_udphy *udphy) ++{ ++ return reset_control_bulk_assert(udphy->num_rsts, udphy->rsts); ++} ++ ++static int rk_udphy_reset_deassert_all(struct rk_udphy *udphy) ++{ ++ return reset_control_bulk_deassert(udphy->num_rsts, udphy->rsts); ++} ++ ++static int rk_udphy_reset_deassert(struct rk_udphy *udphy, char *name) ++{ ++ struct reset_control_bulk_data *list = udphy->rsts; ++ int idx; ++ ++ for (idx = 0; idx < udphy->num_rsts; idx++) { ++ if (!strcmp(list[idx].id, name)) ++ return reset_control_deassert(list[idx].rstc); ++ } ++ ++ return -EINVAL; ++} ++ ++static int rk_udphy_reset_init(struct rk_udphy *udphy, struct device *dev) ++{ ++ const struct rk_udphy_cfg *cfg = udphy->cfgs; ++ int idx; ++ ++ udphy->num_rsts = cfg->num_rsts; ++ udphy->rsts = devm_kcalloc(dev, udphy->num_rsts, ++ sizeof(*udphy->rsts), GFP_KERNEL); ++ if (!udphy->rsts) ++ return -ENOMEM; ++ ++ for (idx = 0; idx < cfg->num_rsts; idx++) ++ udphy->rsts[idx].id = cfg->rst_list[idx]; ++ ++ return devm_reset_control_bulk_get_exclusive(dev, cfg->num_rsts, ++ udphy->rsts); ++} ++ ++static void rk_udphy_u3_port_disable(struct rk_udphy *udphy, u8 disable) ++{ ++ const struct rk_udphy_cfg *cfg = udphy->cfgs; ++ const struct rk_udphy_grf_reg *preg; ++ ++ preg = udphy->id ? &cfg->grfcfg.usb3otg1_cfg : &cfg->grfcfg.usb3otg0_cfg; ++ rk_udphy_grfreg_write(udphy->usbgrf, preg, disable); ++} ++ ++static void rk_udphy_usb_bvalid_enable(struct rk_udphy *udphy, u8 enable) ++{ ++ const struct rk_udphy_cfg *cfg = udphy->cfgs; ++ ++ rk_udphy_grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_phy_con, enable); ++ rk_udphy_grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_grf_con, enable); ++} ++ ++/* ++ * In usb/dp combo phy driver, here are 2 ways to mapping lanes. ++ * ++ * 1 Type-C Mapping table (DP_Alt_Mode V1.0b remove ABF pin mapping) ++ * --------------------------------------------------------------------------- ++ * Type-C Pin B11-B10 A2-A3 A11-A10 B2-B3 ++ * PHY Pad ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) ++ * C/E(Normal) dpln3 dpln2 dpln0 dpln1 ++ * C/E(Flip ) dpln0 dpln1 dpln3 dpln2 ++ * D/F(Normal) usbrx usbtx dpln0 dpln1 ++ * D/F(Flip ) dpln0 dpln1 usbrx usbtx ++ * A(Normal ) dpln3 dpln1 dpln2 dpln0 ++ * A(Flip ) dpln2 dpln0 dpln3 dpln1 ++ * B(Normal ) usbrx usbtx dpln1 dpln0 ++ * B(Flip ) dpln1 dpln0 usbrx usbtx ++ * --------------------------------------------------------------------------- ++ * ++ * 2 Mapping the lanes in dtsi ++ * if all 4 lane assignment for dp function, define rockchip,dp-lane-mux = ; ++ * sample as follow: ++ * --------------------------------------------------------------------------- ++ * B11-B10 A2-A3 A11-A10 B2-B3 ++ * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) ++ * <0 1 2 3> dpln0 dpln1 dpln2 dpln3 ++ * <2 3 0 1> dpln2 dpln3 dpln0 dpln1 ++ * --------------------------------------------------------------------------- ++ * if 2 lane for dp function, 2 lane for usb function, define rockchip,dp-lane-mux = ; ++ * sample as follow: ++ * --------------------------------------------------------------------------- ++ * B11-B10 A2-A3 A11-A10 B2-B3 ++ * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) ++ * <0 1> dpln0 dpln1 usbrx usbtx ++ * <2 3> usbrx usbtx dpln0 dpln1 ++ * --------------------------------------------------------------------------- ++ */ ++ ++static void rk_udphy_dplane_select(struct rk_udphy *udphy) ++{ ++ const struct rk_udphy_cfg *cfg = udphy->cfgs; ++ u32 value = 0; ++ ++ switch (udphy->mode) { ++ case UDPHY_MODE_DP: ++ value |= 2 << udphy->dp_lane_sel[2] * 2; ++ value |= 3 << udphy->dp_lane_sel[3] * 2; ++ fallthrough; ++ ++ case UDPHY_MODE_DP_USB: ++ value |= 0 << udphy->dp_lane_sel[0] * 2; ++ value |= 1 << udphy->dp_lane_sel[1] * 2; ++ break; ++ ++ case UDPHY_MODE_USB: ++ break; ++ ++ default: ++ break; ++ } ++ ++ regmap_write(udphy->vogrf, cfg->vogrfcfg[udphy->id].dp_lane_reg, ++ ((DP_AUX_DIN_SEL | DP_AUX_DOUT_SEL | DP_LANE_SEL_ALL) << 16) | ++ FIELD_PREP(DP_AUX_DIN_SEL, udphy->dp_aux_din_sel) | ++ FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value); ++} ++ ++static int rk_udphy_dplane_get(struct rk_udphy *udphy) ++{ ++ int dp_lanes; ++ ++ switch (udphy->mode) { ++ case UDPHY_MODE_DP: ++ dp_lanes = 4; ++ break; ++ ++ case UDPHY_MODE_DP_USB: ++ dp_lanes = 2; ++ break; ++ ++ case UDPHY_MODE_USB: ++ default: ++ dp_lanes = 0; ++ break; ++ } ++ ++ return dp_lanes; ++} ++ ++static void rk_udphy_dplane_enable(struct rk_udphy *udphy, int dp_lanes) ++{ ++ u32 val = 0; ++ int i; ++ ++ for (i = 0; i < dp_lanes; i++) ++ val |= BIT(udphy->dp_lane_sel[i]); ++ ++ regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, CMN_DP_LANE_EN_ALL, ++ FIELD_PREP(CMN_DP_LANE_EN_ALL, val)); ++ ++ if (!dp_lanes) ++ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, ++ CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); ++} ++ ++static void rk_udphy_dp_hpd_event_trigger(struct rk_udphy *udphy, bool hpd) ++{ ++ const struct rk_udphy_cfg *cfg = udphy->cfgs; ++ ++ udphy->dp_sink_hpd_sel = true; ++ udphy->dp_sink_hpd_cfg = hpd; ++ ++ if (!udphy->dp_in_use) ++ return; ++ ++ rk_udphy_grfreg_write(udphy->vogrf, &cfg->vogrfcfg[udphy->id].hpd_trigger, hpd); ++} ++ ++static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy) ++{ ++ if (udphy->flip) { ++ udphy->dp_lane_sel[0] = 0; ++ udphy->dp_lane_sel[1] = 1; ++ udphy->dp_lane_sel[2] = 3; ++ udphy->dp_lane_sel[3] = 2; ++ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB; ++ udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_INVERT; ++ udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_INVERT; ++ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 1); ++ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0); ++ } else { ++ udphy->dp_lane_sel[0] = 2; ++ udphy->dp_lane_sel[1] = 3; ++ udphy->dp_lane_sel[2] = 1; ++ udphy->dp_lane_sel[3] = 0; ++ udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; ++ udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_NORMAL; ++ udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_NORMAL; ++ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0); ++ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 1); ++ } ++ ++ udphy->mode = UDPHY_MODE_DP_USB; ++} ++ ++static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw, ++ enum typec_orientation orien) ++{ ++ struct rk_udphy *udphy = typec_switch_get_drvdata(sw); ++ ++ mutex_lock(&udphy->mutex); ++ ++ if (orien == TYPEC_ORIENTATION_NONE) { ++ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0); ++ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0); ++ /* unattached */ ++ rk_udphy_usb_bvalid_enable(udphy, false); ++ goto unlock_ret; ++ } ++ ++ udphy->flip = (orien == TYPEC_ORIENTATION_REVERSE) ? true : false; ++ rk_udphy_set_typec_default_mapping(udphy); ++ rk_udphy_usb_bvalid_enable(udphy, true); ++ ++unlock_ret: ++ mutex_unlock(&udphy->mutex); ++ return 0; ++} ++ ++static void rk_udphy_orien_switch_unregister(void *data) ++{ ++ struct rk_udphy *udphy = data; ++ ++ typec_switch_unregister(udphy->sw); ++} ++ ++static int rk_udphy_setup_orien_switch(struct rk_udphy *udphy) ++{ ++ struct typec_switch_desc sw_desc = { }; ++ ++ sw_desc.drvdata = udphy; ++ sw_desc.fwnode = dev_fwnode(udphy->dev); ++ sw_desc.set = rk_udphy_orien_sw_set; ++ ++ udphy->sw = typec_switch_register(udphy->dev, &sw_desc); ++ if (IS_ERR(udphy->sw)) { ++ dev_err(udphy->dev, "Error register typec orientation switch: %ld\n", ++ PTR_ERR(udphy->sw)); ++ return PTR_ERR(udphy->sw); ++ } ++ ++ return devm_add_action_or_reset(udphy->dev, ++ rk_udphy_orien_switch_unregister, udphy); ++} ++ ++static int rk_udphy_refclk_set(struct rk_udphy *udphy) ++{ ++ unsigned long rate; ++ int ret; ++ ++ /* configure phy reference clock */ ++ rate = clk_get_rate(udphy->refclk); ++ dev_dbg(udphy->dev, "refclk freq %ld\n", rate); ++ ++ switch (rate) { ++ case 24000000: ++ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_24m_refclk_cfg, ++ ARRAY_SIZE(rk_udphy_24m_refclk_cfg)); ++ if (ret) ++ return ret; ++ break; ++ ++ case 26000000: ++ /* register default is 26MHz */ ++ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_26m_refclk_cfg, ++ ARRAY_SIZE(rk_udphy_26m_refclk_cfg)); ++ if (ret) ++ return ret; ++ break; ++ ++ default: ++ dev_err(udphy->dev, "unsupported refclk freq %ld\n", rate); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rk_udphy_status_check(struct rk_udphy *udphy) ++{ ++ unsigned int val; ++ int ret; ++ ++ /* LCPLL check */ ++ if (udphy->mode & UDPHY_MODE_USB) { ++ ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_LCPLL_DONE_OFFSET, ++ val, (val & CMN_ANA_LCPLL_AFC_DONE) && ++ (val & CMN_ANA_LCPLL_LOCK_DONE), 200, 100000); ++ if (ret) { ++ dev_err(udphy->dev, "cmn ana lcpll lock timeout\n"); ++ /* ++ * If earlier software (U-Boot) enabled USB once already ++ * the PLL may have problems locking on the first try. ++ * It will be successful on the second try, so for the ++ * time being a -EPROBE_DEFER will solve the issue. ++ * ++ * This requires further investigation to understand the ++ * root cause, especially considering that the driver is ++ * asserting all reset lines at probe time. ++ */ ++ return -EPROBE_DEFER; ++ } ++ ++ if (!udphy->flip) { ++ ret = regmap_read_poll_timeout(udphy->pma_regmap, ++ TRSV_LN0_MON_RX_CDR_DONE_OFFSET, val, ++ val & TRSV_LN0_MON_RX_CDR_LOCK_DONE, ++ 200, 100000); ++ if (ret) ++ dev_err(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n"); ++ } else { ++ ret = regmap_read_poll_timeout(udphy->pma_regmap, ++ TRSV_LN2_MON_RX_CDR_DONE_OFFSET, val, ++ val & TRSV_LN2_MON_RX_CDR_LOCK_DONE, ++ 200, 100000); ++ if (ret) ++ dev_err(udphy->dev, "trsv ln2 mon rx cdr lock timeout\n"); ++ } ++ } ++ ++ return 0; ++} ++ ++static int rk_udphy_init(struct rk_udphy *udphy) ++{ ++ const struct rk_udphy_cfg *cfg = udphy->cfgs; ++ int ret; ++ ++ rk_udphy_reset_assert_all(udphy); ++ usleep_range(10000, 11000); ++ ++ /* enable rx lfps for usb */ ++ if (udphy->mode & UDPHY_MODE_USB) ++ rk_udphy_grfreg_write(udphy->udphygrf, &cfg->grfcfg.rx_lfps, true); ++ ++ /* Step 1: power on pma and deassert apb rstn */ ++ rk_udphy_grfreg_write(udphy->udphygrf, &cfg->grfcfg.low_pwrn, true); ++ ++ rk_udphy_reset_deassert(udphy, "pma_apb"); ++ rk_udphy_reset_deassert(udphy, "pcs_apb"); ++ ++ /* Step 2: set init sequence and phy refclk */ ++ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_init_sequence, ++ ARRAY_SIZE(rk_udphy_init_sequence)); ++ if (ret) { ++ dev_err(udphy->dev, "init sequence set error %d\n", ret); ++ goto assert_resets; ++ } ++ ++ ret = rk_udphy_refclk_set(udphy); ++ if (ret) { ++ dev_err(udphy->dev, "refclk set error %d\n", ret); ++ goto assert_resets; ++ } ++ ++ /* Step 3: configure lane mux */ ++ regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, ++ CMN_DP_LANE_MUX_ALL | CMN_DP_LANE_EN_ALL, ++ FIELD_PREP(CMN_DP_LANE_MUX_N(3), udphy->lane_mux_sel[3]) | ++ FIELD_PREP(CMN_DP_LANE_MUX_N(2), udphy->lane_mux_sel[2]) | ++ FIELD_PREP(CMN_DP_LANE_MUX_N(1), udphy->lane_mux_sel[1]) | ++ FIELD_PREP(CMN_DP_LANE_MUX_N(0), udphy->lane_mux_sel[0]) | ++ FIELD_PREP(CMN_DP_LANE_EN_ALL, 0)); ++ ++ /* Step 4: deassert init rstn and wait for 200ns from datasheet */ ++ if (udphy->mode & UDPHY_MODE_USB) ++ rk_udphy_reset_deassert(udphy, "init"); ++ ++ if (udphy->mode & UDPHY_MODE_DP) { ++ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, ++ CMN_DP_INIT_RSTN, ++ FIELD_PREP(CMN_DP_INIT_RSTN, 0x1)); ++ } ++ ++ udelay(1); ++ ++ /* Step 5: deassert cmn/lane rstn */ ++ if (udphy->mode & UDPHY_MODE_USB) { ++ rk_udphy_reset_deassert(udphy, "cmn"); ++ rk_udphy_reset_deassert(udphy, "lane"); ++ } ++ ++ /* Step 6: wait for lock done of pll */ ++ ret = rk_udphy_status_check(udphy); ++ if (ret) ++ goto assert_resets; ++ ++ return 0; ++ ++assert_resets: ++ rk_udphy_reset_assert_all(udphy); ++ return ret; ++} ++ ++static int rk_udphy_setup(struct rk_udphy *udphy) ++{ ++ int ret = 0; ++ ++ ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks); ++ if (ret) { ++ dev_err(udphy->dev, "failed to enable clk\n"); ++ return ret; ++ } ++ ++ ret = rk_udphy_init(udphy); ++ if (ret) { ++ dev_err(udphy->dev, "failed to init combophy\n"); ++ clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void rk_udphy_disable(struct rk_udphy *udphy) ++{ ++ clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks); ++ rk_udphy_reset_assert_all(udphy); ++} ++ ++static int rk_udphy_parse_lane_mux_data(struct rk_udphy *udphy) ++{ ++ int ret, i, num_lanes; ++ ++ num_lanes = device_property_count_u32(udphy->dev, "rockchip,dp-lane-mux"); ++ if (num_lanes < 0) { ++ dev_dbg(udphy->dev, "no dp-lane-mux, following dp alt mode\n"); ++ udphy->mode = UDPHY_MODE_USB; ++ return 0; ++ } ++ ++ if (num_lanes != 2 && num_lanes != 4) ++ return dev_err_probe(udphy->dev, -EINVAL, ++ "invalid number of lane mux\n"); ++ ++ ret = device_property_read_u32_array(udphy->dev, "rockchip,dp-lane-mux", ++ udphy->dp_lane_sel, num_lanes); ++ if (ret) ++ return dev_err_probe(udphy->dev, ret, "get dp lane mux failed\n"); ++ ++ for (i = 0; i < num_lanes; i++) { ++ int j; ++ ++ if (udphy->dp_lane_sel[i] > 3) ++ return dev_err_probe(udphy->dev, -EINVAL, ++ "lane mux between 0 and 3, exceeding the range\n"); ++ ++ udphy->lane_mux_sel[udphy->dp_lane_sel[i]] = PHY_LANE_MUX_DP; ++ ++ for (j = i + 1; j < num_lanes; j++) { ++ if (udphy->dp_lane_sel[i] == udphy->dp_lane_sel[j]) ++ return dev_err_probe(udphy->dev, -EINVAL, ++ "set repeat lane mux value\n"); ++ } ++ } ++ ++ udphy->mode = UDPHY_MODE_DP; ++ if (num_lanes == 2) { ++ udphy->mode |= UDPHY_MODE_USB; ++ udphy->flip = (udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP); ++ } ++ ++ return 0; ++} ++ ++static int rk_udphy_get_initial_status(struct rk_udphy *udphy) ++{ ++ int ret; ++ u32 value; ++ ++ ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks); ++ if (ret) { ++ dev_err(udphy->dev, "failed to enable clk\n"); ++ return ret; ++ } ++ ++ rk_udphy_reset_deassert_all(udphy); ++ ++ regmap_read(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, &value); ++ if (FIELD_GET(CMN_DP_LANE_MUX_ALL, value) && FIELD_GET(CMN_DP_LANE_EN_ALL, value)) ++ udphy->status = UDPHY_MODE_DP; ++ else ++ rk_udphy_disable(udphy); ++ ++ return 0; ++} ++ ++static int rk_udphy_parse_dt(struct rk_udphy *udphy) ++{ ++ struct device *dev = udphy->dev; ++ struct device_node *np = dev_of_node(dev); ++ enum usb_device_speed maximum_speed; ++ int ret; ++ ++ udphy->u2phygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,u2phy-grf"); ++ if (IS_ERR(udphy->u2phygrf)) ++ return dev_err_probe(dev, PTR_ERR(udphy->u2phygrf), "failed to get u2phy-grf\n"); ++ ++ udphy->udphygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbdpphy-grf"); ++ if (IS_ERR(udphy->udphygrf)) ++ return dev_err_probe(dev, PTR_ERR(udphy->udphygrf), "failed to get usbdpphy-grf\n"); ++ ++ udphy->usbgrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usb-grf"); ++ if (IS_ERR(udphy->usbgrf)) ++ return dev_err_probe(dev, PTR_ERR(udphy->usbgrf), "failed to get usb-grf\n"); ++ ++ udphy->vogrf = syscon_regmap_lookup_by_phandle(np, "rockchip,vo-grf"); ++ if (IS_ERR(udphy->vogrf)) ++ return dev_err_probe(dev, PTR_ERR(udphy->vogrf), "failed to get vo-grf\n"); ++ ++ ret = rk_udphy_parse_lane_mux_data(udphy); ++ if (ret) ++ return ret; ++ ++ udphy->sbu1_dc_gpio = devm_gpiod_get_optional(dev, "sbu1-dc", GPIOD_OUT_LOW); ++ if (IS_ERR(udphy->sbu1_dc_gpio)) ++ return PTR_ERR(udphy->sbu1_dc_gpio); ++ ++ udphy->sbu2_dc_gpio = devm_gpiod_get_optional(dev, "sbu2-dc", GPIOD_OUT_LOW); ++ if (IS_ERR(udphy->sbu2_dc_gpio)) ++ return PTR_ERR(udphy->sbu2_dc_gpio); ++ ++ if (device_property_present(dev, "maximum-speed")) { ++ maximum_speed = usb_get_maximum_speed(dev); ++ udphy->hs = maximum_speed <= USB_SPEED_HIGH ? true : false; ++ } ++ ++ ret = rk_udphy_clk_init(udphy, dev); ++ if (ret) ++ return ret; ++ ++ ret = rk_udphy_reset_init(udphy, dev); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode) ++{ ++ int ret; ++ ++ if (!(udphy->mode & mode)) { ++ dev_info(udphy->dev, "mode 0x%02x is not support\n", mode); ++ return 0; ++ } ++ ++ if (udphy->status == UDPHY_MODE_NONE) { ++ udphy->mode_change = false; ++ ret = rk_udphy_setup(udphy); ++ if (ret) ++ return ret; ++ ++ if (udphy->mode & UDPHY_MODE_USB) ++ rk_udphy_u3_port_disable(udphy, false); ++ } else if (udphy->mode_change) { ++ udphy->mode_change = false; ++ udphy->status = UDPHY_MODE_NONE; ++ if (udphy->mode == UDPHY_MODE_DP) ++ rk_udphy_u3_port_disable(udphy, true); ++ ++ rk_udphy_disable(udphy); ++ ret = rk_udphy_setup(udphy); ++ if (ret) ++ return ret; ++ } ++ ++ udphy->status |= mode; ++ ++ return 0; ++} ++ ++static void rk_udphy_power_off(struct rk_udphy *udphy, u8 mode) ++{ ++ if (!(udphy->mode & mode)) { ++ dev_info(udphy->dev, "mode 0x%02x is not support\n", mode); ++ return; ++ } ++ ++ if (!udphy->status) ++ return; ++ ++ udphy->status &= ~mode; ++ ++ if (udphy->status == UDPHY_MODE_NONE) ++ rk_udphy_disable(udphy); ++} ++ ++static int rk_udphy_dp_phy_init(struct phy *phy) ++{ ++ struct rk_udphy *udphy = phy_get_drvdata(phy); ++ ++ mutex_lock(&udphy->mutex); ++ ++ udphy->dp_in_use = true; ++ rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg); ++ ++ mutex_unlock(&udphy->mutex); ++ ++ return 0; ++} ++ ++static int rk_udphy_dp_phy_exit(struct phy *phy) ++{ ++ struct rk_udphy *udphy = phy_get_drvdata(phy); ++ ++ mutex_lock(&udphy->mutex); ++ udphy->dp_in_use = false; ++ mutex_unlock(&udphy->mutex); ++ return 0; ++} ++ ++static int rk_udphy_dp_phy_power_on(struct phy *phy) ++{ ++ struct rk_udphy *udphy = phy_get_drvdata(phy); ++ int ret, dp_lanes; ++ ++ mutex_lock(&udphy->mutex); ++ ++ dp_lanes = rk_udphy_dplane_get(udphy); ++ phy_set_bus_width(phy, dp_lanes); ++ ++ ret = rk_udphy_power_on(udphy, UDPHY_MODE_DP); ++ if (ret) ++ goto unlock; ++ ++ rk_udphy_dplane_enable(udphy, dp_lanes); ++ ++ rk_udphy_dplane_select(udphy); ++ ++unlock: ++ mutex_unlock(&udphy->mutex); ++ /* ++ * If data send by aux channel too fast after phy power on, ++ * the aux may be not ready which will cause aux error. Adding ++ * delay to avoid this issue. ++ */ ++ usleep_range(10000, 11000); ++ return ret; ++} ++ ++static int rk_udphy_dp_phy_power_off(struct phy *phy) ++{ ++ struct rk_udphy *udphy = phy_get_drvdata(phy); ++ ++ mutex_lock(&udphy->mutex); ++ rk_udphy_dplane_enable(udphy, 0); ++ rk_udphy_power_off(udphy, UDPHY_MODE_DP); ++ mutex_unlock(&udphy->mutex); ++ ++ return 0; ++} ++ ++static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate) ++{ ++ switch (link_rate) { ++ case 1620: ++ case 2700: ++ case 5400: ++ case 8100: ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy, ++ struct phy_configure_opts_dp *dp) ++{ ++ int i, ret; ++ ++ /* If changing link rate was required, verify it's supported. */ ++ ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate); ++ if (ret) ++ return ret; ++ ++ /* Verify lane count. */ ++ switch (dp->lanes) { ++ case 1: ++ case 2: ++ case 4: ++ /* valid lane count. */ ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ /* ++ * If changing voltages is required, check swing and pre-emphasis ++ * levels, per-lane. ++ */ ++ if (dp->set_voltages) { ++ /* Lane count verified previously. */ ++ for (i = 0; i < dp->lanes; i++) { ++ if (dp->voltage[i] > 3 || dp->pre[i] > 3) ++ return -EINVAL; ++ ++ /* ++ * Sum of voltage swing and pre-emphasis levels cannot ++ * exceed 3. ++ */ ++ if (dp->voltage[i] + dp->pre[i] > 3) ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++static void rk_udphy_dp_set_voltage(struct rk_udphy *udphy, u8 bw, ++ u32 voltage, u32 pre, u32 lane) ++{ ++ const struct rk_udphy_cfg *cfg = udphy->cfgs; ++ const struct rk_udphy_dp_tx_drv_ctrl (*dp_ctrl)[4]; ++ u32 offset = 0x800 * lane; ++ u32 val; ++ ++ if (udphy->mux) ++ dp_ctrl = cfg->dp_tx_ctrl_cfg_typec[bw]; ++ else ++ dp_ctrl = cfg->dp_tx_ctrl_cfg[bw]; ++ ++ val = dp_ctrl[voltage][pre].trsv_reg0204; ++ regmap_write(udphy->pma_regmap, 0x0810 + offset, val); ++ ++ val = dp_ctrl[voltage][pre].trsv_reg0205; ++ regmap_write(udphy->pma_regmap, 0x0814 + offset, val); ++ ++ val = dp_ctrl[voltage][pre].trsv_reg0206; ++ regmap_write(udphy->pma_regmap, 0x0818 + offset, val); ++ ++ val = dp_ctrl[voltage][pre].trsv_reg0207; ++ regmap_write(udphy->pma_regmap, 0x081c + offset, val); ++} ++ ++static int rk_udphy_dp_phy_configure(struct phy *phy, ++ union phy_configure_opts *opts) ++{ ++ struct rk_udphy *udphy = phy_get_drvdata(phy); ++ struct phy_configure_opts_dp *dp = &opts->dp; ++ u32 i, val, lane; ++ int ret; ++ ++ ret = rk_udphy_dp_phy_verify_config(udphy, dp); ++ if (ret) ++ return ret; ++ ++ if (dp->set_rate) { ++ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, ++ CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); ++ ++ switch (dp->link_rate) { ++ case 1620: ++ udphy->bw = DP_BW_RBR; ++ break; ++ ++ case 2700: ++ udphy->bw = DP_BW_HBR; ++ break; ++ ++ case 5400: ++ udphy->bw = DP_BW_HBR2; ++ break; ++ ++ case 8100: ++ udphy->bw = DP_BW_HBR3; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ regmap_update_bits(udphy->pma_regmap, CMN_DP_LINK_OFFSET, CMN_DP_TX_LINK_BW, ++ FIELD_PREP(CMN_DP_TX_LINK_BW, udphy->bw)); ++ regmap_update_bits(udphy->pma_regmap, CMN_SSC_EN_OFFSET, CMN_ROPLL_SSC_EN, ++ FIELD_PREP(CMN_ROPLL_SSC_EN, dp->ssc)); ++ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, CMN_DP_CMN_RSTN, ++ FIELD_PREP(CMN_DP_CMN_RSTN, 0x1)); ++ ++ ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_ROPLL_DONE_OFFSET, val, ++ FIELD_GET(CMN_ANA_ROPLL_LOCK_DONE, val) && ++ FIELD_GET(CMN_ANA_ROPLL_AFC_DONE, val), ++ 0, 1000); ++ if (ret) { ++ dev_err(udphy->dev, "ROPLL is not lock, set_rate failed\n"); ++ return ret; ++ } ++ } ++ ++ if (dp->set_voltages) { ++ for (i = 0; i < dp->lanes; i++) { ++ lane = udphy->dp_lane_sel[i]; ++ switch (dp->link_rate) { ++ case 1620: ++ case 2700: ++ regmap_update_bits(udphy->pma_regmap, ++ TRSV_ANA_TX_CLK_OFFSET_N(lane), ++ LN_ANA_TX_SER_TXCLK_INV, ++ FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, ++ udphy->lane_mux_sel[lane])); ++ break; ++ ++ case 5400: ++ case 8100: ++ regmap_update_bits(udphy->pma_regmap, ++ TRSV_ANA_TX_CLK_OFFSET_N(lane), ++ LN_ANA_TX_SER_TXCLK_INV, ++ FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, 0x0)); ++ break; ++ } ++ ++ rk_udphy_dp_set_voltage(udphy, udphy->bw, dp->voltage[i], ++ dp->pre[i], lane); ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct phy_ops rk_udphy_dp_phy_ops = { ++ .init = rk_udphy_dp_phy_init, ++ .exit = rk_udphy_dp_phy_exit, ++ .power_on = rk_udphy_dp_phy_power_on, ++ .power_off = rk_udphy_dp_phy_power_off, ++ .configure = rk_udphy_dp_phy_configure, ++ .owner = THIS_MODULE, ++}; ++ ++static int rk_udphy_usb3_phy_init(struct phy *phy) ++{ ++ struct rk_udphy *udphy = phy_get_drvdata(phy); ++ int ret = 0; ++ ++ mutex_lock(&udphy->mutex); ++ /* DP only or high-speed, disable U3 port */ ++ if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) { ++ rk_udphy_u3_port_disable(udphy, true); ++ goto unlock; ++ } ++ ++ ret = rk_udphy_power_on(udphy, UDPHY_MODE_USB); ++ ++unlock: ++ mutex_unlock(&udphy->mutex); ++ return ret; ++} ++ ++static int rk_udphy_usb3_phy_exit(struct phy *phy) ++{ ++ struct rk_udphy *udphy = phy_get_drvdata(phy); ++ ++ mutex_lock(&udphy->mutex); ++ /* DP only or high-speed */ ++ if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) ++ goto unlock; ++ ++ rk_udphy_power_off(udphy, UDPHY_MODE_USB); ++ ++unlock: ++ mutex_unlock(&udphy->mutex); ++ return 0; ++} ++ ++static const struct phy_ops rk_udphy_usb3_phy_ops = { ++ .init = rk_udphy_usb3_phy_init, ++ .exit = rk_udphy_usb3_phy_exit, ++ .owner = THIS_MODULE, ++}; ++ ++static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux, ++ struct typec_mux_state *state) ++{ ++ struct rk_udphy *udphy = typec_mux_get_drvdata(mux); ++ u8 mode; ++ ++ mutex_lock(&udphy->mutex); ++ ++ switch (state->mode) { ++ case TYPEC_DP_STATE_C: ++ case TYPEC_DP_STATE_E: ++ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; ++ mode = UDPHY_MODE_DP; ++ break; ++ ++ case TYPEC_DP_STATE_D: ++ default: ++ if (udphy->flip) { ++ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB; ++ } else { ++ udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; ++ } ++ mode = UDPHY_MODE_DP_USB; ++ break; ++ } ++ ++ if (state->alt && state->alt->svid == USB_TYPEC_DP_SID) { ++ struct typec_displayport_data *data = state->data; ++ ++ if (!data) { ++ rk_udphy_dp_hpd_event_trigger(udphy, false); ++ } else if (data->status & DP_STATUS_IRQ_HPD) { ++ rk_udphy_dp_hpd_event_trigger(udphy, false); ++ usleep_range(750, 800); ++ rk_udphy_dp_hpd_event_trigger(udphy, true); ++ } else if (data->status & DP_STATUS_HPD_STATE) { ++ if (udphy->mode != mode) { ++ udphy->mode = mode; ++ udphy->mode_change = true; ++ } ++ rk_udphy_dp_hpd_event_trigger(udphy, true); ++ } else { ++ rk_udphy_dp_hpd_event_trigger(udphy, false); ++ } ++ } ++ ++ mutex_unlock(&udphy->mutex); ++ return 0; ++} ++ ++static void rk_udphy_typec_mux_unregister(void *data) ++{ ++ struct rk_udphy *udphy = data; ++ ++ typec_mux_unregister(udphy->mux); ++} ++ ++static int rk_udphy_setup_typec_mux(struct rk_udphy *udphy) ++{ ++ struct typec_mux_desc mux_desc = {}; ++ ++ mux_desc.drvdata = udphy; ++ mux_desc.fwnode = dev_fwnode(udphy->dev); ++ mux_desc.set = rk_udphy_typec_mux_set; ++ ++ udphy->mux = typec_mux_register(udphy->dev, &mux_desc); ++ if (IS_ERR(udphy->mux)) { ++ dev_err(udphy->dev, "Error register typec mux: %ld\n", ++ PTR_ERR(udphy->mux)); ++ return PTR_ERR(udphy->mux); ++ } ++ ++ return devm_add_action_or_reset(udphy->dev, rk_udphy_typec_mux_unregister, ++ udphy); ++} ++ ++static const struct regmap_config rk_udphy_pma_regmap_cfg = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .fast_io = true, ++ .max_register = 0x20dc, ++}; ++ ++static struct phy *rk_udphy_phy_xlate(struct device *dev, struct of_phandle_args *args) ++{ ++ struct rk_udphy *udphy = dev_get_drvdata(dev); ++ ++ if (args->args_count == 0) ++ return ERR_PTR(-EINVAL); ++ ++ switch (args->args[0]) { ++ case PHY_TYPE_USB3: ++ return udphy->phy_u3; ++ case PHY_TYPE_DP: ++ return udphy->phy_dp; ++ } ++ ++ return ERR_PTR(-EINVAL); ++} ++ ++static int rk_udphy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy_provider *phy_provider; ++ struct resource *res; ++ struct rk_udphy *udphy; ++ void __iomem *base; ++ int id, ret; ++ ++ udphy = devm_kzalloc(dev, sizeof(*udphy), GFP_KERNEL); ++ if (!udphy) ++ return -ENOMEM; ++ ++ udphy->cfgs = device_get_match_data(dev); ++ if (!udphy->cfgs) ++ return dev_err_probe(dev, -EINVAL, "missing match data\n"); ++ ++ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ /* find the phy-id from the io address */ ++ udphy->id = -ENODEV; ++ for (id = 0; id < udphy->cfgs->num_phys; id++) { ++ if (res->start == udphy->cfgs->phy_ids[id]) { ++ udphy->id = id; ++ break; ++ } ++ } ++ ++ if (udphy->id < 0) ++ return dev_err_probe(dev, -ENODEV, "no matching device found\n"); ++ ++ udphy->pma_regmap = devm_regmap_init_mmio(dev, base + UDPHY_PMA, ++ &rk_udphy_pma_regmap_cfg); ++ if (IS_ERR(udphy->pma_regmap)) ++ return PTR_ERR(udphy->pma_regmap); ++ ++ udphy->dev = dev; ++ ret = rk_udphy_parse_dt(udphy); ++ if (ret) ++ return ret; ++ ++ ret = rk_udphy_get_initial_status(udphy); ++ if (ret) ++ return ret; ++ ++ mutex_init(&udphy->mutex); ++ platform_set_drvdata(pdev, udphy); ++ ++ if (device_property_present(dev, "orientation-switch")) { ++ ret = rk_udphy_setup_orien_switch(udphy); ++ if (ret) ++ return ret; ++ } ++ ++ if (device_property_present(dev, "mode-switch")) { ++ ret = rk_udphy_setup_typec_mux(udphy); ++ if (ret) ++ return ret; ++ } ++ ++ udphy->phy_u3 = devm_phy_create(dev, dev->of_node, &rk_udphy_usb3_phy_ops); ++ if (IS_ERR(udphy->phy_u3)) { ++ ret = PTR_ERR(udphy->phy_u3); ++ return dev_err_probe(dev, ret, "failed to create USB3 phy\n"); ++ } ++ phy_set_drvdata(udphy->phy_u3, udphy); ++ ++ udphy->phy_dp = devm_phy_create(dev, dev->of_node, &rk_udphy_dp_phy_ops); ++ if (IS_ERR(udphy->phy_dp)) { ++ ret = PTR_ERR(udphy->phy_dp); ++ return dev_err_probe(dev, ret, "failed to create DP phy\n"); ++ } ++ phy_set_bus_width(udphy->phy_dp, rk_udphy_dplane_get(udphy)); ++ udphy->phy_dp->attrs.max_link_rate = 8100; ++ phy_set_drvdata(udphy->phy_dp, udphy); ++ ++ phy_provider = devm_of_phy_provider_register(dev, rk_udphy_phy_xlate); ++ if (IS_ERR(phy_provider)) { ++ ret = PTR_ERR(phy_provider); ++ return dev_err_probe(dev, ret, "failed to register phy provider\n"); ++ } ++ ++ return 0; ++} ++ ++static int __maybe_unused rk_udphy_resume(struct device *dev) ++{ ++ struct rk_udphy *udphy = dev_get_drvdata(dev); ++ ++ if (udphy->dp_sink_hpd_sel) ++ rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops rk_udphy_pm_ops = { ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, rk_udphy_resume) ++}; ++ ++static const char * const rk_udphy_rst_list[] = { ++ "init", "cmn", "lane", "pcs_apb", "pma_apb" ++}; ++ ++static const struct rk_udphy_cfg rk3588_udphy_cfgs = { ++ .num_phys = 2, ++ .phy_ids = { ++ 0xfed80000, ++ 0xfed90000, ++ }, ++ .num_rsts = ARRAY_SIZE(rk_udphy_rst_list), ++ .rst_list = rk_udphy_rst_list, ++ .grfcfg = { ++ /* u2phy-grf */ ++ .bvalid_phy_con = RK_UDPHY_GEN_GRF_REG(0x0008, 1, 0, 0x2, 0x3), ++ .bvalid_grf_con = RK_UDPHY_GEN_GRF_REG(0x0010, 3, 2, 0x2, 0x3), ++ ++ /* usb-grf */ ++ .usb3otg0_cfg = RK_UDPHY_GEN_GRF_REG(0x001c, 15, 0, 0x1100, 0x0188), ++ .usb3otg1_cfg = RK_UDPHY_GEN_GRF_REG(0x0034, 15, 0, 0x1100, 0x0188), ++ ++ /* usbdpphy-grf */ ++ .low_pwrn = RK_UDPHY_GEN_GRF_REG(0x0004, 13, 13, 0, 1), ++ .rx_lfps = RK_UDPHY_GEN_GRF_REG(0x0004, 14, 14, 0, 1), ++ }, ++ .vogrfcfg = { ++ { ++ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0000, 11, 10, 1, 3), ++ .dp_lane_reg = 0x0000, ++ }, ++ { ++ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0008, 11, 10, 1, 3), ++ .dp_lane_reg = 0x0008, ++ }, ++ }, ++ .dp_tx_ctrl_cfg = { ++ rk3588_dp_tx_drv_ctrl_rbr_hbr, ++ rk3588_dp_tx_drv_ctrl_rbr_hbr, ++ rk3588_dp_tx_drv_ctrl_hbr2, ++ rk3588_dp_tx_drv_ctrl_hbr3, ++ }, ++ .dp_tx_ctrl_cfg_typec = { ++ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec, ++ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec, ++ rk3588_dp_tx_drv_ctrl_hbr2, ++ rk3588_dp_tx_drv_ctrl_hbr3, ++ }, ++}; ++ ++static const struct of_device_id rk_udphy_dt_match[] = { ++ { ++ .compatible = "rockchip,rk3588-usbdp-phy", ++ .data = &rk3588_udphy_cfgs ++ }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, rk_udphy_dt_match); ++ ++static struct platform_driver rk_udphy_driver = { ++ .probe = rk_udphy_probe, ++ .driver = { ++ .name = "rockchip-usbdp-phy", ++ .of_match_table = rk_udphy_dt_match, ++ .pm = &rk_udphy_pm_ops, ++ }, ++}; ++module_platform_driver(rk_udphy_driver); ++ ++MODULE_AUTHOR("Frank Wang "); ++MODULE_AUTHOR("Zhang Yubing "); ++MODULE_DESCRIPTION("Rockchip USBDP Combo PHY driver"); ++MODULE_LICENSE("GPL"); +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Fri, 16 Feb 2024 18:01:18 +0100 +Subject: arm64: defconfig: enable Rockchip Samsung USBDP PHY + +The USBDP Phy is used by RK3588 to handle the Dual-Role USB3 +controllers. The Phy also supports Displayport Alt-Mode, but +the necessary DRM driver has not yet been merged. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/configs/defconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig +index 111111111111..222222222222 100644 +--- a/arch/arm64/configs/defconfig ++++ b/arch/arm64/configs/defconfig +@@ -1492,6 +1492,7 @@ CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=m + CONFIG_PHY_ROCKCHIP_PCIE=m + CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=y + CONFIG_PHY_ROCKCHIP_TYPEC=y ++CONFIG_PHY_ROCKCHIP_USBDP=m + CONFIG_PHY_SAMSUNG_UFS=y + CONFIG_PHY_UNIPHIER_USB2=y + CONFIG_PHY_UNIPHIER_USB3=y +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Fri, 16 Feb 2024 18:01:19 +0100 +Subject: arm64: dts: rockchip: fix usb2phy nodename for rk3588 + +usb2-phy should be named usb2phy according to the DT binding, +so let's fix it up accordingly. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -542,7 +542,7 @@ usb2phy2_grf: syscon@fd5d8000 { + #address-cells = <1>; + #size-cells = <1>; + +- u2phy2: usb2-phy@8000 { ++ u2phy2: usb2phy@8000 { + compatible = "rockchip,rk3588-usb2phy"; + reg = <0x8000 0x10>; + interrupts = ; +@@ -567,7 +567,7 @@ usb2phy3_grf: syscon@fd5dc000 { + #address-cells = <1>; + #size-cells = <1>; + +- u2phy3: usb2-phy@c000 { ++ u2phy3: usb2phy@c000 { + compatible = "rockchip,rk3588-usb2phy"; + reg = <0xc000 0x10>; + interrupts = ; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Fri, 16 Feb 2024 18:01:20 +0100 +Subject: arm64: dts: rockchip: reorder usb2phy properties for rk3588 + +Reorder common DT properties alphabetically for usb2phy, according +to latest DT style rules. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 16 +++++----- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -545,13 +545,13 @@ usb2phy2_grf: syscon@fd5d8000 { + u2phy2: usb2phy@8000 { + compatible = "rockchip,rk3588-usb2phy"; + reg = <0x8000 0x10>; +- interrupts = ; +- resets = <&cru SRST_OTGPHY_U2_0>, <&cru SRST_P_USB2PHY_U2_0_GRF0>; +- reset-names = "phy", "apb"; ++ #clock-cells = <0>; + clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; + clock-names = "phyclk"; + clock-output-names = "usb480m_phy2"; +- #clock-cells = <0>; ++ interrupts = ; ++ resets = <&cru SRST_OTGPHY_U2_0>, <&cru SRST_P_USB2PHY_U2_0_GRF0>; ++ reset-names = "phy", "apb"; + status = "disabled"; + + u2phy2_host: host-port { +@@ -570,13 +570,13 @@ usb2phy3_grf: syscon@fd5dc000 { + u2phy3: usb2phy@c000 { + compatible = "rockchip,rk3588-usb2phy"; + reg = <0xc000 0x10>; +- interrupts = ; +- resets = <&cru SRST_OTGPHY_U2_1>, <&cru SRST_P_USB2PHY_U2_1_GRF0>; +- reset-names = "phy", "apb"; ++ #clock-cells = <0>; + clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; + clock-names = "phyclk"; + clock-output-names = "usb480m_phy3"; +- #clock-cells = <0>; ++ interrupts = ; ++ resets = <&cru SRST_OTGPHY_U2_1>, <&cru SRST_P_USB2PHY_U2_1_GRF0>; ++ reset-names = "phy", "apb"; + status = "disabled"; + + u2phy3_host: host-port { +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Fri, 16 Feb 2024 18:01:21 +0100 +Subject: arm64: dts: rockchip: add USBDP phys on rk3588 + +Add both USB3-DisplayPort PHYs to RK3588 SoC DT. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588.dtsi | 52 ++++++++ + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 63 ++++++++++ + 2 files changed, 115 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588.dtsi b/arch/arm64/boot/dts/rockchip/rk3588.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi +@@ -17,6 +17,36 @@ pipe_phy1_grf: syscon@fd5c0000 { + reg = <0x0 0xfd5c0000 0x0 0x100>; + }; + ++ usbdpphy1_grf: syscon@fd5cc000 { ++ compatible = "rockchip,rk3588-usbdpphy-grf", "syscon"; ++ reg = <0x0 0xfd5cc000 0x0 0x4000>; ++ }; ++ ++ usb2phy1_grf: syscon@fd5d4000 { ++ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd"; ++ reg = <0x0 0xfd5d4000 0x0 0x4000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ u2phy1: usb2phy@4000 { ++ compatible = "rockchip,rk3588-usb2phy"; ++ reg = <0x4000 0x10>; ++ #clock-cells = <0>; ++ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; ++ clock-names = "phyclk"; ++ clock-output-names = "usb480m_phy1"; ++ interrupts = ; ++ resets = <&cru SRST_OTGPHY_U3_1>, <&cru SRST_P_USB2PHY_U3_1_GRF0>; ++ reset-names = "phy", "apb"; ++ status = "disabled"; ++ ++ u2phy1_otg: otg-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ + i2s8_8ch: i2s@fddc8000 { + compatible = "rockchip,rk3588-i2s-tdm"; + reg = <0x0 0xfddc8000 0x0 0x1000>; +@@ -310,6 +340,28 @@ sata-port@0 { + }; + }; + ++ usbdp_phy1: phy@fed90000 { ++ compatible = "rockchip,rk3588-usbdp-phy"; ++ reg = <0x0 0xfed90000 0x0 0x10000>; ++ #phy-cells = <1>; ++ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>, ++ <&cru CLK_USBDP_PHY1_IMMORTAL>, ++ <&cru PCLK_USBDPPHY1>, ++ <&u2phy1>; ++ clock-names = "refclk", "immortal", "pclk", "utmi"; ++ resets = <&cru SRST_USBDP_COMBO_PHY1_INIT>, ++ <&cru SRST_USBDP_COMBO_PHY1_CMN>, ++ <&cru SRST_USBDP_COMBO_PHY1_LANE>, ++ <&cru SRST_USBDP_COMBO_PHY1_PCS>, ++ <&cru SRST_P_USBDPPHY1>; ++ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb"; ++ rockchip,u2phy-grf = <&usb2phy1_grf>; ++ rockchip,usb-grf = <&usb_grf>; ++ rockchip,usbdpphy-grf = <&usbdpphy1_grf>; ++ rockchip,vo-grf = <&vo0_grf>; ++ status = "disabled"; ++ }; ++ + combphy1_ps: phy@fee10000 { + compatible = "rockchip,rk3588-naneng-combphy"; + reg = <0x0 0xfee10000 0x0 0x100>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -516,11 +516,22 @@ vop_grf: syscon@fd5a4000 { + reg = <0x0 0xfd5a4000 0x0 0x2000>; + }; + ++ vo0_grf: syscon@fd5a6000 { ++ compatible = "rockchip,rk3588-vo-grf", "syscon"; ++ reg = <0x0 0xfd5a6000 0x0 0x2000>; ++ clocks = <&cru PCLK_VO0GRF>; ++ }; ++ + vo1_grf: syscon@fd5a8000 { + compatible = "rockchip,rk3588-vo-grf", "syscon"; + reg = <0x0 0xfd5a8000 0x0 0x100>; + }; + ++ usb_grf: syscon@fd5ac000 { ++ compatible = "rockchip,rk3588-usb-grf", "syscon"; ++ reg = <0x0 0xfd5ac000 0x0 0x4000>; ++ }; ++ + php_grf: syscon@fd5b0000 { + compatible = "rockchip,rk3588-php-grf", "syscon"; + reg = <0x0 0xfd5b0000 0x0 0x1000>; +@@ -536,6 +547,36 @@ pipe_phy2_grf: syscon@fd5c4000 { + reg = <0x0 0xfd5c4000 0x0 0x100>; + }; + ++ usbdpphy0_grf: syscon@fd5c8000 { ++ compatible = "rockchip,rk3588-usbdpphy-grf", "syscon"; ++ reg = <0x0 0xfd5c8000 0x0 0x4000>; ++ }; ++ ++ usb2phy0_grf: syscon@fd5d0000 { ++ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd"; ++ reg = <0x0 0xfd5d0000 0x0 0x4000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ u2phy0: usb2phy@0 { ++ compatible = "rockchip,rk3588-usb2phy"; ++ reg = <0x0 0x10>; ++ #clock-cells = <0>; ++ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; ++ clock-names = "phyclk"; ++ clock-output-names = "usb480m_phy0"; ++ interrupts = ; ++ resets = <&cru SRST_OTGPHY_U3_0>, <&cru SRST_P_USB2PHY_U3_0_GRF0>; ++ reset-names = "phy", "apb"; ++ status = "disabled"; ++ ++ u2phy0_otg: otg-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ + usb2phy2_grf: syscon@fd5d8000 { + compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd"; + reg = <0x0 0xfd5d8000 0x0 0x4000>; +@@ -2358,6 +2399,28 @@ dmac2: dma-controller@fed10000 { + #dma-cells = <1>; + }; + ++ usbdp_phy0: phy@fed80000 { ++ compatible = "rockchip,rk3588-usbdp-phy"; ++ reg = <0x0 0xfed80000 0x0 0x10000>; ++ #phy-cells = <1>; ++ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>, ++ <&cru CLK_USBDP_PHY0_IMMORTAL>, ++ <&cru PCLK_USBDPPHY0>, ++ <&u2phy0>; ++ clock-names = "refclk", "immortal", "pclk", "utmi"; ++ resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>, ++ <&cru SRST_USBDP_COMBO_PHY0_CMN>, ++ <&cru SRST_USBDP_COMBO_PHY0_LANE>, ++ <&cru SRST_USBDP_COMBO_PHY0_PCS>, ++ <&cru SRST_P_USBDPPHY0>; ++ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb"; ++ rockchip,u2phy-grf = <&usb2phy0_grf>; ++ rockchip,usb-grf = <&usb_grf>; ++ rockchip,usbdpphy-grf = <&usbdpphy0_grf>; ++ rockchip,vo-grf = <&vo0_grf>; ++ status = "disabled"; ++ }; ++ + combphy0_ps: phy@fee00000 { + compatible = "rockchip,rk3588-naneng-combphy"; + reg = <0x0 0xfee00000 0x0 0x100>; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Fri, 16 Feb 2024 18:01:22 +0100 +Subject: arm64: dts: rockchip: add USB3 DRD controllers on rk3588 + +Add both USB3 dual-role controllers to the RK3588 devicetree. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588.dtsi | 20 +++++++++ + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 22 ++++++++++ + 2 files changed, 42 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588.dtsi b/arch/arm64/boot/dts/rockchip/rk3588.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi +@@ -7,6 +7,26 @@ + #include "rk3588-pinctrl.dtsi" + + / { ++ usb_host1_xhci: usb@fc400000 { ++ compatible = "rockchip,rk3588-dwc3", "snps,dwc3"; ++ reg = <0x0 0xfc400000 0x0 0x400000>; ++ interrupts = ; ++ clocks = <&cru REF_CLK_USB3OTG1>, <&cru SUSPEND_CLK_USB3OTG1>, ++ <&cru ACLK_USB3OTG1>; ++ clock-names = "ref_clk", "suspend_clk", "bus_clk"; ++ dr_mode = "otg"; ++ phys = <&u2phy1_otg>, <&usbdp_phy1 PHY_TYPE_USB3>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ phy_type = "utmi_wide"; ++ power-domains = <&power RK3588_PD_USB>; ++ resets = <&cru SRST_A_USB3OTG1>; ++ snps,dis_enblslpm_quirk; ++ snps,dis-u2-freeclk-exists-quirk; ++ snps,dis-del-phy-power-chg-quirk; ++ snps,dis-tx-ipgap-linecheck-quirk; ++ status = "disabled"; ++ }; ++ + pcie30_phy_grf: syscon@fd5b8000 { + compatible = "rockchip,rk3588-pcie3-phy-grf", "syscon"; + reg = <0x0 0xfd5b8000 0x0 0x10000>; +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -436,6 +436,28 @@ scmi_shmem: sram@0 { + }; + }; + ++ usb_host0_xhci: usb@fc000000 { ++ compatible = "rockchip,rk3588-dwc3", "snps,dwc3"; ++ reg = <0x0 0xfc000000 0x0 0x400000>; ++ interrupts = ; ++ clocks = <&cru REF_CLK_USB3OTG0>, <&cru SUSPEND_CLK_USB3OTG0>, ++ <&cru ACLK_USB3OTG0>; ++ clock-names = "ref_clk", "suspend_clk", "bus_clk"; ++ dr_mode = "otg"; ++ phys = <&u2phy0_otg>, <&usbdp_phy0 PHY_TYPE_USB3>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ phy_type = "utmi_wide"; ++ power-domains = <&power RK3588_PD_USB>; ++ resets = <&cru SRST_A_USB3OTG0>; ++ snps,dis_enblslpm_quirk; ++ snps,dis-u1-entry-quirk; ++ snps,dis-u2-entry-quirk; ++ snps,dis-u2-freeclk-exists-quirk; ++ snps,dis-del-phy-power-chg-quirk; ++ snps,dis-tx-ipgap-linecheck-quirk; ++ status = "disabled"; ++ }; ++ + usb_host0_ehci: usb@fc800000 { + compatible = "rockchip,rk3588-ehci", "generic-ehci"; + reg = <0x0 0xfc800000 0x0 0x40000>; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Fri, 16 Feb 2024 18:01:23 +0100 +Subject: arm64: dts: rockchip: add USB3 to rk3588-evb1 + +Add support for the board's USB3 connectors. It has 1x USB Type-A +and 1x USB Type-C. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts | 143 ++++++++++ + 1 file changed, 143 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include "rk3588.dtsi" + + / { +@@ -224,6 +225,18 @@ vcc5v0_usb: vcc5v0-usb-regulator { + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usbdcin>; + }; ++ ++ vbus5v0_typec: vbus5v0-typec { ++ compatible = "regulator-fixed"; ++ regulator-name = "vbus5v0_typec"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&gpio4 RK_PD0 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&vcc5v0_usb>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&typec5v_pwren>; ++ }; + }; + + &combphy0_ps { +@@ -284,6 +297,56 @@ &gmac0_rgmii_clk + &i2c2 { + status = "okay"; + ++ usbc0: usb-typec@22 { ++ compatible = "fcs,fusb302"; ++ reg = <0x22>; ++ interrupt-parent = <&gpio3>; ++ interrupts = ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usbc0_int>; ++ vbus-supply = <&vbus5v0_typec>; ++ status = "okay"; ++ ++ usb_con: connector { ++ compatible = "usb-c-connector"; ++ label = "USB-C"; ++ data-role = "dual"; ++ power-role = "dual"; ++ try-power-role = "source"; ++ op-sink-microwatt = <1000000>; ++ sink-pdos = ++ ; ++ source-pdos = ++ ; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ usbc0_orien_sw: endpoint { ++ remote-endpoint = <&usbdp_phy0_orientation_switch>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ usbc0_role_sw: endpoint { ++ remote-endpoint = <&dwc3_0_role_switch>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ dp_altmode_mux: endpoint { ++ remote-endpoint = <&usbdp_phy0_dp_altmode_mux>; ++ }; ++ }; ++ }; ++ }; ++ }; ++ + hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; +@@ -410,6 +473,16 @@ vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; ++ ++ usb-typec { ++ usbc0_int: usbc0-int { ++ rockchip,pins = <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ typec5v_pwren: typec5v-pwren { ++ rockchip,pins = <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; + }; + + &pwm2 { +@@ -1041,6 +1114,22 @@ &sata0 { + status = "okay"; + }; + ++&u2phy0 { ++ status = "okay"; ++}; ++ ++&u2phy0_otg { ++ status = "okay"; ++}; ++ ++&u2phy1 { ++ status = "okay"; ++}; ++ ++&u2phy1_otg { ++ status = "okay"; ++}; ++ + &u2phy2 { + status = "okay"; + }; +@@ -1079,3 +1168,57 @@ &usb_host1_ehci { + &usb_host1_ohci { + status = "okay"; + }; ++ ++&usbdp_phy0 { ++ orientation-switch; ++ mode-switch; ++ sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>; ++ sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ usbdp_phy0_orientation_switch: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&usbc0_orien_sw>; ++ }; ++ ++ usbdp_phy0_dp_altmode_mux: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&dp_altmode_mux>; ++ }; ++ }; ++}; ++ ++&usbdp_phy1 { ++ /* ++ * USBDP PHY1 is wired to a female USB3 Type-A connector. Additionally ++ * the differential pairs 2+3 and the aux channel are wired to a RTD2166, ++ * which converts the DP signal into VGA. This is exposed on the ++ * board via a female VGA connector. ++ */ ++ rockchip,dp-lane-mux = <2 3>; ++ status = "okay"; ++}; ++ ++&usb_host0_xhci { ++ dr_mode = "otg"; ++ usb-role-switch; ++ status = "okay"; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ dwc3_0_role_switch: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&usbc0_role_sw>; ++ }; ++ }; ++}; ++ ++&usb_host1_xhci { ++ dr_mode = "host"; ++ status = "okay"; ++}; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Fri, 28 Jul 2023 16:43:16 +0200 +Subject: usb: typec: tcpm: avoid graph warning + +When using a devicetree as described in commit d56de8c9a17d ("usb: +typec: tcpm: try to get role switch from tcpc fwnode"), the kernel +will print an error when probing the TCPM driver, which looks +similar to this: + +OF: graph: no port node found in /i2c@feac0000/usb-typec@22 + +This is a false positive, since the code first tries to find a ports +node for the device and only then checks the fwnode. Fix this by +swapping the order. + +Note, that this will now generate a error message for devicetrees with +a role-switch ports node directly in the TCPM node instead of in the +connectors sub-node, before falling back to the legacy behaviour. These +devicetrees generate warnings when being checked against the bindings, +and should be fixed. + +Fixes: d56de8c9a17d ("usb: typec: tcpm: try to get role switch from tcpc fwnode") +Signed-off-by: Sebastian Reichel +--- + drivers/usb/typec/tcpm/tcpm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c +index 111111111111..222222222222 100644 +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -6851,9 +6851,9 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) + + port->partner_desc.identity = &port->partner_ident; + +- port->role_sw = usb_role_switch_get(port->dev); ++ port->role_sw = fwnode_usb_role_switch_get(tcpc->fwnode); + if (!port->role_sw) +- port->role_sw = fwnode_usb_role_switch_get(tcpc->fwnode); ++ port->role_sw = usb_role_switch_get(port->dev); + if (IS_ERR(port->role_sw)) { + err = PTR_ERR(port->role_sw); + goto out_destroy_wq; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Fri, 16 Feb 2024 18:01:24 +0100 +Subject: arm64: dts: rockchip: add upper USB3 port to rock-5a + +Enable full support (XHCI, EHCI, OHCI) for the upper USB3 port from +Radxa Rock 5 Model A. The lower one is already supported. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 18 ++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +@@ -698,6 +698,14 @@ regulator-state-mem { + }; + }; + ++&u2phy0 { ++ status = "okay"; ++}; ++ ++&u2phy0_otg { ++ status = "okay"; ++}; ++ + &u2phy2 { + status = "okay"; + }; +@@ -721,6 +729,11 @@ &uart2 { + status = "okay"; + }; + ++&usbdp_phy0 { ++ status = "okay"; ++ rockchip,dp-lane-mux = <2 3>; ++}; ++ + &usb_host0_ehci { + status = "okay"; + pinctrl-names = "default"; +@@ -731,6 +744,11 @@ &usb_host0_ohci { + status = "okay"; + }; + ++&usb_host0_xhci { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ + &usb_host1_ehci { + status = "okay"; + }; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Fri, 16 Feb 2024 18:01:25 +0100 +Subject: arm64: dts: rockchip: add lower USB3 port to rock-5b + +Enable full support (XHCI, EHCI, OHCI) for the lower USB3 port from +Radxa Rock 5 Model B. The upper one is already supported. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 17 ++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -736,6 +736,14 @@ &uart2 { + status = "okay"; + }; + ++&u2phy1 { ++ status = "okay"; ++}; ++ ++&u2phy1_otg { ++ status = "okay"; ++}; ++ + &u2phy2 { + status = "okay"; + }; +@@ -755,6 +763,10 @@ &u2phy3_host { + status = "okay"; + }; + ++&usbdp_phy1 { ++ status = "okay"; ++}; ++ + &usb_host0_ehci { + status = "okay"; + }; +@@ -771,6 +783,11 @@ &usb_host1_ohci { + status = "okay"; + }; + ++&usb_host1_xhci { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ + &usb_host2_xhci { + status = "okay"; + }; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0022-RK3588-Add-Cpufreq-Support.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0022-RK3588-Add-Cpufreq-Support.patch new file mode 100644 index 000000000000..8fbc5a357cc3 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0022-RK3588-Add-Cpufreq-Support.patch @@ -0,0 +1,626 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexey Charkov +Date: Thu, 29 Feb 2024 23:26:32 +0400 +Subject: arm64: dts: rockchip: enable built-in thermal monitoring on RK3588 + +Include thermal zones information in device tree for RK3588 variants. + +This also enables the TSADC controller unconditionally on all boards +to ensure that thermal protections are in place via throttling and +emergency reset, once OPPs are added to enable CPU DVFS. + +The default settings (using CRU as the emergency reset mechanism) +should work on all boards regardless of their wiring, as CRU resets +do not depend on any external components. Boards that have the TSHUT +signal wired to the reset line of the PMIC may opt to switch to GPIO +tshut mode instead (rockchip,hw-tshut-mode = <1>;) + +It seems though that downstream kernels don't use that, even for +those boards where the wiring allows for GPIO based tshut, such as +Radxa Rock 5B [1], [2], [3] + +[1] https://github.com/radxa/kernel/blob/stable-5.10-rock5/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts#L540 +[2] https://github.com/radxa/kernel/blob/stable-5.10-rock5/arch/arm64/boot/dts/rockchip/rk3588s.dtsi#L5433 +[3] https://dl.radxa.com/rock5/5b/docs/hw/radxa_rock_5b_v1423_sch.pdf page 11 (TSADC_SHUT_H) + +Signed-off-by: Alexey Charkov +Link: https://lore.kernel.org/r/20240229-rk-dts-additions-v3-1-6afe8473a631@gmail.com +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 176 +++++++++- + 1 file changed, 175 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + / { + compatible = "rockchip,rk3588"; +@@ -2286,7 +2287,180 @@ tsadc: tsadc@fec00000 { + pinctrl-1 = <&tsadc_shut>; + pinctrl-names = "gpio", "otpout"; + #thermal-sensor-cells = <1>; +- status = "disabled"; ++ status = "okay"; ++ }; ++ ++ thermal_zones: thermal-zones { ++ /* sensor near the center of the SoC */ ++ package_thermal: package-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 0>; ++ ++ trips { ++ package_crit: package-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ /* sensor between A76 cores 0 and 1 */ ++ bigcore0_thermal: bigcore0-thermal { ++ polling-delay-passive = <100>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 1>; ++ ++ trips { ++ /* threshold to start collecting temperature ++ * statistics e.g. with the IPA governor ++ */ ++ bigcore0_alert0: bigcore0-alert0 { ++ temperature = <75000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ /* actual control temperature */ ++ bigcore0_alert1: bigcore0-alert1 { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ bigcore0_crit: bigcore0-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ cooling-maps { ++ map0 { ++ trip = <&bigcore0_alert1>; ++ cooling-device = ++ <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ ++ /* sensor between A76 cores 2 and 3 */ ++ bigcore2_thermal: bigcore2-thermal { ++ polling-delay-passive = <100>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 2>; ++ ++ trips { ++ /* threshold to start collecting temperature ++ * statistics e.g. with the IPA governor ++ */ ++ bigcore2_alert0: bigcore2-alert0 { ++ temperature = <75000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ /* actual control temperature */ ++ bigcore2_alert1: bigcore2-alert1 { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ bigcore2_crit: bigcore2-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ cooling-maps { ++ map0 { ++ trip = <&bigcore2_alert1>; ++ cooling-device = ++ <&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ ++ /* sensor between the four A55 cores */ ++ little_core_thermal: littlecore-thermal { ++ polling-delay-passive = <100>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 3>; ++ ++ trips { ++ /* threshold to start collecting temperature ++ * statistics e.g. with the IPA governor ++ */ ++ littlecore_alert0: littlecore-alert0 { ++ temperature = <75000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ /* actual control temperature */ ++ littlecore_alert1: littlecore-alert1 { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ littlecore_crit: littlecore-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ cooling-maps { ++ map0 { ++ trip = <&littlecore_alert1>; ++ cooling-device = ++ <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ ++ /* sensor near the PD_CENTER power domain */ ++ center_thermal: center-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 4>; ++ ++ trips { ++ center_crit: center-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ gpu_thermal: gpu-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 5>; ++ ++ trips { ++ gpu_crit: gpu-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ npu_thermal: npu-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&tsadc 6>; ++ ++ trips { ++ npu_crit: npu-crit { ++ temperature = <115000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ }; + }; + + saradc: adc@fec10000 { +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexey Charkov +Date: Thu, 29 Feb 2024 23:26:35 +0400 +Subject: arm64: dts: rockchip: Add OPP data for CPU cores on RK3588 + +By default the CPUs on RK3588 start up in a conservative performance +mode. Add frequency and voltage mappings to the device tree to enable +dynamic scaling via cpufreq. + +OPP values are adapted from Radxa's downstream kernel for Rock 5B [1], +stripping them down to the minimum frequency and voltage combinations +as expected by the generic upstream cpufreq-dt driver, and also dropping +those OPPs that don't differ in voltage but only in frequency (keeping +the top frequency OPP in each case). + +Note that this patch ignores voltage scaling for the CPU memory +interface which the downstream kernel does through a custom cpufreq +driver, and which is why the downstream version has two sets of voltage +values for each OPP (the second one being meant for the memory +interface supply regulator). This is done instead via regulator +coupling between CPU and memory interface supplies on affected boards. + +This has been tested on Rock 5B with u-boot 2023.11 compiled from +Collabora's integration tree [2] with binary bl31 and appears to be +stable both under active cooling and passive cooling (with throttling) + +[1] https://github.com/radxa/kernel/blob/stable-5.10-rock5/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +[2] https://gitlab.collabora.com/hardware-enablement/rockchip-3588/u-boot + +Signed-off-by: Alexey Charkov +Link: https://lore.kernel.org/r/20240229-rk-dts-additions-v3-4-6afe8473a631@gmail.com +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 122 ++++++++++ + 1 file changed, 122 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -97,6 +97,7 @@ cpu_l0: cpu@0 { + clocks = <&scmi_clk SCMI_CLK_CPUL>; + assigned-clocks = <&scmi_clk SCMI_CLK_CPUL>; + assigned-clock-rates = <816000000>; ++ operating-points-v2 = <&cluster0_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <32768>; + i-cache-line-size = <64>; +@@ -116,6 +117,7 @@ cpu_l1: cpu@100 { + enable-method = "psci"; + capacity-dmips-mhz = <530>; + clocks = <&scmi_clk SCMI_CLK_CPUL>; ++ operating-points-v2 = <&cluster0_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <32768>; + i-cache-line-size = <64>; +@@ -135,6 +137,7 @@ cpu_l2: cpu@200 { + enable-method = "psci"; + capacity-dmips-mhz = <530>; + clocks = <&scmi_clk SCMI_CLK_CPUL>; ++ operating-points-v2 = <&cluster0_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <32768>; + i-cache-line-size = <64>; +@@ -154,6 +157,7 @@ cpu_l3: cpu@300 { + enable-method = "psci"; + capacity-dmips-mhz = <530>; + clocks = <&scmi_clk SCMI_CLK_CPUL>; ++ operating-points-v2 = <&cluster0_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <32768>; + i-cache-line-size = <64>; +@@ -175,6 +179,7 @@ cpu_b0: cpu@400 { + clocks = <&scmi_clk SCMI_CLK_CPUB01>; + assigned-clocks = <&scmi_clk SCMI_CLK_CPUB01>; + assigned-clock-rates = <816000000>; ++ operating-points-v2 = <&cluster1_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <65536>; + i-cache-line-size = <64>; +@@ -194,6 +199,7 @@ cpu_b1: cpu@500 { + enable-method = "psci"; + capacity-dmips-mhz = <1024>; + clocks = <&scmi_clk SCMI_CLK_CPUB01>; ++ operating-points-v2 = <&cluster1_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <65536>; + i-cache-line-size = <64>; +@@ -215,6 +221,7 @@ cpu_b2: cpu@600 { + clocks = <&scmi_clk SCMI_CLK_CPUB23>; + assigned-clocks = <&scmi_clk SCMI_CLK_CPUB23>; + assigned-clock-rates = <816000000>; ++ operating-points-v2 = <&cluster2_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <65536>; + i-cache-line-size = <64>; +@@ -234,6 +241,7 @@ cpu_b3: cpu@700 { + enable-method = "psci"; + capacity-dmips-mhz = <1024>; + clocks = <&scmi_clk SCMI_CLK_CPUB23>; ++ operating-points-v2 = <&cluster2_opp_table>; + cpu-idle-states = <&CPU_SLEEP>; + i-cache-size = <65536>; + i-cache-line-size = <64>; +@@ -348,6 +356,120 @@ l3_cache: l3-cache { + }; + }; + ++ cluster0_opp_table: opp-table-cluster0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1008000000 { ++ opp-hz = /bits/ 64 <1008000000>; ++ opp-microvolt = <675000 675000 950000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <712500 712500 950000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1416000000 { ++ opp-hz = /bits/ 64 <1416000000>; ++ opp-microvolt = <762500 762500 950000>; ++ clock-latency-ns = <40000>; ++ opp-suspend; ++ }; ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <850000 850000 950000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <950000 950000 950000>; ++ clock-latency-ns = <40000>; ++ }; ++ }; ++ ++ cluster1_opp_table: opp-table-cluster1 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1416000000 { ++ opp-hz = /bits/ 64 <1416000000>; ++ opp-microvolt = <725000 725000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <762500 762500 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <850000 850000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <925000 925000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <987500 987500 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2400000000 { ++ opp-hz = /bits/ 64 <2400000000>; ++ opp-microvolt = <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ }; ++ ++ cluster2_opp_table: opp-table-cluster2 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1416000000 { ++ opp-hz = /bits/ 64 <1416000000>; ++ opp-microvolt = <725000 725000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <762500 762500 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <850000 850000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <925000 925000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <987500 987500 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2400000000 { ++ opp-hz = /bits/ 64 <2400000000>; ++ opp-microvolt = <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ }; ++ + firmware { + optee: optee { + compatible = "linaro,optee-tz"; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexey Charkov +Date: Thu, 29 Feb 2024 23:26:36 +0400 +Subject: arm64: dts: rockchip: Add further granularity in RK3588 CPU OPPs + +This introduces additional OPPs that share the same voltage as +another OPP already present in the .dtsi but with lower frequency. + +The idea is to try and limit system throughput more gradually upon +reaching the throttling condition for workloads that are close to +sustainable power already, thus avoiding needless performance loss. + +My limited synthetic benchmarking [1] showed around 3.8% performance +benefit when these are in place, other things equal (not meant to +be comprehensive). Though dmesg complains about these OPPs being +'inefficient': + +[ 9.009561] cpu cpu0: EM: OPP:816000 is inefficient +[ 9.009580] cpu cpu0: EM: OPP:600000 is inefficient +[ 9.009591] cpu cpu0: EM: OPP:408000 is inefficient +[ 9.011370] cpu cpu4: EM: OPP:2352000 is inefficient +[ 9.011379] cpu cpu4: EM: OPP:2304000 is inefficient +[ 9.011384] cpu cpu4: EM: OPP:2256000 is inefficient +[ 9.011389] cpu cpu4: EM: OPP:600000 is inefficient +[ 9.011393] cpu cpu4: EM: OPP:408000 is inefficient +[ 9.012978] cpu cpu6: EM: OPP:2352000 is inefficient +[ 9.012987] cpu cpu6: EM: OPP:2304000 is inefficient +[ 9.012992] cpu cpu6: EM: OPP:2256000 is inefficient +[ 9.012996] cpu cpu6: EM: OPP:600000 is inefficient +[ 9.013000] cpu cpu6: EM: OPP:408000 is inefficient + +[1] https://lore.kernel.org/linux-rockchip/CABjd4YxqarUCbZ-a2XLe3TWJ-qjphGkyq=wDnctnEhdoSdPPpw@mail.gmail.com/T/#me92aa0ee25e6eeb1d1501ce85f5af4e58b3b13c5 + +Signed-off-by: Alexey Charkov +Link: https://lore.kernel.org/r/20240229-rk-dts-additions-v3-5-6afe8473a631@gmail.com +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 87 ++++++++++ + 1 file changed, 87 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -360,6 +360,21 @@ cluster0_opp_table: opp-table-cluster0 { + compatible = "operating-points-v2"; + opp-shared; + ++ opp-408000000 { ++ opp-hz = /bits/ 64 <408000000>; ++ opp-microvolt = <675000 675000 950000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <675000 675000 950000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-816000000 { ++ opp-hz = /bits/ 64 <816000000>; ++ opp-microvolt = <675000 675000 950000>; ++ clock-latency-ns = <40000>; ++ }; + opp-1008000000 { + opp-hz = /bits/ 64 <1008000000>; + opp-microvolt = <675000 675000 950000>; +@@ -392,6 +407,27 @@ cluster1_opp_table: opp-table-cluster1 { + compatible = "operating-points-v2"; + opp-shared; + ++ opp-408000000 { ++ opp-hz = /bits/ 64 <408000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ opp-suspend; ++ }; ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-816000000 { ++ opp-hz = /bits/ 64 <816000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1008000000 { ++ opp-hz = /bits/ 64 <1008000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ }; + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <675000 675000 1000000>; +@@ -422,6 +458,21 @@ opp-2208000000 { + opp-microvolt = <987500 987500 1000000>; + clock-latency-ns = <40000>; + }; ++ opp-2256000000 { ++ opp-hz = /bits/ 64 <2256000000>; ++ opp-microvolt = <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2304000000 { ++ opp-hz = /bits/ 64 <2304000000>; ++ opp-microvolt = <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2352000000 { ++ opp-hz = /bits/ 64 <2352000000>; ++ opp-microvolt = <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; + opp-2400000000 { + opp-hz = /bits/ 64 <2400000000>; + opp-microvolt = <1000000 1000000 1000000>; +@@ -433,6 +484,27 @@ cluster2_opp_table: opp-table-cluster2 { + compatible = "operating-points-v2"; + opp-shared; + ++ opp-408000000 { ++ opp-hz = /bits/ 64 <408000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ opp-suspend; ++ }; ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-816000000 { ++ opp-hz = /bits/ 64 <816000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1008000000 { ++ opp-hz = /bits/ 64 <1008000000>; ++ opp-microvolt = <675000 675000 1000000>; ++ clock-latency-ns = <40000>; ++ }; + opp-1200000000 { + opp-hz = /bits/ 64 <1200000000>; + opp-microvolt = <675000 675000 1000000>; +@@ -463,6 +535,21 @@ opp-2208000000 { + opp-microvolt = <987500 987500 1000000>; + clock-latency-ns = <40000>; + }; ++ opp-2256000000 { ++ opp-hz = /bits/ 64 <2256000000>; ++ opp-microvolt = <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2304000000 { ++ opp-hz = /bits/ 64 <2304000000>; ++ opp-microvolt = <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-2352000000 { ++ opp-hz = /bits/ 64 <2352000000>; ++ opp-microvolt = <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; + opp-2400000000 { + opp-hz = /bits/ 64 <2400000000>; + opp-microvolt = <1000000 1000000 1000000>; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0024-RK3588-Add-Crypto-Support.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0024-RK3588-Add-Crypto-Support.patch new file mode 100644 index 000000000000..3a709c1dc59e --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0024-RK3588-Add-Crypto-Support.patch @@ -0,0 +1,2327 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Corentin Labbe +Date: Tue, 7 Nov 2023 15:55:27 +0000 +Subject: dt-bindings: crypto: add support for rockchip,crypto-rk3588 + +Add device tree binding documentation for the Rockchip cryptographic +offloader V2. + +Signed-off-by: Corentin Labbe +--- + Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml | 65 ++++++++++ + 1 file changed, 65 insertions(+) + +diff --git a/Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml b/Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/Documentation/devicetree/bindings/crypto/rockchip,rk3588-crypto.yaml +@@ -0,0 +1,65 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/crypto/rockchip,rk3588-crypto.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Rockchip cryptographic offloader V2 ++ ++maintainers: ++ - Corentin Labbe ++ ++properties: ++ compatible: ++ enum: ++ - rockchip,rk3568-crypto ++ - rockchip,rk3588-crypto ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ minItems: 3 ++ ++ clock-names: ++ items: ++ - const: core ++ - const: a ++ - const: h ++ ++ resets: ++ minItems: 1 ++ ++ reset-names: ++ items: ++ - const: core ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ - clock-names ++ - resets ++ - reset-names ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ crypto@fe370000 { ++ compatible = "rockchip,rk3588-crypto"; ++ reg = <0xfe370000 0x4000>; ++ interrupts = ; ++ clocks = <&scmi_clk SCMI_CRYPTO_CORE>, <&scmi_clk SCMI_ACLK_SECURE_NS>, ++ <&scmi_clk SCMI_HCLK_SECURE_NS>; ++ clock-names = "core", "a", "h"; ++ resets = <&scmi_reset SRST_CRYPTO_CORE>; ++ reset-names = "core"; ++ }; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Corentin Labbe +Date: Tue, 7 Nov 2023 15:55:29 +0000 +Subject: ARM64: dts: rk3588: add crypto node + +The rk3588 has a crypto IP handled by the rk3588 crypto driver so adds a +node for it. + +Signed-off-by: Corentin Labbe +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 12 ++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -1911,6 +1911,18 @@ sdhci: mmc@fe2e0000 { + status = "disabled"; + }; + ++ crypto: crypto@fe370000 { ++ compatible = "rockchip,rk3588-crypto"; ++ reg = <0x0 0xfe370000 0x0 0x2000>; ++ interrupts = ; ++ clocks = <&scmi_clk SCMI_CRYPTO_CORE>, <&scmi_clk SCMI_ACLK_SECURE_NS>, ++ <&scmi_clk SCMI_HCLK_SECURE_NS>; ++ clock-names = "core", "aclk", "hclk"; ++ resets = <&scmi_reset SRST_CRYPTO_CORE>; ++ reset-names = "core"; ++ status = "okay"; ++ }; ++ + i2s0_8ch: i2s@fe470000 { + compatible = "rockchip,rk3588-i2s-tdm"; + reg = <0x0 0xfe470000 0x0 0x1000>; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Corentin Labbe +Date: Tue, 7 Nov 2023 15:55:30 +0000 +Subject: ARM64: dts: rk356x: add crypto node + +Both RK3566 and RK3568 have a crypto IP handled by the rk3588 crypto driver so adds a +node for it. + +Tested-by: Ricardo Pardini +Signed-off-by: Corentin Labbe +--- + arch/arm64/boot/dts/rockchip/rk356x.dtsi | 12 ++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -1071,6 +1071,18 @@ sdhci: mmc@fe310000 { + status = "disabled"; + }; + ++ crypto: crypto@fe380000 { ++ compatible = "rockchip,rk3568-crypto"; ++ reg = <0x0 0xfe380000 0x0 0x2000>; ++ interrupts = ; ++ clocks = <&cru ACLK_CRYPTO_NS>, <&cru HCLK_CRYPTO_NS>, ++ <&cru CLK_CRYPTO_NS_CORE>; ++ clock-names = "aclk", "hclk", "core"; ++ resets = <&cru SRST_CRYPTO_NS_CORE>; ++ reset-names = "core"; ++ status = "okay"; ++ }; ++ + i2s0_8ch: i2s@fe400000 { + compatible = "rockchip,rk3568-i2s-tdm"; + reg = <0x0 0xfe400000 0x0 0x1000>; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Corentin Labbe +Date: Tue, 7 Nov 2023 15:55:31 +0000 +Subject: reset: rockchip: secure reset must be used by SCMI + +While working on the rk3588 crypto driver, I loose lot of time +understanding why resetting the IP failed. +This is due to RK3588_SECURECRU_RESET_OFFSET being in the secure world, +so impossible to operate on it from the kernel. +All resets in this block must be handled via SCMI call. + +Signed-off-by: Corentin Labbe +--- + drivers/clk/rockchip/rst-rk3588.c | 42 ------ + include/dt-bindings/reset/rockchip,rk3588-cru.h | 68 +++++----- + 2 files changed, 34 insertions(+), 76 deletions(-) + +diff --git a/drivers/clk/rockchip/rst-rk3588.c b/drivers/clk/rockchip/rst-rk3588.c +index 111111111111..222222222222 100644 +--- a/drivers/clk/rockchip/rst-rk3588.c ++++ b/drivers/clk/rockchip/rst-rk3588.c +@@ -16,9 +16,6 @@ + /* 0xFD7C8000 + 0x0A00 */ + #define RK3588_PHPTOPCRU_RESET_OFFSET(id, reg, bit) [id] = (0x8000*4 + reg * 16 + bit) + +-/* 0xFD7D0000 + 0x0A00 */ +-#define RK3588_SECURECRU_RESET_OFFSET(id, reg, bit) [id] = (0x10000*4 + reg * 16 + bit) +- + /* 0xFD7F0000 + 0x0A00 */ + #define RK3588_PMU1CRU_RESET_OFFSET(id, reg, bit) [id] = (0x30000*4 + reg * 16 + bit) + +@@ -806,45 +803,6 @@ static const int rk3588_register_offset[] = { + RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU0IOC, 5, 4), + RK3588_PMU1CRU_RESET_OFFSET(SRST_P_GPIO0, 5, 5), + RK3588_PMU1CRU_RESET_OFFSET(SRST_GPIO0, 5, 6), +- +- /* SECURECRU_SOFTRST_CON00 */ +- RK3588_SECURECRU_RESET_OFFSET(SRST_A_SECURE_NS_BIU, 0, 10), +- RK3588_SECURECRU_RESET_OFFSET(SRST_H_SECURE_NS_BIU, 0, 11), +- RK3588_SECURECRU_RESET_OFFSET(SRST_A_SECURE_S_BIU, 0, 12), +- RK3588_SECURECRU_RESET_OFFSET(SRST_H_SECURE_S_BIU, 0, 13), +- RK3588_SECURECRU_RESET_OFFSET(SRST_P_SECURE_S_BIU, 0, 14), +- RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_CORE, 0, 15), +- +- /* SECURECRU_SOFTRST_CON01 */ +- RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_PKA, 1, 0), +- RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_RNG, 1, 1), +- RK3588_SECURECRU_RESET_OFFSET(SRST_A_CRYPTO, 1, 2), +- RK3588_SECURECRU_RESET_OFFSET(SRST_H_CRYPTO, 1, 3), +- RK3588_SECURECRU_RESET_OFFSET(SRST_KEYLADDER_CORE, 1, 9), +- RK3588_SECURECRU_RESET_OFFSET(SRST_KEYLADDER_RNG, 1, 10), +- RK3588_SECURECRU_RESET_OFFSET(SRST_A_KEYLADDER, 1, 11), +- RK3588_SECURECRU_RESET_OFFSET(SRST_H_KEYLADDER, 1, 12), +- RK3588_SECURECRU_RESET_OFFSET(SRST_P_OTPC_S, 1, 13), +- RK3588_SECURECRU_RESET_OFFSET(SRST_OTPC_S, 1, 14), +- RK3588_SECURECRU_RESET_OFFSET(SRST_WDT_S, 1, 15), +- +- /* SECURECRU_SOFTRST_CON02 */ +- RK3588_SECURECRU_RESET_OFFSET(SRST_T_WDT_S, 2, 0), +- RK3588_SECURECRU_RESET_OFFSET(SRST_H_BOOTROM, 2, 1), +- RK3588_SECURECRU_RESET_OFFSET(SRST_A_DCF, 2, 2), +- RK3588_SECURECRU_RESET_OFFSET(SRST_P_DCF, 2, 3), +- RK3588_SECURECRU_RESET_OFFSET(SRST_H_BOOTROM_NS, 2, 5), +- RK3588_SECURECRU_RESET_OFFSET(SRST_P_KEYLADDER, 2, 14), +- RK3588_SECURECRU_RESET_OFFSET(SRST_H_TRNG_S, 2, 15), +- +- /* SECURECRU_SOFTRST_CON03 */ +- RK3588_SECURECRU_RESET_OFFSET(SRST_H_TRNG_NS, 3, 0), +- RK3588_SECURECRU_RESET_OFFSET(SRST_D_SDMMC_BUFFER, 3, 1), +- RK3588_SECURECRU_RESET_OFFSET(SRST_H_SDMMC, 3, 2), +- RK3588_SECURECRU_RESET_OFFSET(SRST_H_SDMMC_BUFFER, 3, 3), +- RK3588_SECURECRU_RESET_OFFSET(SRST_SDMMC, 3, 4), +- RK3588_SECURECRU_RESET_OFFSET(SRST_P_TRNG_CHK, 3, 5), +- RK3588_SECURECRU_RESET_OFFSET(SRST_TRNG_S, 3, 6), + }; + + void rk3588_rst_init(struct device_node *np, void __iomem *reg_base) +diff --git a/include/dt-bindings/reset/rockchip,rk3588-cru.h b/include/dt-bindings/reset/rockchip,rk3588-cru.h +index 111111111111..222222222222 100644 +--- a/include/dt-bindings/reset/rockchip,rk3588-cru.h ++++ b/include/dt-bindings/reset/rockchip,rk3588-cru.h +@@ -716,39 +716,39 @@ + #define SRST_P_GPIO0 627 + #define SRST_GPIO0 628 + +-#define SRST_A_SECURE_NS_BIU 629 +-#define SRST_H_SECURE_NS_BIU 630 +-#define SRST_A_SECURE_S_BIU 631 +-#define SRST_H_SECURE_S_BIU 632 +-#define SRST_P_SECURE_S_BIU 633 +-#define SRST_CRYPTO_CORE 634 +- +-#define SRST_CRYPTO_PKA 635 +-#define SRST_CRYPTO_RNG 636 +-#define SRST_A_CRYPTO 637 +-#define SRST_H_CRYPTO 638 +-#define SRST_KEYLADDER_CORE 639 +-#define SRST_KEYLADDER_RNG 640 +-#define SRST_A_KEYLADDER 641 +-#define SRST_H_KEYLADDER 642 +-#define SRST_P_OTPC_S 643 +-#define SRST_OTPC_S 644 +-#define SRST_WDT_S 645 +- +-#define SRST_T_WDT_S 646 +-#define SRST_H_BOOTROM 647 +-#define SRST_A_DCF 648 +-#define SRST_P_DCF 649 +-#define SRST_H_BOOTROM_NS 650 +-#define SRST_P_KEYLADDER 651 +-#define SRST_H_TRNG_S 652 +- +-#define SRST_H_TRNG_NS 653 +-#define SRST_D_SDMMC_BUFFER 654 +-#define SRST_H_SDMMC 655 +-#define SRST_H_SDMMC_BUFFER 656 +-#define SRST_SDMMC 657 +-#define SRST_P_TRNG_CHK 658 +-#define SRST_TRNG_S 659 ++#define SRST_A_SECURE_NS_BIU 10 ++#define SRST_H_SECURE_NS_BIU 11 ++#define SRST_A_SECURE_S_BIU 12 ++#define SRST_H_SECURE_S_BIU 13 ++#define SRST_P_SECURE_S_BIU 14 ++#define SRST_CRYPTO_CORE 15 ++ ++#define SRST_CRYPTO_PKA 16 ++#define SRST_CRYPTO_RNG 17 ++#define SRST_A_CRYPTO 18 ++#define SRST_H_CRYPTO 19 ++#define SRST_KEYLADDER_CORE 25 ++#define SRST_KEYLADDER_RNG 26 ++#define SRST_A_KEYLADDER 27 ++#define SRST_H_KEYLADDER 28 ++#define SRST_P_OTPC_S 29 ++#define SRST_OTPC_S 30 ++#define SRST_WDT_S 31 ++ ++#define SRST_T_WDT_S 32 ++#define SRST_H_BOOTROM 33 ++#define SRST_A_DCF 34 ++#define SRST_P_DCF 35 ++#define SRST_H_BOOTROM_NS 37 ++#define SRST_P_KEYLADDER 46 ++#define SRST_H_TRNG_S 47 ++ ++#define SRST_H_TRNG_NS 48 ++#define SRST_D_SDMMC_BUFFER 49 ++#define SRST_H_SDMMC 50 ++#define SRST_H_SDMMC_BUFFER 51 ++#define SRST_SDMMC 52 ++#define SRST_P_TRNG_CHK 53 ++#define SRST_TRNG_S 54 + + #endif +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Corentin Labbe +Date: Tue, 7 Nov 2023 15:55:32 +0000 +Subject: crypto: rockchip: add rk3588 driver + +RK3588 have a new crypto IP, this patch adds basic support for it. +Only hashes and cipher are handled for the moment. + +Signed-off-by: Corentin Labbe +--- + drivers/crypto/Kconfig | 29 + + drivers/crypto/rockchip/Makefile | 5 + + drivers/crypto/rockchip/rk2_crypto.c | 739 ++++++++++ + drivers/crypto/rockchip/rk2_crypto.h | 246 +++ + drivers/crypto/rockchip/rk2_crypto_ahash.c | 344 +++++ + drivers/crypto/rockchip/rk2_crypto_skcipher.c | 576 ++++++++ + 6 files changed, 1939 insertions(+) + +diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -661,6 +661,35 @@ config CRYPTO_DEV_ROCKCHIP_DEBUG + the number of requests per algorithm and other internal stats. + + ++config CRYPTO_DEV_ROCKCHIP2 ++ tristate "Rockchip's cryptographic offloader V2" ++ depends on OF && ARCH_ROCKCHIP ++ depends on PM ++ select CRYPTO_ECB ++ select CRYPTO_CBC ++ select CRYPTO_AES ++ select CRYPTO_MD5 ++ select CRYPTO_SHA1 ++ select CRYPTO_SHA256 ++ select CRYPTO_SHA512 ++ select CRYPTO_SM3_GENERIC ++ select CRYPTO_HASH ++ select CRYPTO_SKCIPHER ++ select CRYPTO_ENGINE ++ ++ help ++ This driver interfaces with the hardware crypto offloader present ++ on RK3566, RK3568 and RK3588. ++ ++config CRYPTO_DEV_ROCKCHIP2_DEBUG ++ bool "Enable Rockchip V2 crypto stats" ++ depends on CRYPTO_DEV_ROCKCHIP2 ++ depends on DEBUG_FS ++ help ++ Say y to enable Rockchip crypto debug stats. ++ This will create /sys/kernel/debug/rk3588_crypto/stats for displaying ++ the number of requests per algorithm and other internal stats. ++ + config CRYPTO_DEV_ZYNQMP_AES + tristate "Support for Xilinx ZynqMP AES hw accelerator" + depends on ZYNQMP_FIRMWARE || COMPILE_TEST +diff --git a/drivers/crypto/rockchip/Makefile b/drivers/crypto/rockchip/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/crypto/rockchip/Makefile ++++ b/drivers/crypto/rockchip/Makefile +@@ -3,3 +3,8 @@ obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rk_crypto.o + rk_crypto-objs := rk3288_crypto.o \ + rk3288_crypto_skcipher.o \ + rk3288_crypto_ahash.o ++ ++obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP2) += rk_crypto2.o ++rk_crypto2-objs := rk2_crypto.o \ ++ rk2_crypto_skcipher.o \ ++ rk2_crypto_ahash.o +diff --git a/drivers/crypto/rockchip/rk2_crypto.c b/drivers/crypto/rockchip/rk2_crypto.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/crypto/rockchip/rk2_crypto.c +@@ -0,0 +1,739 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * hardware cryptographic offloader for RK3568/RK3588 SoC ++ * ++ * Copyright (c) 2022-2023, Corentin Labbe ++ */ ++ ++#include "rk2_crypto.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static struct rockchip_ip rocklist = { ++ .dev_list = LIST_HEAD_INIT(rocklist.dev_list), ++ .lock = __SPIN_LOCK_UNLOCKED(rocklist.lock), ++}; ++ ++struct rk2_crypto_dev *get_rk2_crypto(void) ++{ ++ struct rk2_crypto_dev *first; ++ ++ spin_lock(&rocklist.lock); ++ first = list_first_entry_or_null(&rocklist.dev_list, ++ struct rk2_crypto_dev, list); ++ list_rotate_left(&rocklist.dev_list); ++ spin_unlock(&rocklist.lock); ++ return first; ++} ++ ++static const struct rk2_variant rk3568_variant = { ++ .num_clks = 3, ++}; ++ ++static const struct rk2_variant rk3588_variant = { ++ .num_clks = 3, ++}; ++ ++static int rk2_crypto_get_clks(struct rk2_crypto_dev *dev) ++{ ++ int i, j, err; ++ unsigned long cr; ++ ++ dev->num_clks = devm_clk_bulk_get_all(dev->dev, &dev->clks); ++ if (dev->num_clks < dev->variant->num_clks) { ++ dev_err(dev->dev, "Missing clocks, got %d instead of %d\n", ++ dev->num_clks, dev->variant->num_clks); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < dev->num_clks; i++) { ++ cr = clk_get_rate(dev->clks[i].clk); ++ for (j = 0; j < ARRAY_SIZE(dev->variant->rkclks); j++) { ++ if (dev->variant->rkclks[j].max == 0) ++ continue; ++ if (strcmp(dev->variant->rkclks[j].name, dev->clks[i].id)) ++ continue; ++ if (cr > dev->variant->rkclks[j].max) { ++ err = clk_set_rate(dev->clks[i].clk, ++ dev->variant->rkclks[j].max); ++ if (err) ++ dev_err(dev->dev, "Fail downclocking %s from %lu to %lu\n", ++ dev->variant->rkclks[j].name, cr, ++ dev->variant->rkclks[j].max); ++ else ++ dev_info(dev->dev, "Downclocking %s from %lu to %lu\n", ++ dev->variant->rkclks[j].name, cr, ++ dev->variant->rkclks[j].max); ++ } ++ } ++ } ++ return 0; ++} ++ ++static int rk2_crypto_enable_clk(struct rk2_crypto_dev *dev) ++{ ++ int err; ++ ++ err = clk_bulk_prepare_enable(dev->num_clks, dev->clks); ++ if (err) ++ dev_err(dev->dev, "Could not enable clock clks\n"); ++ ++ return err; ++} ++ ++static void rk2_crypto_disable_clk(struct rk2_crypto_dev *dev) ++{ ++ clk_bulk_disable_unprepare(dev->num_clks, dev->clks); ++} ++ ++/* ++ * Power management strategy: The device is suspended until a request ++ * is handled. For avoiding suspend/resume yoyo, the autosuspend is set to 2s. ++ */ ++static int rk2_crypto_pm_suspend(struct device *dev) ++{ ++ struct rk2_crypto_dev *rkdev = dev_get_drvdata(dev); ++ ++ rk2_crypto_disable_clk(rkdev); ++ reset_control_assert(rkdev->rst); ++ ++ return 0; ++} ++ ++static int rk2_crypto_pm_resume(struct device *dev) ++{ ++ struct rk2_crypto_dev *rkdev = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = rk2_crypto_enable_clk(rkdev); ++ if (ret) ++ return ret; ++ ++ reset_control_deassert(rkdev->rst); ++ return 0; ++} ++ ++static const struct dev_pm_ops rk2_crypto_pm_ops = { ++ SET_RUNTIME_PM_OPS(rk2_crypto_pm_suspend, rk2_crypto_pm_resume, NULL) ++}; ++ ++static int rk2_crypto_pm_init(struct rk2_crypto_dev *rkdev) ++{ ++ int err; ++ ++ pm_runtime_use_autosuspend(rkdev->dev); ++ pm_runtime_set_autosuspend_delay(rkdev->dev, 2000); ++ ++ err = pm_runtime_set_suspended(rkdev->dev); ++ if (err) ++ return err; ++ pm_runtime_enable(rkdev->dev); ++ return err; ++} ++ ++static void rk2_crypto_pm_exit(struct rk2_crypto_dev *rkdev) ++{ ++ pm_runtime_disable(rkdev->dev); ++} ++ ++static irqreturn_t rk2_crypto_irq_handle(int irq, void *dev_id) ++{ ++ struct rk2_crypto_dev *rkc = platform_get_drvdata(dev_id); ++ u32 v; ++ ++ v = readl(rkc->reg + RK2_CRYPTO_DMA_INT_ST); ++ writel(v, rkc->reg + RK2_CRYPTO_DMA_INT_ST); ++ ++ rkc->status = 1; ++ if (v & 0xF8) { ++ dev_warn(rkc->dev, "DMA Error\n"); ++ rkc->status = 0; ++ } ++ complete(&rkc->complete); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct rk2_crypto_template rk2_crypto_algs[] = { ++ { ++ .type = CRYPTO_ALG_TYPE_SKCIPHER, ++ .rk2_mode = RK2_CRYPTO_AES_ECB, ++ .alg.skcipher.base = { ++ .base.cra_name = "ecb(aes)", ++ .base.cra_driver_name = "ecb-aes-rk2", ++ .base.cra_priority = 300, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, ++ .base.cra_blocksize = AES_BLOCK_SIZE, ++ .base.cra_ctxsize = sizeof(struct rk2_cipher_ctx), ++ .base.cra_alignmask = 0x0f, ++ .base.cra_module = THIS_MODULE, ++ ++ .init = rk2_cipher_tfm_init, ++ .exit = rk2_cipher_tfm_exit, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .setkey = rk2_aes_setkey, ++ .encrypt = rk2_skcipher_encrypt, ++ .decrypt = rk2_skcipher_decrypt, ++ }, ++ .alg.skcipher.op = { ++ .do_one_request = rk2_cipher_run, ++ }, ++ }, ++ { ++ .type = CRYPTO_ALG_TYPE_SKCIPHER, ++ .rk2_mode = RK2_CRYPTO_AES_CBC, ++ .alg.skcipher.base = { ++ .base.cra_name = "cbc(aes)", ++ .base.cra_driver_name = "cbc-aes-rk2", ++ .base.cra_priority = 300, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, ++ .base.cra_blocksize = AES_BLOCK_SIZE, ++ .base.cra_ctxsize = sizeof(struct rk2_cipher_ctx), ++ .base.cra_alignmask = 0x0f, ++ .base.cra_module = THIS_MODULE, ++ ++ .init = rk2_cipher_tfm_init, ++ .exit = rk2_cipher_tfm_exit, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .setkey = rk2_aes_setkey, ++ .encrypt = rk2_skcipher_encrypt, ++ .decrypt = rk2_skcipher_decrypt, ++ }, ++ .alg.skcipher.op = { ++ .do_one_request = rk2_cipher_run, ++ }, ++ }, ++ { ++ .type = CRYPTO_ALG_TYPE_SKCIPHER, ++ .rk2_mode = RK2_CRYPTO_AES_XTS, ++ .is_xts = true, ++ .alg.skcipher.base = { ++ .base.cra_name = "xts(aes)", ++ .base.cra_driver_name = "xts-aes-rk2", ++ .base.cra_priority = 300, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, ++ .base.cra_blocksize = AES_BLOCK_SIZE, ++ .base.cra_ctxsize = sizeof(struct rk2_cipher_ctx), ++ .base.cra_alignmask = 0x0f, ++ .base.cra_module = THIS_MODULE, ++ ++ .init = rk2_cipher_tfm_init, ++ .exit = rk2_cipher_tfm_exit, ++ .min_keysize = AES_MIN_KEY_SIZE * 2, ++ .max_keysize = AES_MAX_KEY_SIZE * 2, ++ .ivsize = AES_BLOCK_SIZE, ++ .setkey = rk2_aes_xts_setkey, ++ .encrypt = rk2_skcipher_encrypt, ++ .decrypt = rk2_skcipher_decrypt, ++ }, ++ .alg.skcipher.op = { ++ .do_one_request = rk2_cipher_run, ++ }, ++ }, ++ { ++ .type = CRYPTO_ALG_TYPE_AHASH, ++ .rk2_mode = RK2_CRYPTO_MD5, ++ .alg.hash.base = { ++ .init = rk2_ahash_init, ++ .update = rk2_ahash_update, ++ .final = rk2_ahash_final, ++ .finup = rk2_ahash_finup, ++ .export = rk2_ahash_export, ++ .import = rk2_ahash_import, ++ .digest = rk2_ahash_digest, ++ .init_tfm = rk2_hash_init_tfm, ++ .exit_tfm = rk2_hash_exit_tfm, ++ .halg = { ++ .digestsize = MD5_DIGEST_SIZE, ++ .statesize = sizeof(struct md5_state), ++ .base = { ++ .cra_name = "md5", ++ .cra_driver_name = "rk2-md5", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK, ++ .cra_blocksize = MD5_HMAC_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct rk2_ahash_ctx), ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ .alg.hash.op = { ++ .do_one_request = rk2_hash_run, ++ }, ++ ++ }, ++ { ++ .type = CRYPTO_ALG_TYPE_AHASH, ++ .rk2_mode = RK2_CRYPTO_SHA1, ++ .alg.hash.base = { ++ .init = rk2_ahash_init, ++ .update = rk2_ahash_update, ++ .final = rk2_ahash_final, ++ .finup = rk2_ahash_finup, ++ .export = rk2_ahash_export, ++ .import = rk2_ahash_import, ++ .digest = rk2_ahash_digest, ++ .init_tfm = rk2_hash_init_tfm, ++ .exit_tfm = rk2_hash_exit_tfm, ++ .halg = { ++ .digestsize = SHA1_DIGEST_SIZE, ++ .statesize = sizeof(struct sha1_state), ++ .base = { ++ .cra_name = "sha1", ++ .cra_driver_name = "rk2-sha1", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK, ++ .cra_blocksize = SHA1_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct rk2_ahash_ctx), ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ .alg.hash.op = { ++ .do_one_request = rk2_hash_run, ++ }, ++ }, ++ { ++ .type = CRYPTO_ALG_TYPE_AHASH, ++ .rk2_mode = RK2_CRYPTO_SHA256, ++ .alg.hash.base = { ++ .init = rk2_ahash_init, ++ .update = rk2_ahash_update, ++ .final = rk2_ahash_final, ++ .finup = rk2_ahash_finup, ++ .export = rk2_ahash_export, ++ .import = rk2_ahash_import, ++ .digest = rk2_ahash_digest, ++ .init_tfm = rk2_hash_init_tfm, ++ .exit_tfm = rk2_hash_exit_tfm, ++ .halg = { ++ .digestsize = SHA256_DIGEST_SIZE, ++ .statesize = sizeof(struct sha256_state), ++ .base = { ++ .cra_name = "sha256", ++ .cra_driver_name = "rk2-sha256", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK, ++ .cra_blocksize = SHA256_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct rk2_ahash_ctx), ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ .alg.hash.op = { ++ .do_one_request = rk2_hash_run, ++ }, ++ }, ++ { ++ .type = CRYPTO_ALG_TYPE_AHASH, ++ .rk2_mode = RK2_CRYPTO_SHA384, ++ .alg.hash.base = { ++ .init = rk2_ahash_init, ++ .update = rk2_ahash_update, ++ .final = rk2_ahash_final, ++ .finup = rk2_ahash_finup, ++ .export = rk2_ahash_export, ++ .import = rk2_ahash_import, ++ .digest = rk2_ahash_digest, ++ .init_tfm = rk2_hash_init_tfm, ++ .exit_tfm = rk2_hash_exit_tfm, ++ .halg = { ++ .digestsize = SHA384_DIGEST_SIZE, ++ .statesize = sizeof(struct sha512_state), ++ .base = { ++ .cra_name = "sha384", ++ .cra_driver_name = "rk2-sha384", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK, ++ .cra_blocksize = SHA384_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct rk2_ahash_ctx), ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ .alg.hash.op = { ++ .do_one_request = rk2_hash_run, ++ }, ++ }, ++ { ++ .type = CRYPTO_ALG_TYPE_AHASH, ++ .rk2_mode = RK2_CRYPTO_SHA512, ++ .alg.hash.base = { ++ .init = rk2_ahash_init, ++ .update = rk2_ahash_update, ++ .final = rk2_ahash_final, ++ .finup = rk2_ahash_finup, ++ .export = rk2_ahash_export, ++ .import = rk2_ahash_import, ++ .digest = rk2_ahash_digest, ++ .init_tfm = rk2_hash_init_tfm, ++ .exit_tfm = rk2_hash_exit_tfm, ++ .halg = { ++ .digestsize = SHA512_DIGEST_SIZE, ++ .statesize = sizeof(struct sha512_state), ++ .base = { ++ .cra_name = "sha512", ++ .cra_driver_name = "rk2-sha512", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK, ++ .cra_blocksize = SHA512_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct rk2_ahash_ctx), ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ .alg.hash.op = { ++ .do_one_request = rk2_hash_run, ++ }, ++ }, ++ { ++ .type = CRYPTO_ALG_TYPE_AHASH, ++ .rk2_mode = RK2_CRYPTO_SM3, ++ .alg.hash.base = { ++ .init = rk2_ahash_init, ++ .update = rk2_ahash_update, ++ .final = rk2_ahash_final, ++ .finup = rk2_ahash_finup, ++ .export = rk2_ahash_export, ++ .import = rk2_ahash_import, ++ .digest = rk2_ahash_digest, ++ .init_tfm = rk2_hash_init_tfm, ++ .exit_tfm = rk2_hash_exit_tfm, ++ .halg = { ++ .digestsize = SM3_DIGEST_SIZE, ++ .statesize = sizeof(struct sm3_state), ++ .base = { ++ .cra_name = "sm3", ++ .cra_driver_name = "rk2-sm3", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK, ++ .cra_blocksize = SM3_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct rk2_ahash_ctx), ++ .cra_module = THIS_MODULE, ++ } ++ } ++ }, ++ .alg.hash.op = { ++ .do_one_request = rk2_hash_run, ++ }, ++ }, ++}; ++ ++#ifdef CONFIG_CRYPTO_DEV_ROCKCHIP2_DEBUG ++static int rk2_crypto_debugfs_stats_show(struct seq_file *seq, void *v) ++{ ++ struct rk2_crypto_dev *rkc; ++ unsigned int i; ++ ++ spin_lock(&rocklist.lock); ++ list_for_each_entry(rkc, &rocklist.dev_list, list) { ++ seq_printf(seq, "%s %s requests: %lu\n", ++ dev_driver_string(rkc->dev), dev_name(rkc->dev), ++ rkc->nreq); ++ } ++ spin_unlock(&rocklist.lock); ++ ++ for (i = 0; i < ARRAY_SIZE(rk2_crypto_algs); i++) { ++ if (!rk2_crypto_algs[i].dev) ++ continue; ++ switch (rk2_crypto_algs[i].type) { ++ case CRYPTO_ALG_TYPE_SKCIPHER: ++ seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", ++ rk2_crypto_algs[i].alg.skcipher.base.base.cra_driver_name, ++ rk2_crypto_algs[i].alg.skcipher.base.base.cra_name, ++ rk2_crypto_algs[i].stat_req, rk2_crypto_algs[i].stat_fb); ++ seq_printf(seq, "\tfallback due to length: %lu\n", ++ rk2_crypto_algs[i].stat_fb_len); ++ seq_printf(seq, "\tfallback due to alignment: %lu\n", ++ rk2_crypto_algs[i].stat_fb_align); ++ seq_printf(seq, "\tfallback due to SGs: %lu\n", ++ rk2_crypto_algs[i].stat_fb_sgdiff); ++ break; ++ case CRYPTO_ALG_TYPE_AHASH: ++ seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", ++ rk2_crypto_algs[i].alg.hash.base.halg.base.cra_driver_name, ++ rk2_crypto_algs[i].alg.hash.base.halg.base.cra_name, ++ rk2_crypto_algs[i].stat_req, rk2_crypto_algs[i].stat_fb); ++ break; ++ } ++ } ++ return 0; ++} ++ ++static int rk2_crypto_debugfs_info_show(struct seq_file *seq, void *d) ++{ ++ struct rk2_crypto_dev *rkc; ++ u32 v; ++ ++ spin_lock(&rocklist.lock); ++ list_for_each_entry(rkc, &rocklist.dev_list, list) { ++ v = readl(rkc->reg + RK2_CRYPTO_CLK_CTL); ++ seq_printf(seq, "CRYPTO_CLK_CTL %x\n", v); ++ v = readl(rkc->reg + RK2_CRYPTO_RST_CTL); ++ seq_printf(seq, "CRYPTO_RST_CTL %x\n", v); ++ ++ v = readl(rkc->reg + CRYPTO_AES_VERSION); ++ seq_printf(seq, "CRYPTO_AES_VERSION %x\n", v); ++ if (v & BIT(17)) ++ seq_puts(seq, "AES 192\n"); ++ ++ v = readl(rkc->reg + CRYPTO_DES_VERSION); ++ seq_printf(seq, "CRYPTO_DES_VERSION %x\n", v); ++ v = readl(rkc->reg + CRYPTO_SM4_VERSION); ++ seq_printf(seq, "CRYPTO_SM4_VERSION %x\n", v); ++ v = readl(rkc->reg + CRYPTO_HASH_VERSION); ++ seq_printf(seq, "CRYPTO_HASH_VERSION %x\n", v); ++ v = readl(rkc->reg + CRYPTO_HMAC_VERSION); ++ seq_printf(seq, "CRYPTO_HMAC_VERSION %x\n", v); ++ v = readl(rkc->reg + CRYPTO_RNG_VERSION); ++ seq_printf(seq, "CRYPTO_RNG_VERSION %x\n", v); ++ v = readl(rkc->reg + CRYPTO_PKA_VERSION); ++ seq_printf(seq, "CRYPTO_PKA_VERSION %x\n", v); ++ v = readl(rkc->reg + CRYPTO_CRYPTO_VERSION); ++ seq_printf(seq, "CRYPTO_CRYPTO_VERSION %x\n", v); ++ } ++ spin_unlock(&rocklist.lock); ++ ++ return 0; ++} ++ ++DEFINE_SHOW_ATTRIBUTE(rk2_crypto_debugfs_stats); ++DEFINE_SHOW_ATTRIBUTE(rk2_crypto_debugfs_info); ++ ++#endif ++ ++static void register_debugfs(struct rk2_crypto_dev *crypto_dev) ++{ ++#ifdef CONFIG_CRYPTO_DEV_ROCKCHIP2_DEBUG ++ /* Ignore error of debugfs */ ++ rocklist.dbgfs_dir = debugfs_create_dir("rk2_crypto", NULL); ++ rocklist.dbgfs_stats = debugfs_create_file("stats", 0440, ++ rocklist.dbgfs_dir, ++ &rocklist, ++ &rk2_crypto_debugfs_stats_fops); ++ rocklist.dbgfs_stats = debugfs_create_file("info", 0440, ++ rocklist.dbgfs_dir, ++ &rocklist, ++ &rk2_crypto_debugfs_info_fops); ++#endif ++} ++ ++static int rk2_crypto_register(struct rk2_crypto_dev *rkc) ++{ ++ unsigned int i, k; ++ int err = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(rk2_crypto_algs); i++) { ++ rk2_crypto_algs[i].dev = rkc; ++ switch (rk2_crypto_algs[i].type) { ++ case CRYPTO_ALG_TYPE_SKCIPHER: ++ dev_info(rkc->dev, "Register %s as %s\n", ++ rk2_crypto_algs[i].alg.skcipher.base.base.cra_name, ++ rk2_crypto_algs[i].alg.skcipher.base.base.cra_driver_name); ++ err = crypto_engine_register_skcipher(&rk2_crypto_algs[i].alg.skcipher); ++ break; ++ case CRYPTO_ALG_TYPE_AHASH: ++ dev_info(rkc->dev, "Register %s as %s %d\n", ++ rk2_crypto_algs[i].alg.hash.base.halg.base.cra_name, ++ rk2_crypto_algs[i].alg.hash.base.halg.base.cra_driver_name, i); ++ err = crypto_engine_register_ahash(&rk2_crypto_algs[i].alg.hash); ++ break; ++ default: ++ dev_err(rkc->dev, "unknown algorithm\n"); ++ } ++ if (err) ++ goto err_cipher_algs; ++ } ++ return 0; ++ ++err_cipher_algs: ++ for (k = 0; k < i; k++) { ++ if (rk2_crypto_algs[k].type == CRYPTO_ALG_TYPE_SKCIPHER) ++ crypto_engine_unregister_skcipher(&rk2_crypto_algs[k].alg.skcipher); ++ else ++ crypto_engine_unregister_ahash(&rk2_crypto_algs[k].alg.hash); ++ } ++ return err; ++} ++ ++static void rk2_crypto_unregister(void) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(rk2_crypto_algs); i++) { ++ if (rk2_crypto_algs[i].type == CRYPTO_ALG_TYPE_SKCIPHER) ++ crypto_engine_unregister_skcipher(&rk2_crypto_algs[i].alg.skcipher); ++ else ++ crypto_engine_unregister_ahash(&rk2_crypto_algs[i].alg.hash); ++ } ++} ++ ++static const struct of_device_id crypto_of_id_table[] = { ++ { .compatible = "rockchip,rk3568-crypto", ++ .data = &rk3568_variant, ++ }, ++ { .compatible = "rockchip,rk3588-crypto", ++ .data = &rk3588_variant, ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, crypto_of_id_table); ++ ++static int rk2_crypto_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rk2_crypto_dev *rkc, *first; ++ int err = 0; ++ ++ rkc = devm_kzalloc(&pdev->dev, sizeof(*rkc), GFP_KERNEL); ++ if (!rkc) { ++ err = -ENOMEM; ++ goto err_crypto; ++ } ++ ++ rkc->dev = &pdev->dev; ++ platform_set_drvdata(pdev, rkc); ++ ++ rkc->variant = of_device_get_match_data(&pdev->dev); ++ if (!rkc->variant) { ++ dev_err(&pdev->dev, "Missing variant\n"); ++ return -EINVAL; ++ } ++ ++ rkc->rst = devm_reset_control_array_get_exclusive(dev); ++ if (IS_ERR(rkc->rst)) { ++ err = PTR_ERR(rkc->rst); ++ dev_err(&pdev->dev, "Fail to get resets err=%d\n", err); ++ goto err_crypto; ++ } ++ ++ rkc->tl = dma_alloc_coherent(rkc->dev, ++ sizeof(struct rk2_crypto_lli) * MAX_LLI, ++ &rkc->t_phy, GFP_KERNEL); ++ if (!rkc->tl) { ++ dev_err(rkc->dev, "Cannot get DMA memory for task\n"); ++ err = -ENOMEM; ++ goto err_crypto; ++ } ++ ++ reset_control_assert(rkc->rst); ++ usleep_range(10, 20); ++ reset_control_deassert(rkc->rst); ++ ++ rkc->reg = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(rkc->reg)) { ++ err = PTR_ERR(rkc->reg); ++ dev_err(&pdev->dev, "Fail to get resources\n"); ++ goto err_crypto; ++ } ++ ++ err = rk2_crypto_get_clks(rkc); ++ if (err) ++ goto err_crypto; ++ ++ rkc->irq = platform_get_irq(pdev, 0); ++ if (rkc->irq < 0) { ++ dev_err(&pdev->dev, "control Interrupt is not available.\n"); ++ err = rkc->irq; ++ goto err_crypto; ++ } ++ ++ err = devm_request_irq(&pdev->dev, rkc->irq, ++ rk2_crypto_irq_handle, IRQF_SHARED, ++ "rk-crypto", pdev); ++ ++ if (err) { ++ dev_err(&pdev->dev, "irq request failed.\n"); ++ goto err_crypto; ++ } ++ ++ rkc->engine = crypto_engine_alloc_init(&pdev->dev, true); ++ crypto_engine_start(rkc->engine); ++ init_completion(&rkc->complete); ++ ++ err = rk2_crypto_pm_init(rkc); ++ if (err) ++ goto err_pm; ++ ++ err = pm_runtime_resume_and_get(&pdev->dev); ++ ++ spin_lock(&rocklist.lock); ++ first = list_first_entry_or_null(&rocklist.dev_list, ++ struct rk2_crypto_dev, list); ++ list_add_tail(&rkc->list, &rocklist.dev_list); ++ spin_unlock(&rocklist.lock); ++ ++ if (!first) { ++ dev_info(dev, "Registers crypto algos\n"); ++ err = rk2_crypto_register(rkc); ++ if (err) { ++ dev_err(dev, "Fail to register crypto algorithms"); ++ goto err_register_alg; ++ } ++ ++ register_debugfs(rkc); ++ } ++ ++ return 0; ++ ++err_register_alg: ++ rk2_crypto_pm_exit(rkc); ++err_pm: ++ crypto_engine_exit(rkc->engine); ++err_crypto: ++ dev_err(dev, "Crypto Accelerator not successfully registered\n"); ++ return err; ++} ++ ++static int rk2_crypto_remove(struct platform_device *pdev) ++{ ++ struct rk2_crypto_dev *rkc = platform_get_drvdata(pdev); ++ struct rk2_crypto_dev *first; ++ ++ spin_lock_bh(&rocklist.lock); ++ list_del(&rkc->list); ++ first = list_first_entry_or_null(&rocklist.dev_list, ++ struct rk2_crypto_dev, list); ++ spin_unlock_bh(&rocklist.lock); ++ ++ if (!first) { ++#ifdef CONFIG_CRYPTO_DEV_ROCKCHIP2_DEBUG ++ debugfs_remove_recursive(rocklist.dbgfs_dir); ++#endif ++ rk2_crypto_unregister(); ++ } ++ rk2_crypto_pm_exit(rkc); ++ crypto_engine_exit(rkc->engine); ++ return 0; ++} ++ ++static struct platform_driver crypto_driver = { ++ .probe = rk2_crypto_probe, ++ .remove = rk2_crypto_remove, ++ .driver = { ++ .name = "rk2-crypto", ++ .pm = &rk2_crypto_pm_ops, ++ .of_match_table = crypto_of_id_table, ++ }, ++}; ++ ++module_platform_driver(crypto_driver); ++ ++MODULE_DESCRIPTION("Rockchip Crypto Engine cryptographic offloader"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Corentin Labbe "); +diff --git a/drivers/crypto/rockchip/rk2_crypto.h b/drivers/crypto/rockchip/rk2_crypto.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/crypto/rockchip/rk2_crypto.h +@@ -0,0 +1,246 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RK2_CRYPTO_CLK_CTL 0x0000 ++#define RK2_CRYPTO_RST_CTL 0x0004 ++ ++#define RK2_CRYPTO_DMA_INT_EN 0x0008 ++/* values for RK2_CRYPTO_DMA_INT_EN */ ++#define RK2_CRYPTO_DMA_INT_LISTDONE BIT(0) ++ ++#define RK2_CRYPTO_DMA_INT_ST 0x000C ++/* values in RK2_CRYPTO_DMA_INT_ST are the same than in RK2_CRYPTO_DMA_INT_EN */ ++ ++#define RK2_CRYPTO_DMA_CTL 0x0010 ++#define RK2_CRYPTO_DMA_CTL_START BIT(0) ++ ++#define RK2_CRYPTO_DMA_LLI_ADDR 0x0014 ++#define RK2_CRYPTO_DMA_ST 0x0018 ++#define RK2_CRYPTO_DMA_STATE 0x001C ++#define RK2_CRYPTO_DMA_LLI_RADDR 0x0020 ++#define RK2_CRYPTO_DMA_SRC_RADDR 0x0024 ++#define RK2_CRYPTO_DMA_DST_WADDR 0x0028 ++#define RK2_CRYPTO_DMA_ITEM_ID 0x002C ++ ++#define RK2_CRYPTO_FIFO_CTL 0x0040 ++ ++#define RK2_CRYPTO_BC_CTL 0x0044 ++#define RK2_CRYPTO_AES (0 << 8) ++#define RK2_CRYPTO_MODE_ECB (0 << 4) ++#define RK2_CRYPTO_MODE_CBC (1 << 4) ++#define RK2_CRYPTO_XTS (6 << 4) ++ ++#define RK2_CRYPTO_HASH_CTL 0x0048 ++#define RK2_CRYPTO_HW_PAD BIT(2) ++#define RK2_CRYPTO_SHA1 (0 << 4) ++#define RK2_CRYPTO_MD5 (1 << 4) ++#define RK2_CRYPTO_SHA224 (3 << 4) ++#define RK2_CRYPTO_SHA256 (2 << 4) ++#define RK2_CRYPTO_SHA384 (9 << 4) ++#define RK2_CRYPTO_SHA512 (8 << 4) ++#define RK2_CRYPTO_SM3 (4 << 4) ++ ++#define RK2_CRYPTO_AES_ECB (RK2_CRYPTO_AES | RK2_CRYPTO_MODE_ECB) ++#define RK2_CRYPTO_AES_CBC (RK2_CRYPTO_AES | RK2_CRYPTO_MODE_CBC) ++#define RK2_CRYPTO_AES_XTS (RK2_CRYPTO_AES | RK2_CRYPTO_XTS) ++#define RK2_CRYPTO_AES_CTR_MODE 3 ++#define RK2_CRYPTO_AES_128BIT_key (0 << 2) ++#define RK2_CRYPTO_AES_192BIT_key (1 << 2) ++#define RK2_CRYPTO_AES_256BIT_key (2 << 2) ++ ++#define RK2_CRYPTO_DEC BIT(1) ++#define RK2_CRYPTO_ENABLE BIT(0) ++ ++#define RK2_CRYPTO_CIPHER_ST 0x004C ++#define RK2_CRYPTO_CIPHER_STATE 0x0050 ++ ++#define RK2_CRYPTO_CH0_IV_0 0x0100 ++ ++#define RK2_CRYPTO_KEY0 0x0180 ++#define RK2_CRYPTO_KEY1 0x0184 ++#define RK2_CRYPTO_KEY2 0x0188 ++#define RK2_CRYPTO_KEY3 0x018C ++#define RK2_CRYPTO_KEY4 0x0190 ++#define RK2_CRYPTO_KEY5 0x0194 ++#define RK2_CRYPTO_KEY6 0x0198 ++#define RK2_CRYPTO_KEY7 0x019C ++#define RK2_CRYPTO_CH4_KEY0 0x01c0 ++ ++#define RK2_CRYPTO_CH0_PC_LEN_0 0x0280 ++ ++#define RK2_CRYPTO_CH0_IV_LEN 0x0300 ++ ++#define RK2_CRYPTO_HASH_DOUT_0 0x03A0 ++#define RK2_CRYPTO_HASH_VALID 0x03E4 ++ ++#define RK2_CRYPTO_TRNG_CTL 0x0400 ++#define RK2_CRYPTO_TRNG_START BIT(0) ++#define RK2_CRYPTO_TRNG_ENABLE BIT(1) ++#define RK2_CRYPTO_TRNG_256 (0x3 << 4) ++#define RK2_CRYPTO_TRNG_SAMPLE_CNT 0x0404 ++#define RK2_CRYPTO_TRNG_DOUT 0x0410 ++ ++#define CRYPTO_AES_VERSION 0x0680 ++#define CRYPTO_DES_VERSION 0x0684 ++#define CRYPTO_SM4_VERSION 0x0688 ++#define CRYPTO_HASH_VERSION 0x068C ++#define CRYPTO_HMAC_VERSION 0x0690 ++#define CRYPTO_RNG_VERSION 0x0694 ++#define CRYPTO_PKA_VERSION 0x0698 ++#define CRYPTO_CRYPTO_VERSION 0x06F0 ++ ++#define RK2_LLI_DMA_CTRL_SRC_INT BIT(10) ++#define RK2_LLI_DMA_CTRL_DST_INT BIT(9) ++#define RK2_LLI_DMA_CTRL_LIST_INT BIT(8) ++#define RK2_LLI_DMA_CTRL_LAST BIT(0) ++ ++#define RK2_LLI_STRING_LAST BIT(2) ++#define RK2_LLI_STRING_FIRST BIT(1) ++#define RK2_LLI_CIPHER_START BIT(0) ++ ++#define RK2_MAX_CLKS 4 ++ ++#define MAX_LLI 20 ++ ++struct rk2_crypto_lli { ++ __le32 src_addr; ++ __le32 src_len; ++ __le32 dst_addr; ++ __le32 dst_len; ++ __le32 user; ++ __le32 iv; ++ __le32 dma_ctrl; ++ __le32 next; ++}; ++ ++/* ++ * struct rockchip_ip - struct for managing a list of RK crypto instance ++ * @dev_list: Used for doing a list of rk2_crypto_dev ++ * @lock: Control access to dev_list ++ * @dbgfs_dir: Debugfs dentry for statistic directory ++ * @dbgfs_stats: Debugfs dentry for statistic counters ++ */ ++struct rockchip_ip { ++ struct list_head dev_list; ++ spinlock_t lock; /* Control access to dev_list */ ++ struct dentry *dbgfs_dir; ++ struct dentry *dbgfs_stats; ++}; ++ ++struct rk2_clks { ++ const char *name; ++ unsigned long max; ++}; ++ ++struct rk2_variant { ++ int num_clks; ++ struct rk2_clks rkclks[RK2_MAX_CLKS]; ++}; ++ ++struct rk2_crypto_dev { ++ struct list_head list; ++ struct device *dev; ++ struct clk_bulk_data *clks; ++ int num_clks; ++ struct reset_control *rst; ++ void __iomem *reg; ++ int irq; ++ const struct rk2_variant *variant; ++ unsigned long nreq; ++ struct crypto_engine *engine; ++ struct completion complete; ++ int status; ++ struct rk2_crypto_lli *tl; ++ dma_addr_t t_phy; ++}; ++ ++/* the private variable of hash */ ++struct rk2_ahash_ctx { ++ /* for fallback */ ++ struct crypto_ahash *fallback_tfm; ++}; ++ ++/* the private variable of hash for fallback */ ++struct rk2_ahash_rctx { ++ struct rk2_crypto_dev *dev; ++ struct ahash_request fallback_req; ++ u32 mode; ++ int nrsgs; ++}; ++ ++/* the private variable of cipher */ ++struct rk2_cipher_ctx { ++ unsigned int keylen; ++ u8 key[AES_MAX_KEY_SIZE * 2]; ++ u8 iv[AES_BLOCK_SIZE]; ++ struct crypto_skcipher *fallback_tfm; ++}; ++ ++struct rk2_cipher_rctx { ++ struct rk2_crypto_dev *dev; ++ u8 backup_iv[AES_BLOCK_SIZE]; ++ u32 mode; ++ struct skcipher_request fallback_req; // keep at the end ++}; ++ ++struct rk2_crypto_template { ++ u32 type; ++ u32 rk2_mode; ++ bool is_xts; ++ struct rk2_crypto_dev *dev; ++ union { ++ struct skcipher_engine_alg skcipher; ++ struct ahash_engine_alg hash; ++ } alg; ++ unsigned long stat_req; ++ unsigned long stat_fb; ++ unsigned long stat_fb_len; ++ unsigned long stat_fb_sglen; ++ unsigned long stat_fb_align; ++ unsigned long stat_fb_sgdiff; ++}; ++ ++struct rk2_crypto_dev *get_rk2_crypto(void); ++int rk2_cipher_run(struct crypto_engine *engine, void *async_req); ++int rk2_hash_run(struct crypto_engine *engine, void *breq); ++ ++int rk2_cipher_tfm_init(struct crypto_skcipher *tfm); ++void rk2_cipher_tfm_exit(struct crypto_skcipher *tfm); ++int rk2_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, ++ unsigned int keylen); ++int rk2_aes_xts_setkey(struct crypto_skcipher *cipher, const u8 *key, ++ unsigned int keylen); ++int rk2_skcipher_encrypt(struct skcipher_request *req); ++int rk2_skcipher_decrypt(struct skcipher_request *req); ++int rk2_aes_ecb_encrypt(struct skcipher_request *req); ++int rk2_aes_ecb_decrypt(struct skcipher_request *req); ++int rk2_aes_cbc_encrypt(struct skcipher_request *req); ++int rk2_aes_cbc_decrypt(struct skcipher_request *req); ++ ++int rk2_ahash_init(struct ahash_request *req); ++int rk2_ahash_update(struct ahash_request *req); ++int rk2_ahash_final(struct ahash_request *req); ++int rk2_ahash_finup(struct ahash_request *req); ++int rk2_ahash_import(struct ahash_request *req, const void *in); ++int rk2_ahash_export(struct ahash_request *req, void *out); ++int rk2_ahash_digest(struct ahash_request *req); ++int rk2_hash_init_tfm(struct crypto_ahash *tfm); ++void rk2_hash_exit_tfm(struct crypto_ahash *tfm); +diff --git a/drivers/crypto/rockchip/rk2_crypto_ahash.c b/drivers/crypto/rockchip/rk2_crypto_ahash.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/crypto/rockchip/rk2_crypto_ahash.c +@@ -0,0 +1,344 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Crypto offloader support for Rockchip RK3568/RK3588 ++ * ++ * Copyright (c) 2022-2023 Corentin Labbe ++ */ ++#include ++#include ++#include "rk2_crypto.h" ++ ++static bool rk2_ahash_need_fallback(struct ahash_request *areq) ++{ ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct ahash_alg *alg = crypto_ahash_alg(tfm); ++ struct rk2_crypto_template *algt = container_of(alg, struct rk2_crypto_template, alg.hash.base); ++ struct scatterlist *sg; ++ ++ sg = areq->src; ++ while (sg) { ++ if (!IS_ALIGNED(sg->offset, sizeof(u32))) { ++ algt->stat_fb_align++; ++ return true; ++ } ++ if (sg->length % 4) { ++ algt->stat_fb_sglen++; ++ return true; ++ } ++ sg = sg_next(sg); ++ } ++ return false; ++} ++ ++static int rk2_ahash_digest_fb(struct ahash_request *areq) ++{ ++ struct rk2_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct rk2_ahash_ctx *tfmctx = crypto_ahash_ctx(tfm); ++ struct ahash_alg *alg = crypto_ahash_alg(tfm); ++ struct rk2_crypto_template *algt = container_of(alg, struct rk2_crypto_template, alg.hash.base); ++ ++ algt->stat_fb++; ++ ++ ahash_request_set_tfm(&rctx->fallback_req, tfmctx->fallback_tfm); ++ rctx->fallback_req.base.flags = areq->base.flags & ++ CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ rctx->fallback_req.nbytes = areq->nbytes; ++ rctx->fallback_req.src = areq->src; ++ rctx->fallback_req.result = areq->result; ++ ++ return crypto_ahash_digest(&rctx->fallback_req); ++} ++ ++static int zero_message_process(struct ahash_request *req) ++{ ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct ahash_alg *alg = crypto_ahash_alg(tfm); ++ struct rk2_crypto_template *algt = container_of(alg, struct rk2_crypto_template, alg.hash.base); ++ int digestsize = crypto_ahash_digestsize(tfm); ++ ++ switch (algt->rk2_mode) { ++ case RK2_CRYPTO_SHA1: ++ memcpy(req->result, sha1_zero_message_hash, digestsize); ++ break; ++ case RK2_CRYPTO_SHA256: ++ memcpy(req->result, sha256_zero_message_hash, digestsize); ++ break; ++ case RK2_CRYPTO_SHA384: ++ memcpy(req->result, sha384_zero_message_hash, digestsize); ++ break; ++ case RK2_CRYPTO_SHA512: ++ memcpy(req->result, sha512_zero_message_hash, digestsize); ++ break; ++ case RK2_CRYPTO_MD5: ++ memcpy(req->result, md5_zero_message_hash, digestsize); ++ break; ++ case RK2_CRYPTO_SM3: ++ memcpy(req->result, sm3_zero_message_hash, digestsize); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++int rk2_ahash_init(struct ahash_request *req) ++{ ++ struct rk2_ahash_rctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct rk2_ahash_ctx *ctx = crypto_ahash_ctx(tfm); ++ ++ ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); ++ rctx->fallback_req.base.flags = req->base.flags & ++ CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ return crypto_ahash_init(&rctx->fallback_req); ++} ++ ++int rk2_ahash_update(struct ahash_request *req) ++{ ++ struct rk2_ahash_rctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct rk2_ahash_ctx *ctx = crypto_ahash_ctx(tfm); ++ ++ ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); ++ rctx->fallback_req.base.flags = req->base.flags & ++ CRYPTO_TFM_REQ_MAY_SLEEP; ++ rctx->fallback_req.nbytes = req->nbytes; ++ rctx->fallback_req.src = req->src; ++ ++ return crypto_ahash_update(&rctx->fallback_req); ++} ++ ++int rk2_ahash_final(struct ahash_request *req) ++{ ++ struct rk2_ahash_rctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct rk2_ahash_ctx *ctx = crypto_ahash_ctx(tfm); ++ ++ ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); ++ rctx->fallback_req.base.flags = req->base.flags & ++ CRYPTO_TFM_REQ_MAY_SLEEP; ++ rctx->fallback_req.result = req->result; ++ ++ return crypto_ahash_final(&rctx->fallback_req); ++} ++ ++int rk2_ahash_finup(struct ahash_request *req) ++{ ++ struct rk2_ahash_rctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct rk2_ahash_ctx *ctx = crypto_ahash_ctx(tfm); ++ ++ ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); ++ rctx->fallback_req.base.flags = req->base.flags & ++ CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ rctx->fallback_req.nbytes = req->nbytes; ++ rctx->fallback_req.src = req->src; ++ rctx->fallback_req.result = req->result; ++ ++ return crypto_ahash_finup(&rctx->fallback_req); ++} ++ ++int rk2_ahash_import(struct ahash_request *req, const void *in) ++{ ++ struct rk2_ahash_rctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct rk2_ahash_ctx *ctx = crypto_ahash_ctx(tfm); ++ ++ ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); ++ rctx->fallback_req.base.flags = req->base.flags & ++ CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ return crypto_ahash_import(&rctx->fallback_req, in); ++} ++ ++int rk2_ahash_export(struct ahash_request *req, void *out) ++{ ++ struct rk2_ahash_rctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct rk2_ahash_ctx *ctx = crypto_ahash_ctx(tfm); ++ ++ ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback_tfm); ++ rctx->fallback_req.base.flags = req->base.flags & ++ CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ return crypto_ahash_export(&rctx->fallback_req, out); ++} ++ ++int rk2_ahash_digest(struct ahash_request *req) ++{ ++ struct rk2_ahash_rctx *rctx = ahash_request_ctx(req); ++ struct rk2_crypto_dev *dev; ++ struct crypto_engine *engine; ++ ++ if (rk2_ahash_need_fallback(req)) ++ return rk2_ahash_digest_fb(req); ++ ++ if (!req->nbytes) ++ return zero_message_process(req); ++ ++ dev = get_rk2_crypto(); ++ ++ rctx->dev = dev; ++ engine = dev->engine; ++ ++ return crypto_transfer_hash_request_to_engine(engine, req); ++} ++ ++static int rk2_hash_prepare(struct crypto_engine *engine, void *breq) ++{ ++ struct ahash_request *areq = container_of(breq, struct ahash_request, base); ++ struct rk2_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct rk2_crypto_dev *rkc = rctx->dev; ++ int ret; ++ ++ ret = dma_map_sg(rkc->dev, areq->src, sg_nents(areq->src), DMA_TO_DEVICE); ++ if (ret <= 0) ++ return -EINVAL; ++ ++ rctx->nrsgs = ret; ++ ++ return 0; ++} ++ ++static void rk2_hash_unprepare(struct crypto_engine *engine, void *breq) ++{ ++ struct ahash_request *areq = container_of(breq, struct ahash_request, base); ++ struct rk2_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct rk2_crypto_dev *rkc = rctx->dev; ++ ++ dma_unmap_sg(rkc->dev, areq->src, rctx->nrsgs, DMA_TO_DEVICE); ++} ++ ++int rk2_hash_run(struct crypto_engine *engine, void *breq) ++{ ++ struct ahash_request *areq = container_of(breq, struct ahash_request, base); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct rk2_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct ahash_alg *alg = crypto_ahash_alg(tfm); ++ struct rk2_crypto_template *algt = container_of(alg, struct rk2_crypto_template, alg.hash.base); ++ struct scatterlist *sgs = areq->src; ++ struct rk2_crypto_dev *rkc = rctx->dev; ++ struct rk2_crypto_lli *dd = &rkc->tl[0]; ++ int ddi = 0; ++ int err = 0; ++ unsigned int len = areq->nbytes; ++ unsigned int todo; ++ u32 v; ++ int i; ++ ++ err = rk2_hash_prepare(engine, breq); ++ ++ err = pm_runtime_resume_and_get(rkc->dev); ++ if (err) ++ return err; ++ ++ dev_dbg(rkc->dev, "%s %s len=%d\n", __func__, ++ crypto_tfm_alg_name(areq->base.tfm), areq->nbytes); ++ ++ algt->stat_req++; ++ rkc->nreq++; ++ ++ rctx->mode = algt->rk2_mode; ++ rctx->mode |= 0xffff0000; ++ rctx->mode |= RK2_CRYPTO_ENABLE | RK2_CRYPTO_HW_PAD; ++ writel(rctx->mode, rkc->reg + RK2_CRYPTO_HASH_CTL); ++ ++ while (sgs && len > 0) { ++ dd = &rkc->tl[ddi]; ++ ++ todo = min(sg_dma_len(sgs), len); ++ dd->src_addr = sg_dma_address(sgs); ++ dd->src_len = todo; ++ dd->dst_addr = 0; ++ dd->dst_len = 0; ++ dd->dma_ctrl = ddi << 24; ++ dd->iv = 0; ++ dd->next = rkc->t_phy + sizeof(struct rk2_crypto_lli) * (ddi + 1); ++ ++ if (ddi == 0) ++ dd->user = RK2_LLI_CIPHER_START | RK2_LLI_STRING_FIRST; ++ else ++ dd->user = 0; ++ ++ len -= todo; ++ dd->dma_ctrl |= RK2_LLI_DMA_CTRL_SRC_INT; ++ if (len == 0) { ++ dd->user |= RK2_LLI_STRING_LAST; ++ dd->dma_ctrl |= RK2_LLI_DMA_CTRL_LAST; ++ } ++ dev_dbg(rkc->dev, "HASH SG %d sglen=%d user=%x dma=%x mode=%x len=%d todo=%d phy=%llx\n", ++ ddi, sgs->length, dd->user, dd->dma_ctrl, rctx->mode, len, todo, rkc->t_phy); ++ ++ sgs = sg_next(sgs); ++ ddi++; ++ } ++ dd->next = 1; ++ writel(RK2_CRYPTO_DMA_INT_LISTDONE | 0x7F, rkc->reg + RK2_CRYPTO_DMA_INT_EN); ++ ++ writel(rkc->t_phy, rkc->reg + RK2_CRYPTO_DMA_LLI_ADDR); ++ ++ reinit_completion(&rkc->complete); ++ rkc->status = 0; ++ ++ writel(RK2_CRYPTO_DMA_CTL_START | RK2_CRYPTO_DMA_CTL_START << 16, rkc->reg + RK2_CRYPTO_DMA_CTL); ++ ++ wait_for_completion_interruptible_timeout(&rkc->complete, ++ msecs_to_jiffies(2000)); ++ if (!rkc->status) { ++ dev_err(rkc->dev, "DMA timeout\n"); ++ err = -EFAULT; ++ goto theend; ++ } ++ ++ readl_poll_timeout_atomic(rkc->reg + RK2_CRYPTO_HASH_VALID, v, v == 1, ++ 10, 1000); ++ ++ for (i = 0; i < crypto_ahash_digestsize(tfm) / 4; i++) { ++ v = readl(rkc->reg + RK2_CRYPTO_HASH_DOUT_0 + i * 4); ++ put_unaligned_le32(be32_to_cpu(v), areq->result + i * 4); ++ } ++ ++theend: ++ pm_runtime_put_autosuspend(rkc->dev); ++ ++ rk2_hash_unprepare(engine, breq); ++ ++ local_bh_disable(); ++ crypto_finalize_hash_request(engine, breq, err); ++ local_bh_enable(); ++ ++ return 0; ++} ++ ++int rk2_hash_init_tfm(struct crypto_ahash *tfm) ++{ ++ struct rk2_ahash_ctx *tctx = crypto_ahash_ctx(tfm); ++ const char *alg_name = crypto_ahash_alg_name(tfm); ++ struct ahash_alg *alg = crypto_ahash_alg(tfm); ++ struct rk2_crypto_template *algt = container_of(alg, struct rk2_crypto_template, alg.hash.base); ++ ++ /* for fallback */ ++ tctx->fallback_tfm = crypto_alloc_ahash(alg_name, 0, ++ CRYPTO_ALG_NEED_FALLBACK); ++ if (IS_ERR(tctx->fallback_tfm)) { ++ dev_err(algt->dev->dev, "Could not load fallback driver.\n"); ++ return PTR_ERR(tctx->fallback_tfm); ++ } ++ ++ crypto_ahash_set_reqsize(tfm, ++ sizeof(struct rk2_ahash_rctx) + ++ crypto_ahash_reqsize(tctx->fallback_tfm)); ++ return 0; ++} ++ ++void rk2_hash_exit_tfm(struct crypto_ahash *tfm) ++{ ++ struct rk2_ahash_ctx *tctx = crypto_ahash_ctx(tfm); ++ ++ crypto_free_ahash(tctx->fallback_tfm); ++} +diff --git a/drivers/crypto/rockchip/rk2_crypto_skcipher.c b/drivers/crypto/rockchip/rk2_crypto_skcipher.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/crypto/rockchip/rk2_crypto_skcipher.c +@@ -0,0 +1,576 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * hardware cryptographic offloader for RK3568/RK3588 SoC ++ * ++ * Copyright (c) 2022-2023 Corentin Labbe ++ */ ++#include ++#include "rk2_crypto.h" ++ ++static void rk2_print(struct rk2_crypto_dev *rkc) ++{ ++ u32 v; ++ ++ v = readl(rkc->reg + RK2_CRYPTO_DMA_ST); ++ dev_info(rkc->dev, "DMA_ST %x\n", v); ++ switch (v) { ++ case 0: ++ dev_info(rkc->dev, "DMA_ST: DMA IDLE\n"); ++ break; ++ case 1: ++ dev_info(rkc->dev, "DMA_ST: DMA BUSY\n"); ++ break; ++ default: ++ dev_err(rkc->dev, "DMA_ST: invalid value\n"); ++ } ++ ++ v = readl(rkc->reg + RK2_CRYPTO_DMA_STATE); ++ dev_info(rkc->dev, "DMA_STATE %x\n", v); ++ ++ switch (v & 0x3) { ++ case 0: ++ dev_info(rkc->dev, "DMA_STATE: DMA DST IDLE\n"); ++ break; ++ case 1: ++ dev_info(rkc->dev, "DMA_STATE: DMA DST LOAD\n"); ++ break; ++ case 2: ++ dev_info(rkc->dev, "DMA_STATE: DMA DST WORK\n"); ++ break; ++ default: ++ dev_err(rkc->dev, "DMA DST invalid\n"); ++ break; ++ } ++ switch (v & 0xC) { ++ case 0: ++ dev_info(rkc->dev, "DMA_STATE: DMA SRC IDLE\n"); ++ break; ++ case 1: ++ dev_info(rkc->dev, "DMA_STATE: DMA SRC LOAD\n"); ++ break; ++ case 2: ++ dev_info(rkc->dev, "DMA_STATE: DMA SRC WORK\n"); ++ break; ++ default: ++ dev_err(rkc->dev, "DMA_STATE: DMA SRC invalid\n"); ++ break; ++ } ++ switch (v & 0x30) { ++ case 0: ++ dev_info(rkc->dev, "DMA_STATE: DMA LLI IDLE\n"); ++ break; ++ case 1: ++ dev_info(rkc->dev, "DMA_STATE: DMA LLI LOAD\n"); ++ break; ++ case 2: ++ dev_info(rkc->dev, "DMA LLI WORK\n"); ++ break; ++ default: ++ dev_err(rkc->dev, "DMA LLI invalid\n"); ++ break; ++ } ++ ++ v = readl(rkc->reg + RK2_CRYPTO_DMA_LLI_RADDR); ++ dev_info(rkc->dev, "DMA_LLI_RADDR %x\n", v); ++ v = readl(rkc->reg + RK2_CRYPTO_DMA_SRC_RADDR); ++ dev_info(rkc->dev, "DMA_SRC_RADDR %x\n", v); ++ v = readl(rkc->reg + RK2_CRYPTO_DMA_DST_WADDR); ++ dev_info(rkc->dev, "DMA_LLI_WADDR %x\n", v); ++ v = readl(rkc->reg + RK2_CRYPTO_DMA_ITEM_ID); ++ dev_info(rkc->dev, "DMA_LLI_ITEMID %x\n", v); ++ ++ v = readl(rkc->reg + RK2_CRYPTO_CIPHER_ST); ++ dev_info(rkc->dev, "CIPHER_ST %x\n", v); ++ if (v & BIT(0)) ++ dev_info(rkc->dev, "CIPHER_ST: BLOCK CIPHER BUSY\n"); ++ else ++ dev_info(rkc->dev, "CIPHER_ST: BLOCK CIPHER IDLE\n"); ++ if (v & BIT(2)) ++ dev_info(rkc->dev, "CIPHER_ST: HASH BUSY\n"); ++ else ++ dev_info(rkc->dev, "CIPHER_ST: HASH IDLE\n"); ++ if (v & BIT(2)) ++ dev_info(rkc->dev, "CIPHER_ST: OTP KEY VALID\n"); ++ else ++ dev_info(rkc->dev, "CIPHER_ST: OTP KEY INVALID\n"); ++ ++ v = readl(rkc->reg + RK2_CRYPTO_CIPHER_STATE); ++ dev_info(rkc->dev, "CIPHER_STATE %x\n", v); ++ switch (v & 0x3) { ++ case 0: ++ dev_info(rkc->dev, "serial: IDLE state\n"); ++ break; ++ case 1: ++ dev_info(rkc->dev, "serial: PRE state\n"); ++ break; ++ case 2: ++ dev_info(rkc->dev, "serial: BULK state\n"); ++ break; ++ default: ++ dev_info(rkc->dev, "serial: reserved state\n"); ++ break; ++ } ++ switch (v & 0xC) { ++ case 0: ++ dev_info(rkc->dev, "mac_state: IDLE state\n"); ++ break; ++ case 1: ++ dev_info(rkc->dev, "mac_state: PRE state\n"); ++ break; ++ case 2: ++ dev_info(rkc->dev, "mac_state: BULK state\n"); ++ break; ++ default: ++ dev_info(rkc->dev, "mac_state: reserved state\n"); ++ break; ++ } ++ switch (v & 0x30) { ++ case 0: ++ dev_info(rkc->dev, "parallel_state: IDLE state\n"); ++ break; ++ case 1: ++ dev_info(rkc->dev, "parallel_state: PRE state\n"); ++ break; ++ case 2: ++ dev_info(rkc->dev, "parallel_state: BULK state\n"); ++ break; ++ default: ++ dev_info(rkc->dev, "parallel_state: reserved state\n"); ++ break; ++ } ++ switch (v & 0xC0) { ++ case 0: ++ dev_info(rkc->dev, "ccm_state: IDLE state\n"); ++ break; ++ case 1: ++ dev_info(rkc->dev, "ccm_state: PRE state\n"); ++ break; ++ case 2: ++ dev_info(rkc->dev, "ccm_state: NA state\n"); ++ break; ++ default: ++ dev_info(rkc->dev, "ccm_state: reserved state\n"); ++ break; ++ } ++ switch (v & 0xF00) { ++ case 0: ++ dev_info(rkc->dev, "gcm_state: IDLE state\n"); ++ break; ++ case 1: ++ dev_info(rkc->dev, "gcm_state: PRE state\n"); ++ break; ++ case 2: ++ dev_info(rkc->dev, "gcm_state: NA state\n"); ++ break; ++ case 3: ++ dev_info(rkc->dev, "gcm_state: PC state\n"); ++ break; ++ } ++ switch (v & 0xC00) { ++ case 0x1: ++ dev_info(rkc->dev, "hash_state: IDLE state\n"); ++ break; ++ case 0x2: ++ dev_info(rkc->dev, "hash_state: IPAD state\n"); ++ break; ++ case 0x4: ++ dev_info(rkc->dev, "hash_state: TEXT state\n"); ++ break; ++ case 0x8: ++ dev_info(rkc->dev, "hash_state: OPAD state\n"); ++ break; ++ case 0x10: ++ dev_info(rkc->dev, "hash_state: OPAD EXT state\n"); ++ break; ++ default: ++ dev_info(rkc->dev, "hash_state: invalid state\n"); ++ break; ++ } ++ ++ v = readl(rkc->reg + RK2_CRYPTO_DMA_INT_ST); ++ dev_info(rkc->dev, "RK2_CRYPTO_DMA_INT_ST %x\n", v); ++} ++ ++static int rk2_cipher_need_fallback(struct skcipher_request *req) ++{ ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); ++ struct rk2_crypto_template *algt = container_of(alg, struct rk2_crypto_template, alg.skcipher.base); ++ struct scatterlist *sgs, *sgd; ++ unsigned int stodo, dtodo, len; ++ unsigned int bs = crypto_skcipher_blocksize(tfm); ++ ++ if (!req->cryptlen) ++ return true; ++ ++ if (algt->is_xts) { ++ if (sg_nents_for_len(req->src, req->cryptlen) > 1) ++ return true; ++ if (sg_nents_for_len(req->dst, req->cryptlen) > 1) ++ return true; ++ } ++ ++ len = req->cryptlen; ++ sgs = req->src; ++ sgd = req->dst; ++ while (sgs && sgd) { ++ if (!IS_ALIGNED(sgs->offset, sizeof(u32))) { ++ algt->stat_fb_align++; ++ return true; ++ } ++ if (!IS_ALIGNED(sgd->offset, sizeof(u32))) { ++ algt->stat_fb_align++; ++ return true; ++ } ++ stodo = min(len, sgs->length); ++ if (stodo % bs) { ++ algt->stat_fb_len++; ++ return true; ++ } ++ dtodo = min(len, sgd->length); ++ if (dtodo % bs) { ++ algt->stat_fb_len++; ++ return true; ++ } ++ if (stodo != dtodo) { ++ algt->stat_fb_sgdiff++; ++ return true; ++ } ++ len -= stodo; ++ sgs = sg_next(sgs); ++ sgd = sg_next(sgd); ++ } ++ return false; ++} ++ ++static int rk2_cipher_fallback(struct skcipher_request *areq) ++{ ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); ++ struct rk2_cipher_ctx *op = crypto_skcipher_ctx(tfm); ++ struct rk2_cipher_rctx *rctx = skcipher_request_ctx(areq); ++ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); ++ struct rk2_crypto_template *algt = container_of(alg, struct rk2_crypto_template, alg.skcipher.base); ++ int err; ++ ++ algt->stat_fb++; ++ ++ skcipher_request_set_tfm(&rctx->fallback_req, op->fallback_tfm); ++ skcipher_request_set_callback(&rctx->fallback_req, areq->base.flags, ++ areq->base.complete, areq->base.data); ++ skcipher_request_set_crypt(&rctx->fallback_req, areq->src, areq->dst, ++ areq->cryptlen, areq->iv); ++ if (rctx->mode & RK2_CRYPTO_DEC) ++ err = crypto_skcipher_decrypt(&rctx->fallback_req); ++ else ++ err = crypto_skcipher_encrypt(&rctx->fallback_req); ++ return err; ++} ++ ++static int rk2_cipher_handle_req(struct skcipher_request *req) ++{ ++ struct rk2_cipher_rctx *rctx = skcipher_request_ctx(req); ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ struct rk2_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk2_crypto_dev *rkc; ++ struct crypto_engine *engine; ++ ++ if (ctx->keylen == AES_KEYSIZE_192 * 2) ++ return rk2_cipher_fallback(req); ++ ++ if (rk2_cipher_need_fallback(req)) ++ return rk2_cipher_fallback(req); ++ ++ rkc = get_rk2_crypto(); ++ ++ engine = rkc->engine; ++ rctx->dev = rkc; ++ ++ return crypto_transfer_skcipher_request_to_engine(engine, req); ++} ++ ++int rk2_aes_xts_setkey(struct crypto_skcipher *cipher, const u8 *key, ++ unsigned int keylen) ++{ ++ struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher); ++ struct rk2_cipher_ctx *ctx = crypto_tfm_ctx(tfm); ++ int err; ++ ++ err = xts_verify_key(cipher, key, keylen); ++ if (err) ++ return err; ++ ++ ctx->keylen = keylen; ++ memcpy(ctx->key, key, keylen); ++ ++ return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); ++} ++ ++int rk2_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, ++ unsigned int keylen) ++{ ++ struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher); ++ struct rk2_cipher_ctx *ctx = crypto_tfm_ctx(tfm); ++ ++ if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && ++ keylen != AES_KEYSIZE_256) ++ return -EINVAL; ++ ctx->keylen = keylen; ++ memcpy(ctx->key, key, keylen); ++ ++ return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); ++} ++ ++int rk2_skcipher_encrypt(struct skcipher_request *req) ++{ ++ struct rk2_cipher_rctx *rctx = skcipher_request_ctx(req); ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); ++ struct rk2_crypto_template *algt = container_of(alg, struct rk2_crypto_template, alg.skcipher.base); ++ ++ rctx->mode = algt->rk2_mode; ++ return rk2_cipher_handle_req(req); ++} ++ ++int rk2_skcipher_decrypt(struct skcipher_request *req) ++{ ++ struct rk2_cipher_rctx *rctx = skcipher_request_ctx(req); ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); ++ struct rk2_crypto_template *algt = container_of(alg, struct rk2_crypto_template, alg.skcipher.base); ++ ++ rctx->mode = algt->rk2_mode | RK2_CRYPTO_DEC; ++ return rk2_cipher_handle_req(req); ++} ++ ++int rk2_cipher_run(struct crypto_engine *engine, void *async_req) ++{ ++ struct skcipher_request *areq = container_of(async_req, struct skcipher_request, base); ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); ++ struct rk2_cipher_rctx *rctx = skcipher_request_ctx(areq); ++ struct rk2_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct scatterlist *sgs, *sgd; ++ int err = 0; ++ int ivsize = crypto_skcipher_ivsize(tfm); ++ unsigned int len = areq->cryptlen; ++ unsigned int todo; ++ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); ++ struct rk2_crypto_template *algt = container_of(alg, struct rk2_crypto_template, alg.skcipher.base); ++ struct rk2_crypto_dev *rkc = rctx->dev; ++ struct rk2_crypto_lli *dd = &rkc->tl[0]; ++ u32 m, v; ++ u32 *rkey = (u32 *)ctx->key; ++ u32 *riv = (u32 *)areq->iv; ++ int i; ++ unsigned int offset; ++ ++ algt->stat_req++; ++ rkc->nreq++; ++ ++ m = rctx->mode | RK2_CRYPTO_ENABLE; ++ if (algt->is_xts) { ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128 * 2: ++ m |= RK2_CRYPTO_AES_128BIT_key; ++ break; ++ case AES_KEYSIZE_256 * 2: ++ m |= RK2_CRYPTO_AES_256BIT_key; ++ break; ++ default: ++ dev_err(rkc->dev, "Invalid key length %u\n", ctx->keylen); ++ return -EINVAL; ++ } ++ } else { ++ switch (ctx->keylen) { ++ case AES_KEYSIZE_128: ++ m |= RK2_CRYPTO_AES_128BIT_key; ++ break; ++ case AES_KEYSIZE_192: ++ m |= RK2_CRYPTO_AES_192BIT_key; ++ break; ++ case AES_KEYSIZE_256: ++ m |= RK2_CRYPTO_AES_256BIT_key; ++ break; ++ default: ++ dev_err(rkc->dev, "Invalid key length %u\n", ctx->keylen); ++ return -EINVAL; ++ } ++ } ++ ++ err = pm_runtime_resume_and_get(rkc->dev); ++ if (err) ++ return err; ++ ++ /* the upper bits are a write enable mask, so we need to write 1 to all ++ * upper 16 bits to allow write to the 16 lower bits ++ */ ++ m |= 0xffff0000; ++ ++ dev_dbg(rkc->dev, "%s %s len=%u keylen=%u mode=%x\n", __func__, ++ crypto_tfm_alg_name(areq->base.tfm), ++ areq->cryptlen, ctx->keylen, m); ++ sgs = areq->src; ++ sgd = areq->dst; ++ ++ while (sgs && sgd && len) { ++ ivsize = crypto_skcipher_ivsize(tfm); ++ if (areq->iv && crypto_skcipher_ivsize(tfm) > 0) { ++ if (rctx->mode & RK2_CRYPTO_DEC) { ++ offset = sgs->length - ivsize; ++ scatterwalk_map_and_copy(rctx->backup_iv, sgs, ++ offset, ivsize, 0); ++ } ++ } ++ ++ dev_dbg(rkc->dev, "SG len=%u mode=%x ivsize=%u\n", sgs->length, m, ivsize); ++ ++ if (sgs == sgd) { ++ err = dma_map_sg(rkc->dev, sgs, 1, DMA_BIDIRECTIONAL); ++ if (err != 1) { ++ dev_err(rkc->dev, "Invalid sg number %d\n", err); ++ err = -EINVAL; ++ goto theend; ++ } ++ } else { ++ err = dma_map_sg(rkc->dev, sgs, 1, DMA_TO_DEVICE); ++ if (err != 1) { ++ dev_err(rkc->dev, "Invalid sg number %d\n", err); ++ err = -EINVAL; ++ goto theend; ++ } ++ err = dma_map_sg(rkc->dev, sgd, 1, DMA_FROM_DEVICE); ++ if (err != 1) { ++ dev_err(rkc->dev, "Invalid sg number %d\n", err); ++ err = -EINVAL; ++ dma_unmap_sg(rkc->dev, sgs, 1, DMA_TO_DEVICE); ++ goto theend; ++ } ++ } ++ err = 0; ++ writel(m, rkc->reg + RK2_CRYPTO_BC_CTL); ++ ++ if (algt->is_xts) { ++ for (i = 0; i < ctx->keylen / 8; i++) { ++ v = cpu_to_be32(rkey[i]); ++ writel(v, rkc->reg + RK2_CRYPTO_KEY0 + i * 4); ++ } ++ for (i = 0; i < (ctx->keylen / 8); i++) { ++ v = cpu_to_be32(rkey[i + ctx->keylen / 8]); ++ writel(v, rkc->reg + RK2_CRYPTO_CH4_KEY0 + i * 4); ++ } ++ } else { ++ for (i = 0; i < ctx->keylen / 4; i++) { ++ v = cpu_to_be32(rkey[i]); ++ writel(v, rkc->reg + RK2_CRYPTO_KEY0 + i * 4); ++ } ++ } ++ ++ if (ivsize) { ++ for (i = 0; i < ivsize / 4; i++) ++ writel(cpu_to_be32(riv[i]), ++ rkc->reg + RK2_CRYPTO_CH0_IV_0 + i * 4); ++ writel(ivsize, rkc->reg + RK2_CRYPTO_CH0_IV_LEN); ++ } ++ if (!sgs->length) { ++ sgs = sg_next(sgs); ++ sgd = sg_next(sgd); ++ continue; ++ } ++ ++ /* The hw support multiple descriptor, so why this driver use ++ * only one descriptor ? ++ * Using one descriptor per SG seems the way to do and it works ++ * but only when doing encryption. ++ * With decryption it always fail on second descriptor. ++ * Probably the HW dont know how to use IV. ++ */ ++ todo = min(sg_dma_len(sgs), len); ++ len -= todo; ++ dd->src_addr = sg_dma_address(sgs); ++ dd->src_len = todo; ++ dd->dst_addr = sg_dma_address(sgd); ++ dd->dst_len = todo; ++ dd->iv = 0; ++ dd->next = 1; ++ ++ dd->user = RK2_LLI_CIPHER_START | RK2_LLI_STRING_FIRST | RK2_LLI_STRING_LAST; ++ dd->dma_ctrl |= RK2_LLI_DMA_CTRL_DST_INT | RK2_LLI_DMA_CTRL_LAST; ++ ++ writel(RK2_CRYPTO_DMA_INT_LISTDONE | 0x7F, rkc->reg + RK2_CRYPTO_DMA_INT_EN); ++ ++ /*writel(0x00030000, rkc->reg + RK2_CRYPTO_FIFO_CTL);*/ ++ writel(rkc->t_phy, rkc->reg + RK2_CRYPTO_DMA_LLI_ADDR); ++ ++ reinit_completion(&rkc->complete); ++ rkc->status = 0; ++ ++ writel(RK2_CRYPTO_DMA_CTL_START | 1 << 16, rkc->reg + RK2_CRYPTO_DMA_CTL); ++ ++ wait_for_completion_interruptible_timeout(&rkc->complete, ++ msecs_to_jiffies(10000)); ++ if (sgs == sgd) { ++ dma_unmap_sg(rkc->dev, sgs, 1, DMA_BIDIRECTIONAL); ++ } else { ++ dma_unmap_sg(rkc->dev, sgs, 1, DMA_TO_DEVICE); ++ dma_unmap_sg(rkc->dev, sgd, 1, DMA_FROM_DEVICE); ++ } ++ ++ if (!rkc->status) { ++ dev_err(rkc->dev, "DMA timeout\n"); ++ rk2_print(rkc); ++ err = -EFAULT; ++ goto theend; ++ } ++ if (areq->iv && ivsize > 0) { ++ offset = sgd->length - ivsize; ++ if (rctx->mode & RK2_CRYPTO_DEC) { ++ memcpy(areq->iv, rctx->backup_iv, ivsize); ++ memzero_explicit(rctx->backup_iv, ivsize); ++ } else { ++ scatterwalk_map_and_copy(areq->iv, sgd, offset, ++ ivsize, 0); ++ } ++ } ++ sgs = sg_next(sgs); ++ sgd = sg_next(sgd); ++ } ++theend: ++ writel(0xffff0000, rkc->reg + RK2_CRYPTO_BC_CTL); ++ pm_runtime_put_autosuspend(rkc->dev); ++ ++ local_bh_disable(); ++ crypto_finalize_skcipher_request(engine, areq, err); ++ local_bh_enable(); ++ return 0; ++} ++ ++int rk2_cipher_tfm_init(struct crypto_skcipher *tfm) ++{ ++ struct rk2_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ const char *name = crypto_tfm_alg_name(&tfm->base); ++ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); ++ struct rk2_crypto_template *algt = container_of(alg, struct rk2_crypto_template, alg.skcipher.base); ++ ++ ctx->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); ++ if (IS_ERR(ctx->fallback_tfm)) { ++ dev_err(algt->dev->dev, "ERROR: Cannot allocate fallback for %s %ld\n", ++ name, PTR_ERR(ctx->fallback_tfm)); ++ return PTR_ERR(ctx->fallback_tfm); ++ } ++ ++ dev_info(algt->dev->dev, "Fallback for %s is %s\n", ++ crypto_tfm_alg_driver_name(&tfm->base), ++ crypto_tfm_alg_driver_name(crypto_skcipher_tfm(ctx->fallback_tfm))); ++ ++ tfm->reqsize = sizeof(struct rk2_cipher_rctx) + ++ crypto_skcipher_reqsize(ctx->fallback_tfm); ++ ++ return 0; ++} ++ ++void rk2_cipher_tfm_exit(struct crypto_skcipher *tfm) ++{ ++ struct rk2_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ ++ memzero_explicit(ctx->key, ctx->keylen); ++ crypto_free_skcipher(ctx->fallback_tfm); ++} +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0025-RK3588-Add-HW-RNG-Support.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0025-RK3588-Add-HW-RNG-Support.patch new file mode 100644 index 000000000000..b195c28b6d61 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0025-RK3588-Add-HW-RNG-Support.patch @@ -0,0 +1,663 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Thu, 16 Nov 2023 17:49:42 +0300 +Subject: hwrng: rockchip: Add support for Rockchip HW RNG + +--- + drivers/char/hw_random/Kconfig | 13 + + drivers/char/hw_random/Makefile | 1 + + drivers/char/hw_random/rockchip-rng.c | 574 ++++++++++ + 3 files changed, 588 insertions(+) + +diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/char/hw_random/Kconfig ++++ b/drivers/char/hw_random/Kconfig +@@ -538,6 +538,19 @@ config HW_RANDOM_XIPHERA + To compile this driver as a module, choose M here: the + module will be called xiphera-trng. + ++config HW_RANDOM_ROCKCHIP ++ tristate "Rockchip Random Number Generator support" ++ depends on ARCH_ROCKCHIP ++ default HW_RANDOM ++ help ++ This driver provides kernel-side support for the Random Number ++ Generator hardware found on Rockchip cpus. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called rockchip-rng. ++ ++ If unsure, say Y. ++ + config HW_RANDOM_ARM_SMCCC_TRNG + tristate "Arm SMCCC TRNG firmware interface support" + depends on HAVE_ARM_SMCCC_DISCOVERY +diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/char/hw_random/Makefile ++++ b/drivers/char/hw_random/Makefile +@@ -35,6 +35,7 @@ obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o + obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o + obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o + obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o ++obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o + obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o + obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o + obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o +diff --git a/drivers/char/hw_random/rockchip-rng.c b/drivers/char/hw_random/rockchip-rng.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/char/hw_random/rockchip-rng.c +@@ -0,0 +1,574 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * rockchip-rng.c Random Number Generator driver for the Rockchip ++ * ++ * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd. ++ * Author: Lin Jinhan ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define _SBF(s, v) ((v) << (s)) ++#define HIWORD_UPDATE(val, mask, shift) \ ++ ((val) << (shift) | (mask) << ((shift) + 16)) ++ ++#define ROCKCHIP_AUTOSUSPEND_DELAY 100 ++#define ROCKCHIP_POLL_PERIOD_US 100 ++#define ROCKCHIP_POLL_TIMEOUT_US 50000 ++#define RK_MAX_RNG_BYTE (32) ++ ++/* start of CRYPTO V1 register define */ ++#define CRYPTO_V1_CTRL 0x0008 ++#define CRYPTO_V1_RNG_START BIT(8) ++#define CRYPTO_V1_RNG_FLUSH BIT(9) ++ ++#define CRYPTO_V1_TRNG_CTRL 0x0200 ++#define CRYPTO_V1_OSC_ENABLE BIT(16) ++#define CRYPTO_V1_TRNG_SAMPLE_PERIOD(x) (x) ++ ++#define CRYPTO_V1_TRNG_DOUT_0 0x0204 ++/* end of CRYPTO V1 register define */ ++ ++/* start of CRYPTO V2 register define */ ++#define CRYPTO_V2_RNG_DEFAULT_OFFSET 0x0400 ++#define CRYPTO_V2_RNG_CTL 0x0 ++#define CRYPTO_V2_RNG_64_BIT_LEN _SBF(4, 0x00) ++#define CRYPTO_V2_RNG_128_BIT_LEN _SBF(4, 0x01) ++#define CRYPTO_V2_RNG_192_BIT_LEN _SBF(4, 0x02) ++#define CRYPTO_V2_RNG_256_BIT_LEN _SBF(4, 0x03) ++#define CRYPTO_V2_RNG_FATESY_SOC_RING _SBF(2, 0x00) ++#define CRYPTO_V2_RNG_SLOWER_SOC_RING_0 _SBF(2, 0x01) ++#define CRYPTO_V2_RNG_SLOWER_SOC_RING_1 _SBF(2, 0x02) ++#define CRYPTO_V2_RNG_SLOWEST_SOC_RING _SBF(2, 0x03) ++#define CRYPTO_V2_RNG_ENABLE BIT(1) ++#define CRYPTO_V2_RNG_START BIT(0) ++#define CRYPTO_V2_RNG_SAMPLE_CNT 0x0004 ++#define CRYPTO_V2_RNG_DOUT_0 0x0010 ++/* end of CRYPTO V2 register define */ ++ ++/* start of TRNG_V1 register define */ ++/* TRNG is no longer subordinate to the Crypto module */ ++#define TRNG_V1_CTRL 0x0000 ++#define TRNG_V1_CTRL_NOP _SBF(0, 0x00) ++#define TRNG_V1_CTRL_RAND _SBF(0, 0x01) ++#define TRNG_V1_CTRL_SEED _SBF(0, 0x02) ++ ++#define TRNG_V1_STAT 0x0004 ++#define TRNG_V1_STAT_SEEDED BIT(9) ++#define TRNG_V1_STAT_GENERATING BIT(30) ++#define TRNG_V1_STAT_RESEEDING BIT(31) ++ ++#define TRNG_V1_MODE 0x0008 ++#define TRNG_V1_MODE_128_BIT _SBF(3, 0x00) ++#define TRNG_V1_MODE_256_BIT _SBF(3, 0x01) ++ ++#define TRNG_V1_IE 0x0010 ++#define TRNG_V1_IE_GLBL_EN BIT(31) ++#define TRNG_V1_IE_SEED_DONE_EN BIT(1) ++#define TRNG_V1_IE_RAND_RDY_EN BIT(0) ++ ++#define TRNG_V1_ISTAT 0x0014 ++#define TRNG_V1_ISTAT_RAND_RDY BIT(0) ++ ++/* RAND0 ~ RAND7 */ ++#define TRNG_V1_RAND0 0x0020 ++#define TRNG_V1_RAND7 0x003C ++ ++#define TRNG_V1_AUTO_RQSTS 0x0060 ++ ++#define TRNG_V1_VERSION 0x00F0 ++#define TRNG_v1_VERSION_CODE 0x46bc ++/* end of TRNG_V1 register define */ ++ ++/* start of RKRNG register define */ ++#define RKRNG_CTRL 0x0010 ++#define RKRNG_CTRL_INST_REQ BIT(0) ++#define RKRNG_CTRL_RESEED_REQ BIT(1) ++#define RKRNG_CTRL_TEST_REQ BIT(2) ++#define RKRNG_CTRL_SW_DRNG_REQ BIT(3) ++#define RKRNG_CTRL_SW_TRNG_REQ BIT(4) ++ ++#define RKRNG_STATE 0x0014 ++#define RKRNG_STATE_INST_ACK BIT(0) ++#define RKRNG_STATE_RESEED_ACK BIT(1) ++#define RKRNG_STATE_TEST_ACK BIT(2) ++#define RKRNG_STATE_SW_DRNG_ACK BIT(3) ++#define RKRNG_STATE_SW_TRNG_ACK BIT(4) ++ ++/* DRNG_DATA_0 ~ DNG_DATA_7 */ ++#define RKRNG_DRNG_DATA_0 0x0070 ++#define RKRNG_DRNG_DATA_7 0x008C ++ ++/* end of RKRNG register define */ ++ ++struct rk_rng_soc_data { ++ u32 default_offset; ++ ++ int (*rk_rng_init)(struct hwrng *rng); ++ int (*rk_rng_read)(struct hwrng *rng, void *buf, size_t max, bool wait); ++}; ++ ++struct rk_rng { ++ struct device *dev; ++ struct hwrng rng; ++ void __iomem *mem; ++ struct rk_rng_soc_data *soc_data; ++ int clk_num; ++ struct clk_bulk_data *clk_bulks; ++}; ++ ++static void rk_rng_writel(struct rk_rng *rng, u32 val, u32 offset) ++{ ++ __raw_writel(val, rng->mem + offset); ++} ++ ++static u32 rk_rng_readl(struct rk_rng *rng, u32 offset) ++{ ++ return __raw_readl(rng->mem + offset); ++} ++ ++static int rk_rng_init(struct hwrng *rng) ++{ ++ int ret; ++ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); ++ ++ dev_dbg(rk_rng->dev, "clk_bulk_prepare_enable.\n"); ++ ++ ret = clk_bulk_prepare_enable(rk_rng->clk_num, rk_rng->clk_bulks); ++ if (ret < 0) { ++ dev_err(rk_rng->dev, "failed to enable clks %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void rk_rng_cleanup(struct hwrng *rng) ++{ ++ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); ++ ++ dev_dbg(rk_rng->dev, "clk_bulk_disable_unprepare.\n"); ++ clk_bulk_disable_unprepare(rk_rng->clk_num, rk_rng->clk_bulks); ++} ++ ++static int rk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) ++{ ++ int ret; ++ int read_len = 0; ++ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); ++ ++ if (!rk_rng->soc_data->rk_rng_read) ++ return -EFAULT; ++ ++ ret = pm_runtime_get_sync(rk_rng->dev); ++ if (ret < 0) { ++ pm_runtime_put_noidle(rk_rng->dev); ++ return ret; ++ } ++ ++ ret = 0; ++ while (max > ret) { ++ read_len = rk_rng->soc_data->rk_rng_read(rng, buf + ret, ++ max - ret, wait); ++ if (read_len < 0) { ++ ret = read_len; ++ break; ++ } ++ ret += read_len; ++ } ++ ++ pm_runtime_mark_last_busy(rk_rng->dev); ++ pm_runtime_put_sync_autosuspend(rk_rng->dev); ++ ++ return ret; ++} ++ ++static void rk_rng_read_regs(struct rk_rng *rng, u32 offset, void *buf, ++ size_t size) ++{ ++ u32 i; ++ ++ for (i = 0; i < size; i += 4) ++ *(u32 *)(buf + i) = be32_to_cpu(rk_rng_readl(rng, offset + i)); ++} ++ ++static int crypto_v1_read(struct hwrng *rng, void *buf, size_t max, bool wait) ++{ ++ int ret = 0; ++ u32 reg_ctrl = 0; ++ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); ++ ++ /* enable osc_ring to get entropy, sample period is set as 100 */ ++ reg_ctrl = CRYPTO_V1_OSC_ENABLE | CRYPTO_V1_TRNG_SAMPLE_PERIOD(100); ++ rk_rng_writel(rk_rng, reg_ctrl, CRYPTO_V1_TRNG_CTRL); ++ ++ reg_ctrl = HIWORD_UPDATE(CRYPTO_V1_RNG_START, CRYPTO_V1_RNG_START, 0); ++ ++ rk_rng_writel(rk_rng, reg_ctrl, CRYPTO_V1_CTRL); ++ ++ ret = read_poll_timeout(rk_rng_readl, reg_ctrl, ++ !(reg_ctrl & CRYPTO_V1_RNG_START), ++ ROCKCHIP_POLL_PERIOD_US, ++ ROCKCHIP_POLL_TIMEOUT_US, false, ++ rk_rng, CRYPTO_V1_CTRL); ++ ++ if (ret < 0) ++ goto out; ++ ++ ret = min_t(size_t, max, RK_MAX_RNG_BYTE); ++ ++ rk_rng_read_regs(rk_rng, CRYPTO_V1_TRNG_DOUT_0, buf, ret); ++ ++out: ++ /* close TRNG */ ++ rk_rng_writel(rk_rng, HIWORD_UPDATE(0, CRYPTO_V1_RNG_START, 0), ++ CRYPTO_V1_CTRL); ++ ++ return ret; ++} ++ ++static int crypto_v2_read(struct hwrng *rng, void *buf, size_t max, bool wait) ++{ ++ int ret = 0; ++ u32 reg_ctrl = 0; ++ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); ++ ++ /* enable osc_ring to get entropy, sample period is set as 100 */ ++ rk_rng_writel(rk_rng, 100, CRYPTO_V2_RNG_SAMPLE_CNT); ++ ++ reg_ctrl |= CRYPTO_V2_RNG_256_BIT_LEN; ++ reg_ctrl |= CRYPTO_V2_RNG_SLOWER_SOC_RING_0; ++ reg_ctrl |= CRYPTO_V2_RNG_ENABLE; ++ reg_ctrl |= CRYPTO_V2_RNG_START; ++ ++ rk_rng_writel(rk_rng, HIWORD_UPDATE(reg_ctrl, 0xffff, 0), ++ CRYPTO_V2_RNG_CTL); ++ ++ ret = read_poll_timeout(rk_rng_readl, reg_ctrl, ++ !(reg_ctrl & CRYPTO_V2_RNG_START), ++ ROCKCHIP_POLL_PERIOD_US, ++ ROCKCHIP_POLL_TIMEOUT_US, false, ++ rk_rng, CRYPTO_V2_RNG_CTL); ++ if (ret < 0) ++ goto out; ++ ++ ret = min_t(size_t, max, RK_MAX_RNG_BYTE); ++ ++ rk_rng_read_regs(rk_rng, CRYPTO_V2_RNG_DOUT_0, buf, ret); ++ ++out: ++ /* close TRNG */ ++ rk_rng_writel(rk_rng, HIWORD_UPDATE(0, 0xffff, 0), CRYPTO_V2_RNG_CTL); ++ ++ return ret; ++} ++ ++static int trng_v1_init(struct hwrng *rng) ++{ ++ int ret; ++ uint32_t auto_reseed_cnt = 1000; ++ uint32_t reg_ctrl, status, version; ++ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); ++ ++ version = rk_rng_readl(rk_rng, TRNG_V1_VERSION); ++ if (version != TRNG_v1_VERSION_CODE) { ++ dev_err(rk_rng->dev, ++ "wrong trng version, expected = %08x, actual = %08x\n", ++ TRNG_V1_VERSION, version); ++ ret = -EFAULT; ++ goto exit; ++ } ++ ++ status = rk_rng_readl(rk_rng, TRNG_V1_STAT); ++ ++ /* TRNG should wait RAND_RDY triggered if it is busy or not seeded */ ++ if (!(status & TRNG_V1_STAT_SEEDED) || ++ (status & TRNG_V1_STAT_GENERATING) || ++ (status & TRNG_V1_STAT_RESEEDING)) { ++ uint32_t mask = TRNG_V1_STAT_SEEDED | ++ TRNG_V1_STAT_GENERATING | ++ TRNG_V1_STAT_RESEEDING; ++ ++ udelay(10); ++ ++ /* wait for GENERATING and RESEEDING flag to clear */ ++ read_poll_timeout(rk_rng_readl, reg_ctrl, ++ (reg_ctrl & mask) == TRNG_V1_STAT_SEEDED, ++ ROCKCHIP_POLL_PERIOD_US, ++ ROCKCHIP_POLL_TIMEOUT_US, false, ++ rk_rng, TRNG_V1_STAT); ++ } ++ ++ /* clear ISTAT flag because trng may auto reseeding when power on */ ++ reg_ctrl = rk_rng_readl(rk_rng, TRNG_V1_ISTAT); ++ rk_rng_writel(rk_rng, reg_ctrl, TRNG_V1_ISTAT); ++ ++ /* auto reseed after (auto_reseed_cnt * 16) byte rand generate */ ++ rk_rng_writel(rk_rng, auto_reseed_cnt, TRNG_V1_AUTO_RQSTS); ++ ++ ret = 0; ++exit: ++ ++ return ret; ++} ++ ++static int trng_v1_read(struct hwrng *rng, void *buf, size_t max, bool wait) ++{ ++ int ret = 0; ++ u32 reg_ctrl = 0; ++ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); ++ ++ /* clear ISTAT anyway */ ++ reg_ctrl = rk_rng_readl(rk_rng, TRNG_V1_ISTAT); ++ rk_rng_writel(rk_rng, reg_ctrl, TRNG_V1_ISTAT); ++ ++ /* generate 256bit random */ ++ rk_rng_writel(rk_rng, TRNG_V1_MODE_256_BIT, TRNG_V1_MODE); ++ rk_rng_writel(rk_rng, TRNG_V1_CTRL_RAND, TRNG_V1_CTRL); ++ ++ /* ++ * Generate2 56 bit random data will cost 1024 clock cycles. ++ * Estimated at 150M RNG module frequency, it takes 6.7 microseconds. ++ */ ++ udelay(10); ++ reg_ctrl = rk_rng_readl(rk_rng, TRNG_V1_ISTAT); ++ if (!(reg_ctrl & TRNG_V1_ISTAT_RAND_RDY)) { ++ /* wait RAND_RDY triggered */ ++ ret = read_poll_timeout(rk_rng_readl, reg_ctrl, ++ (reg_ctrl & TRNG_V1_ISTAT_RAND_RDY), ++ ROCKCHIP_POLL_PERIOD_US, ++ ROCKCHIP_POLL_TIMEOUT_US, false, ++ rk_rng, TRNG_V1_ISTAT); ++ if (ret < 0) ++ goto out; ++ } ++ ++ ret = min_t(size_t, max, RK_MAX_RNG_BYTE); ++ ++ rk_rng_read_regs(rk_rng, TRNG_V1_RAND0, buf, ret); ++ ++ /* clear all status flag */ ++ rk_rng_writel(rk_rng, reg_ctrl, TRNG_V1_ISTAT); ++out: ++ /* close TRNG */ ++ rk_rng_writel(rk_rng, TRNG_V1_CTRL_NOP, TRNG_V1_CTRL); ++ ++ return ret; ++} ++ ++static int rkrng_init(struct hwrng *rng) ++{ ++ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); ++ u32 reg = 0; ++ ++ rk_rng_writel(rk_rng, HIWORD_UPDATE(0, 0xffff, 0), RKRNG_CTRL); ++ ++ reg = rk_rng_readl(rk_rng, RKRNG_STATE); ++ rk_rng_writel(rk_rng, reg, RKRNG_STATE); ++ ++ return 0; ++} ++ ++static int rkrng_read(struct hwrng *rng, void *buf, size_t max, bool wait) ++{ ++ struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); ++ u32 reg_ctrl = 0; ++ int ret; ++ ++ reg_ctrl = RKRNG_CTRL_SW_DRNG_REQ; ++ ++ rk_rng_writel(rk_rng, HIWORD_UPDATE(reg_ctrl, 0xffff, 0), RKRNG_CTRL); ++ ++ ret = readl_poll_timeout(rk_rng->mem + RKRNG_STATE, reg_ctrl, ++ (reg_ctrl & RKRNG_STATE_SW_DRNG_ACK), ++ ROCKCHIP_POLL_PERIOD_US, ++ ROCKCHIP_POLL_TIMEOUT_US); ++ ++ if (ret) ++ goto exit; ++ ++ rk_rng_writel(rk_rng, reg_ctrl, RKRNG_STATE); ++ ++ ret = min_t(size_t, max, RK_MAX_RNG_BYTE); ++ ++ rk_rng_read_regs(rk_rng, RKRNG_DRNG_DATA_0, buf, ret); ++ ++exit: ++ /* close TRNG */ ++ rk_rng_writel(rk_rng, HIWORD_UPDATE(0, 0xffff, 0), RKRNG_CTRL); ++ ++ return ret; ++} ++ ++static const struct rk_rng_soc_data crypto_v1_soc_data = { ++ .default_offset = 0, ++ ++ .rk_rng_read = crypto_v1_read, ++}; ++ ++static const struct rk_rng_soc_data crypto_v2_soc_data = { ++ .default_offset = CRYPTO_V2_RNG_DEFAULT_OFFSET, ++ ++ .rk_rng_read = crypto_v2_read, ++}; ++ ++static const struct rk_rng_soc_data trng_v1_soc_data = { ++ .default_offset = 0, ++ ++ .rk_rng_init = trng_v1_init, ++ .rk_rng_read = trng_v1_read, ++}; ++ ++static const struct rk_rng_soc_data rkrng_soc_data = { ++ .default_offset = 0, ++ ++ .rk_rng_init = rkrng_init, ++ .rk_rng_read = rkrng_read, ++}; ++ ++static const struct of_device_id rk_rng_dt_match[] = { ++ { ++ .compatible = "rockchip,cryptov1-rng", ++ .data = (void *)&crypto_v1_soc_data, ++ }, ++ { ++ .compatible = "rockchip,cryptov2-rng", ++ .data = (void *)&crypto_v2_soc_data, ++ }, ++ { ++ .compatible = "rockchip,trngv1", ++ .data = (void *)&trng_v1_soc_data, ++ }, ++ { ++ .compatible = "rockchip,rkrng", ++ .data = (void *)&rkrng_soc_data, ++ }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, rk_rng_dt_match); ++ ++static int rk_rng_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct rk_rng *rk_rng; ++ struct device_node *np = pdev->dev.of_node; ++ const struct of_device_id *match; ++ resource_size_t map_size; ++ ++ dev_dbg(&pdev->dev, "probing...\n"); ++ rk_rng = devm_kzalloc(&pdev->dev, sizeof(struct rk_rng), GFP_KERNEL); ++ if (!rk_rng) ++ return -ENOMEM; ++ ++ match = of_match_node(rk_rng_dt_match, np); ++ rk_rng->soc_data = (struct rk_rng_soc_data *)match->data; ++ ++ rk_rng->dev = &pdev->dev; ++ rk_rng->rng.name = "rockchip"; ++#ifndef CONFIG_PM ++ rk_rng->rng.init = rk_rng_init; ++ rk_rng->rng.cleanup = rk_rng_cleanup, ++#endif ++ rk_rng->rng.read = rk_rng_read; ++ rk_rng->rng.quality = 999; ++ ++ rk_rng->mem = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, &map_size); ++ if (IS_ERR(rk_rng->mem)) ++ return PTR_ERR(rk_rng->mem); ++ ++ /* compatible with crypto v2 module */ ++ /* ++ * With old dtsi configurations, the RNG base was equal to the crypto ++ * base, so both drivers could not be enabled at the same time. ++ * RNG base = CRYPTO base + RNG offset ++ * (Since RK356X, RNG module is no longer belongs to CRYPTO module) ++ * ++ * With new dtsi configurations, CRYPTO regs is divided into two parts ++ * |---cipher---|---rng---|---pka---|, and RNG base is real RNG base. ++ * RNG driver and CRYPTO driver could be enabled at the same time. ++ */ ++ if (map_size > rk_rng->soc_data->default_offset) ++ rk_rng->mem += rk_rng->soc_data->default_offset; ++ ++ rk_rng->clk_num = devm_clk_bulk_get_all(&pdev->dev, &rk_rng->clk_bulks); ++ if (rk_rng->clk_num < 0) { ++ dev_err(&pdev->dev, "failed to get clks property\n"); ++ return -ENODEV; ++ } ++ ++ platform_set_drvdata(pdev, rk_rng); ++ ++ pm_runtime_set_autosuspend_delay(&pdev->dev, ++ ROCKCHIP_AUTOSUSPEND_DELAY); ++ pm_runtime_use_autosuspend(&pdev->dev); ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = devm_hwrng_register(&pdev->dev, &rk_rng->rng); ++ if (ret) { ++ pm_runtime_dont_use_autosuspend(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ } ++ ++ /* for some platform need hardware operation when probe */ ++ if (rk_rng->soc_data->rk_rng_init) { ++ pm_runtime_get_sync(rk_rng->dev); ++ ++ ret = rk_rng->soc_data->rk_rng_init(&rk_rng->rng); ++ ++ pm_runtime_mark_last_busy(rk_rng->dev); ++ pm_runtime_put_sync_autosuspend(rk_rng->dev); ++ } ++ ++ return ret; ++} ++ ++#ifdef CONFIG_PM ++static int rk_rng_runtime_suspend(struct device *dev) ++{ ++ struct rk_rng *rk_rng = dev_get_drvdata(dev); ++ ++ rk_rng_cleanup(&rk_rng->rng); ++ ++ return 0; ++} ++ ++static int rk_rng_runtime_resume(struct device *dev) ++{ ++ struct rk_rng *rk_rng = dev_get_drvdata(dev); ++ ++ return rk_rng_init(&rk_rng->rng); ++} ++ ++static const struct dev_pm_ops rk_rng_pm_ops = { ++ SET_RUNTIME_PM_OPS(rk_rng_runtime_suspend, ++ rk_rng_runtime_resume, NULL) ++ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, ++ pm_runtime_force_resume) ++}; ++ ++#endif ++ ++static struct platform_driver rk_rng_driver = { ++ .driver = { ++ .name = "rockchip-rng", ++#ifdef CONFIG_PM ++ .pm = &rk_rng_pm_ops, ++#endif ++ .of_match_table = rk_rng_dt_match, ++ }, ++ .probe = rk_rng_probe, ++}; ++ ++module_platform_driver(rk_rng_driver); ++ ++MODULE_DESCRIPTION("ROCKCHIP H/W Random Number Generator driver"); ++MODULE_AUTHOR("Lin Jinhan "); ++MODULE_LICENSE("GPL v2"); +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Thu, 16 Nov 2023 17:52:35 +0300 +Subject: arm64: dts: Add HW RNG support to RK3588S + +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -1923,6 +1923,16 @@ crypto: crypto@fe370000 { + status = "okay"; + }; + ++ rng: rng@fe378000 { ++ compatible = "rockchip,trngv1"; ++ reg = <0x0 0xfe378000 0x0 0x200>; ++ interrupts = ; ++ clocks = <&scmi_clk SCMI_HCLK_SECURE_NS>; ++ clock-names = "hclk_trng"; ++ resets = <&scmi_reset SRST_H_TRNG_NS>; ++ reset-names = "reset"; ++ }; ++ + i2s0_8ch: i2s@fe470000 { + compatible = "rockchip,rk3588-i2s-tdm"; + reg = <0x0 0xfe470000 0x0 0x1000>; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0135-phy-rockchip-Add-Samsung-HDMI-eDP-Combo-PHY-driver.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0135-phy-rockchip-Add-Samsung-HDMI-eDP-Combo-PHY-driver.patch new file mode 100644 index 000000000000..ab55331f8eb9 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0135-phy-rockchip-Add-Samsung-HDMI-eDP-Combo-PHY-driver.patch @@ -0,0 +1,1091 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Wed, 14 Feb 2024 13:45:37 +0200 +Subject: phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver + +Add driver for the HDMI/eDP TX Combo PHY found on Rockchip RK3588 SoC. + +The PHY is based on a Samsung IP block and supports HDMI 2.1 TMDS, FRL +and eDP links. The maximum data rate is 12Gbps (FRL), while the minimum +is 250Mbps (TMDS). + +Only the TMDS link is currently supported. + +Co-developed-by: Algea Cao +Signed-off-by: Algea Cao +Tested-by: Heiko Stuebner +Signed-off-by: Cristian Ciocaltea +--- + drivers/phy/rockchip/Kconfig | 8 + + drivers/phy/rockchip/Makefile | 1 + + drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 1028 ++++++++++ + 3 files changed, 1037 insertions(+) + +diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/phy/rockchip/Kconfig ++++ b/drivers/phy/rockchip/Kconfig +@@ -83,6 +83,14 @@ config PHY_ROCKCHIP_PCIE + help + Enable this to support the Rockchip PCIe PHY. + ++config PHY_ROCKCHIP_SAMSUNG_HDPTX ++ tristate "Rockchip Samsung HDMI/eDP Combo PHY driver" ++ depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF ++ select GENERIC_PHY ++ help ++ Enable this to support the Rockchip HDMI/eDP Combo PHY ++ with Samsung IP block. ++ + config PHY_ROCKCHIP_SNPS_PCIE3 + tristate "Rockchip Snps PCIe3 PHY Driver" + depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST +diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/phy/rockchip/Makefile ++++ b/drivers/phy/rockchip/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o + obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o + obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o + obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o ++obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX) += phy-rockchip-samsung-hdptx.o + obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o + obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o + obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o +diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +@@ -0,0 +1,1028 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd. ++ * Copyright (c) 2024 Collabora Ltd. ++ * ++ * Author: Algea Cao ++ * Author: Cristian Ciocaltea ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define GRF_HDPTX_CON0 0x00 ++#define HDPTX_I_PLL_EN BIT(7) ++#define HDPTX_I_BIAS_EN BIT(6) ++#define HDPTX_I_BGR_EN BIT(5) ++#define GRF_HDPTX_STATUS 0x80 ++#define HDPTX_O_PLL_LOCK_DONE BIT(3) ++#define HDPTX_O_PHY_CLK_RDY BIT(2) ++#define HDPTX_O_PHY_RDY BIT(1) ++#define HDPTX_O_SB_RDY BIT(0) ++ ++#define HDTPX_REG(_n, _min, _max) \ ++ ( \ ++ BUILD_BUG_ON_ZERO((0x##_n) < (0x##_min)) + \ ++ BUILD_BUG_ON_ZERO((0x##_n) > (0x##_max)) + \ ++ ((0x##_n) * 4) \ ++ ) ++ ++#define CMN_REG(n) HDTPX_REG(n, 0000, 00a7) ++#define SB_REG(n) HDTPX_REG(n, 0100, 0129) ++#define LNTOP_REG(n) HDTPX_REG(n, 0200, 0229) ++#define LANE_REG(n) HDTPX_REG(n, 0300, 062d) ++ ++/* CMN_REG(0008) */ ++#define LCPLL_EN_MASK BIT(6) ++#define LCPLL_LCVCO_MODE_EN_MASK BIT(4) ++/* CMN_REG(001e) */ ++#define LCPLL_PI_EN_MASK BIT(5) ++#define LCPLL_100M_CLK_EN_MASK BIT(0) ++/* CMN_REG(0025) */ ++#define LCPLL_PMS_IQDIV_RSTN BIT(4) ++/* CMN_REG(0028) */ ++#define LCPLL_SDC_FRAC_EN BIT(2) ++#define LCPLL_SDC_FRAC_RSTN BIT(0) ++/* CMN_REG(002d) */ ++#define LCPLL_SDC_N_MASK GENMASK(3, 1) ++/* CMN_REG(002e) */ ++#define LCPLL_SDC_NUMBERATOR_MASK GENMASK(5, 0) ++/* CMN_REG(002f) */ ++#define LCPLL_SDC_DENOMINATOR_MASK GENMASK(7, 2) ++#define LCPLL_SDC_NDIV_RSTN BIT(0) ++/* CMN_REG(003d) */ ++#define ROPLL_LCVCO_EN BIT(4) ++/* CMN_REG(004e) */ ++#define ROPLL_PI_EN BIT(5) ++/* CMN_REG(005c) */ ++#define ROPLL_PMS_IQDIV_RSTN BIT(5) ++/* CMN_REG(005e) */ ++#define ROPLL_SDM_EN_MASK BIT(6) ++#define ROPLL_SDM_FRAC_EN_RBR BIT(3) ++#define ROPLL_SDM_FRAC_EN_HBR BIT(2) ++#define ROPLL_SDM_FRAC_EN_HBR2 BIT(1) ++#define ROPLL_SDM_FRAC_EN_HBR3 BIT(0) ++/* CMN_REG(0064) */ ++#define ROPLL_SDM_NUM_SIGN_RBR_MASK BIT(3) ++/* CMN_REG(0069) */ ++#define ROPLL_SDC_N_RBR_MASK GENMASK(2, 0) ++/* CMN_REG(0074) */ ++#define ROPLL_SDC_NDIV_RSTN BIT(2) ++#define ROPLL_SSC_EN BIT(0) ++/* CMN_REG(0081) */ ++#define OVRD_PLL_CD_CLK_EN BIT(8) ++#define PLL_CD_HSCLK_EAST_EN BIT(0) ++/* CMN_REG(0086) */ ++#define PLL_PCG_POSTDIV_SEL_MASK GENMASK(7, 4) ++#define PLL_PCG_CLK_SEL_MASK GENMASK(3, 1) ++#define PLL_PCG_CLK_EN BIT(0) ++/* CMN_REG(0087) */ ++#define PLL_FRL_MODE_EN BIT(3) ++#define PLL_TX_HS_CLK_EN BIT(2) ++/* CMN_REG(0089) */ ++#define LCPLL_ALONE_MODE BIT(1) ++/* CMN_REG(0097) */ ++#define DIG_CLK_SEL BIT(1) ++#define ROPLL_REF BIT(1) ++#define LCPLL_REF 0 ++/* CMN_REG(0099) */ ++#define CMN_ROPLL_ALONE_MODE BIT(2) ++#define ROPLL_ALONE_MODE BIT(2) ++/* CMN_REG(009a) */ ++#define HS_SPEED_SEL BIT(0) ++#define DIV_10_CLOCK BIT(0) ++/* CMN_REG(009b) */ ++#define IS_SPEED_SEL BIT(4) ++#define LINK_SYMBOL_CLOCK BIT(4) ++#define LINK_SYMBOL_CLOCK1_2 0 ++ ++/* SB_REG(0102) */ ++#define OVRD_SB_RXTERM_EN_MASK BIT(5) ++#define SB_RXTERM_EN_MASK BIT(4) ++#define ANA_SB_RXTERM_OFFSP_MASK GENMASK(3, 0) ++/* SB_REG(0103) */ ++#define ANA_SB_RXTERM_OFFSN_MASK GENMASK(6, 3) ++#define OVRD_SB_RX_RESCAL_DONE_MASK BIT(1) ++#define SB_RX_RESCAL_DONE_MASK BIT(0) ++/* SB_REG(0104) */ ++#define OVRD_SB_EN_MASK BIT(5) ++#define SB_EN_MASK BIT(4) ++/* SB_REG(0105) */ ++#define OVRD_SB_EARC_CMDC_EN_MASK BIT(6) ++#define SB_EARC_CMDC_EN_MASK BIT(5) ++#define ANA_SB_TX_HLVL_PROG_MASK GENMASK(2, 0) ++/* SB_REG(0106) */ ++#define ANA_SB_TX_LLVL_PROG_MASK GENMASK(6, 4) ++/* SB_REG(0109) */ ++#define ANA_SB_DMRX_AFC_DIV_RATIO_MASK GENMASK(2, 0) ++/* SB_REG(010f) */ ++#define OVRD_SB_VREG_EN_MASK BIT(7) ++#define SB_VREG_EN_MASK BIT(6) ++#define OVRD_SB_VREG_LPF_BYPASS_MASK BIT(5) ++#define SB_VREG_LPF_BYPASS_MASK BIT(4) ++#define ANA_SB_VREG_GAIN_CTRL_MASK GENMASK(3, 0) ++/* SB_REG(0110) */ ++#define ANA_SB_VREG_REF_SEL_MASK BIT(0) ++/* SB_REG(0113) */ ++#define SB_RX_RCAL_OPT_CODE_MASK GENMASK(5, 4) ++#define SB_RX_RTERM_CTRL_MASK GENMASK(3, 0) ++/* SB_REG(0114) */ ++#define SB_TG_SB_EN_DELAY_TIME_MASK GENMASK(5, 3) ++#define SB_TG_RXTERM_EN_DELAY_TIME_MASK GENMASK(2, 0) ++/* SB_REG(0115) */ ++#define SB_READY_DELAY_TIME_MASK GENMASK(5, 3) ++#define SB_TG_OSC_EN_DELAY_TIME_MASK GENMASK(2, 0) ++/* SB_REG(0116) */ ++#define AFC_RSTN_DELAY_TIME_MASK GENMASK(6, 4) ++/* SB_REG(0117) */ ++#define FAST_PULSE_TIME_MASK GENMASK(3, 0) ++/* SB_REG(011b) */ ++#define SB_EARC_SIG_DET_BYPASS_MASK BIT(4) ++#define SB_AFC_TOL_MASK GENMASK(3, 0) ++/* SB_REG(011f) */ ++#define SB_PWM_AFC_CTRL_MASK GENMASK(7, 2) ++#define SB_RCAL_RSTN_MASK BIT(1) ++/* SB_REG(0120) */ ++#define SB_EARC_EN_MASK BIT(1) ++#define SB_EARC_AFC_EN_MASK BIT(2) ++/* SB_REG(0123) */ ++#define OVRD_SB_READY_MASK BIT(5) ++#define SB_READY_MASK BIT(4) ++ ++/* LNTOP_REG(0200) */ ++#define PROTOCOL_SEL BIT(2) ++#define HDMI_MODE BIT(2) ++#define HDMI_TMDS_FRL_SEL BIT(1) ++/* LNTOP_REG(0206) */ ++#define DATA_BUS_SEL BIT(0) ++#define DATA_BUS_36_40 BIT(0) ++/* LNTOP_REG(0207) */ ++#define LANE_EN 0xf ++#define ALL_LANE_EN 0xf ++ ++/* LANE_REG(0312) */ ++#define LN0_TX_SER_RATE_SEL_RBR BIT(5) ++#define LN0_TX_SER_RATE_SEL_HBR BIT(4) ++#define LN0_TX_SER_RATE_SEL_HBR2 BIT(3) ++#define LN0_TX_SER_RATE_SEL_HBR3 BIT(2) ++/* LANE_REG(0412) */ ++#define LN1_TX_SER_RATE_SEL_RBR BIT(5) ++#define LN1_TX_SER_RATE_SEL_HBR BIT(4) ++#define LN1_TX_SER_RATE_SEL_HBR2 BIT(3) ++#define LN1_TX_SER_RATE_SEL_HBR3 BIT(2) ++/* LANE_REG(0512) */ ++#define LN2_TX_SER_RATE_SEL_RBR BIT(5) ++#define LN2_TX_SER_RATE_SEL_HBR BIT(4) ++#define LN2_TX_SER_RATE_SEL_HBR2 BIT(3) ++#define LN2_TX_SER_RATE_SEL_HBR3 BIT(2) ++/* LANE_REG(0612) */ ++#define LN3_TX_SER_RATE_SEL_RBR BIT(5) ++#define LN3_TX_SER_RATE_SEL_HBR BIT(4) ++#define LN3_TX_SER_RATE_SEL_HBR2 BIT(3) ++#define LN3_TX_SER_RATE_SEL_HBR3 BIT(2) ++ ++struct lcpll_config { ++ u32 bit_rate; ++ u8 lcvco_mode_en; ++ u8 pi_en; ++ u8 clk_en_100m; ++ u8 pms_mdiv; ++ u8 pms_mdiv_afc; ++ u8 pms_pdiv; ++ u8 pms_refdiv; ++ u8 pms_sdiv; ++ u8 pi_cdiv_rstn; ++ u8 pi_cdiv_sel; ++ u8 sdm_en; ++ u8 sdm_rstn; ++ u8 sdc_frac_en; ++ u8 sdc_rstn; ++ u8 sdm_deno; ++ u8 sdm_num_sign; ++ u8 sdm_num; ++ u8 sdc_n; ++ u8 sdc_n2; ++ u8 sdc_num; ++ u8 sdc_deno; ++ u8 sdc_ndiv_rstn; ++ u8 ssc_en; ++ u8 ssc_fm_dev; ++ u8 ssc_fm_freq; ++ u8 ssc_clk_div_sel; ++ u8 cd_tx_ser_rate_sel; ++}; ++ ++struct ropll_config { ++ u32 bit_rate; ++ u8 pms_mdiv; ++ u8 pms_mdiv_afc; ++ u8 pms_pdiv; ++ u8 pms_refdiv; ++ u8 pms_sdiv; ++ u8 pms_iqdiv_rstn; ++ u8 ref_clk_sel; ++ u8 sdm_en; ++ u8 sdm_rstn; ++ u8 sdc_frac_en; ++ u8 sdc_rstn; ++ u8 sdm_clk_div; ++ u8 sdm_deno; ++ u8 sdm_num_sign; ++ u8 sdm_num; ++ u8 sdc_n; ++ u8 sdc_num; ++ u8 sdc_deno; ++ u8 sdc_ndiv_rstn; ++ u8 ssc_en; ++ u8 ssc_fm_dev; ++ u8 ssc_fm_freq; ++ u8 ssc_clk_div_sel; ++ u8 ana_cpp_ctrl; ++ u8 ana_lpf_c_sel; ++ u8 cd_tx_ser_rate_sel; ++}; ++ ++enum rk_hdptx_reset { ++ RST_PHY = 0, ++ RST_APB, ++ RST_INIT, ++ RST_CMN, ++ RST_LANE, ++ RST_ROPLL, ++ RST_LCPLL, ++ RST_MAX ++}; ++ ++struct rk_hdptx_phy { ++ struct device *dev; ++ struct regmap *regmap; ++ struct regmap *grf; ++ ++ struct phy *phy; ++ struct phy_config *phy_cfg; ++ struct clk_bulk_data *clks; ++ int nr_clks; ++ struct reset_control_bulk_data rsts[RST_MAX]; ++}; ++ ++static const struct ropll_config ropll_tmds_cfg[] = { ++ { 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, ++ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 3712500, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, ++ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 2970000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, ++ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 1620000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10, ++ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 1856250, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, ++ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 1540000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1, ++ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 1485000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5, ++ 0x10, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 1462500, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1, ++ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 1190000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1, ++ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 1065000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1, ++ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 1080000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0, ++ 0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 855000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1, ++ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 835000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0, ++ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 928125, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, ++ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 742500, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0, ++ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1, ++ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5, ++ 1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0, ++ 0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 270000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0, ++ 0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1, ++ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++}; ++ ++static const struct reg_sequence rk_hdtpx_common_cmn_init_seq[] = { ++ REG_SEQ0(CMN_REG(0009), 0x0c), ++ REG_SEQ0(CMN_REG(000a), 0x83), ++ REG_SEQ0(CMN_REG(000b), 0x06), ++ REG_SEQ0(CMN_REG(000c), 0x20), ++ REG_SEQ0(CMN_REG(000d), 0xb8), ++ REG_SEQ0(CMN_REG(000e), 0x0f), ++ REG_SEQ0(CMN_REG(000f), 0x0f), ++ REG_SEQ0(CMN_REG(0010), 0x04), ++ REG_SEQ0(CMN_REG(0011), 0x00), ++ REG_SEQ0(CMN_REG(0012), 0x26), ++ REG_SEQ0(CMN_REG(0013), 0x22), ++ REG_SEQ0(CMN_REG(0014), 0x24), ++ REG_SEQ0(CMN_REG(0015), 0x77), ++ REG_SEQ0(CMN_REG(0016), 0x08), ++ REG_SEQ0(CMN_REG(0017), 0x00), ++ REG_SEQ0(CMN_REG(0018), 0x04), ++ REG_SEQ0(CMN_REG(0019), 0x48), ++ REG_SEQ0(CMN_REG(001a), 0x01), ++ REG_SEQ0(CMN_REG(001b), 0x00), ++ REG_SEQ0(CMN_REG(001c), 0x01), ++ REG_SEQ0(CMN_REG(001d), 0x64), ++ REG_SEQ0(CMN_REG(001f), 0x00), ++ REG_SEQ0(CMN_REG(0026), 0x53), ++ REG_SEQ0(CMN_REG(0029), 0x01), ++ REG_SEQ0(CMN_REG(0030), 0x00), ++ REG_SEQ0(CMN_REG(0031), 0x20), ++ REG_SEQ0(CMN_REG(0032), 0x30), ++ REG_SEQ0(CMN_REG(0033), 0x0b), ++ REG_SEQ0(CMN_REG(0034), 0x23), ++ REG_SEQ0(CMN_REG(0035), 0x00), ++ REG_SEQ0(CMN_REG(0038), 0x00), ++ REG_SEQ0(CMN_REG(0039), 0x00), ++ REG_SEQ0(CMN_REG(003a), 0x00), ++ REG_SEQ0(CMN_REG(003b), 0x00), ++ REG_SEQ0(CMN_REG(003c), 0x80), ++ REG_SEQ0(CMN_REG(003e), 0x0c), ++ REG_SEQ0(CMN_REG(003f), 0x83), ++ REG_SEQ0(CMN_REG(0040), 0x06), ++ REG_SEQ0(CMN_REG(0041), 0x20), ++ REG_SEQ0(CMN_REG(0042), 0xb8), ++ REG_SEQ0(CMN_REG(0043), 0x00), ++ REG_SEQ0(CMN_REG(0044), 0x46), ++ REG_SEQ0(CMN_REG(0045), 0x24), ++ REG_SEQ0(CMN_REG(0046), 0xff), ++ REG_SEQ0(CMN_REG(0047), 0x00), ++ REG_SEQ0(CMN_REG(0048), 0x44), ++ REG_SEQ0(CMN_REG(0049), 0xfa), ++ REG_SEQ0(CMN_REG(004a), 0x08), ++ REG_SEQ0(CMN_REG(004b), 0x00), ++ REG_SEQ0(CMN_REG(004c), 0x01), ++ REG_SEQ0(CMN_REG(004d), 0x64), ++ REG_SEQ0(CMN_REG(004e), 0x14), ++ REG_SEQ0(CMN_REG(004f), 0x00), ++ REG_SEQ0(CMN_REG(0050), 0x00), ++ REG_SEQ0(CMN_REG(005d), 0x0c), ++ REG_SEQ0(CMN_REG(005f), 0x01), ++ REG_SEQ0(CMN_REG(006b), 0x04), ++ REG_SEQ0(CMN_REG(0073), 0x30), ++ REG_SEQ0(CMN_REG(0074), 0x00), ++ REG_SEQ0(CMN_REG(0075), 0x20), ++ REG_SEQ0(CMN_REG(0076), 0x30), ++ REG_SEQ0(CMN_REG(0077), 0x08), ++ REG_SEQ0(CMN_REG(0078), 0x0c), ++ REG_SEQ0(CMN_REG(0079), 0x00), ++ REG_SEQ0(CMN_REG(007b), 0x00), ++ REG_SEQ0(CMN_REG(007c), 0x00), ++ REG_SEQ0(CMN_REG(007d), 0x00), ++ REG_SEQ0(CMN_REG(007e), 0x00), ++ REG_SEQ0(CMN_REG(007f), 0x00), ++ REG_SEQ0(CMN_REG(0080), 0x00), ++ REG_SEQ0(CMN_REG(0081), 0x09), ++ REG_SEQ0(CMN_REG(0082), 0x04), ++ REG_SEQ0(CMN_REG(0083), 0x24), ++ REG_SEQ0(CMN_REG(0084), 0x20), ++ REG_SEQ0(CMN_REG(0085), 0x03), ++ REG_SEQ0(CMN_REG(0086), 0x01), ++ REG_SEQ0(CMN_REG(0087), 0x0c), ++ REG_SEQ0(CMN_REG(008a), 0x55), ++ REG_SEQ0(CMN_REG(008b), 0x25), ++ REG_SEQ0(CMN_REG(008c), 0x2c), ++ REG_SEQ0(CMN_REG(008d), 0x22), ++ REG_SEQ0(CMN_REG(008e), 0x14), ++ REG_SEQ0(CMN_REG(008f), 0x20), ++ REG_SEQ0(CMN_REG(0090), 0x00), ++ REG_SEQ0(CMN_REG(0091), 0x00), ++ REG_SEQ0(CMN_REG(0092), 0x00), ++ REG_SEQ0(CMN_REG(0093), 0x00), ++ REG_SEQ0(CMN_REG(009a), 0x11), ++ REG_SEQ0(CMN_REG(009b), 0x10), ++}; ++ ++static const struct reg_sequence rk_hdtpx_tmds_cmn_init_seq[] = { ++ REG_SEQ0(CMN_REG(0008), 0x00), ++ REG_SEQ0(CMN_REG(0011), 0x01), ++ REG_SEQ0(CMN_REG(0017), 0x20), ++ REG_SEQ0(CMN_REG(001e), 0x14), ++ REG_SEQ0(CMN_REG(0020), 0x00), ++ REG_SEQ0(CMN_REG(0021), 0x00), ++ REG_SEQ0(CMN_REG(0022), 0x11), ++ REG_SEQ0(CMN_REG(0023), 0x00), ++ REG_SEQ0(CMN_REG(0024), 0x00), ++ REG_SEQ0(CMN_REG(0025), 0x53), ++ REG_SEQ0(CMN_REG(0026), 0x00), ++ REG_SEQ0(CMN_REG(0027), 0x00), ++ REG_SEQ0(CMN_REG(0028), 0x01), ++ REG_SEQ0(CMN_REG(002a), 0x00), ++ REG_SEQ0(CMN_REG(002b), 0x00), ++ REG_SEQ0(CMN_REG(002c), 0x00), ++ REG_SEQ0(CMN_REG(002d), 0x00), ++ REG_SEQ0(CMN_REG(002e), 0x04), ++ REG_SEQ0(CMN_REG(002f), 0x00), ++ REG_SEQ0(CMN_REG(0030), 0x20), ++ REG_SEQ0(CMN_REG(0031), 0x30), ++ REG_SEQ0(CMN_REG(0032), 0x0b), ++ REG_SEQ0(CMN_REG(0033), 0x23), ++ REG_SEQ0(CMN_REG(0034), 0x00), ++ REG_SEQ0(CMN_REG(003d), 0x40), ++ REG_SEQ0(CMN_REG(0042), 0x78), ++ REG_SEQ0(CMN_REG(004e), 0x34), ++ REG_SEQ0(CMN_REG(005c), 0x25), ++ REG_SEQ0(CMN_REG(005e), 0x4f), ++ REG_SEQ0(CMN_REG(0074), 0x04), ++ REG_SEQ0(CMN_REG(0081), 0x01), ++ REG_SEQ0(CMN_REG(0087), 0x04), ++ REG_SEQ0(CMN_REG(0089), 0x00), ++ REG_SEQ0(CMN_REG(0095), 0x00), ++ REG_SEQ0(CMN_REG(0097), 0x02), ++ REG_SEQ0(CMN_REG(0099), 0x04), ++ REG_SEQ0(CMN_REG(009b), 0x00), ++}; ++ ++static const struct reg_sequence rk_hdtpx_common_sb_init_seq[] = { ++ REG_SEQ0(SB_REG(0114), 0x00), ++ REG_SEQ0(SB_REG(0115), 0x00), ++ REG_SEQ0(SB_REG(0116), 0x00), ++ REG_SEQ0(SB_REG(0117), 0x00), ++}; ++ ++static const struct reg_sequence rk_hdtpx_tmds_lntop_highbr_seq[] = { ++ REG_SEQ0(LNTOP_REG(0201), 0x00), ++ REG_SEQ0(LNTOP_REG(0202), 0x00), ++ REG_SEQ0(LNTOP_REG(0203), 0x0f), ++ REG_SEQ0(LNTOP_REG(0204), 0xff), ++ REG_SEQ0(LNTOP_REG(0205), 0xff), ++}; ++ ++static const struct reg_sequence rk_hdtpx_tmds_lntop_lowbr_seq[] = { ++ REG_SEQ0(LNTOP_REG(0201), 0x07), ++ REG_SEQ0(LNTOP_REG(0202), 0xc1), ++ REG_SEQ0(LNTOP_REG(0203), 0xf0), ++ REG_SEQ0(LNTOP_REG(0204), 0x7c), ++ REG_SEQ0(LNTOP_REG(0205), 0x1f), ++}; ++ ++static const struct reg_sequence rk_hdtpx_common_lane_init_seq[] = { ++ REG_SEQ0(LANE_REG(0303), 0x0c), ++ REG_SEQ0(LANE_REG(0307), 0x20), ++ REG_SEQ0(LANE_REG(030a), 0x17), ++ REG_SEQ0(LANE_REG(030b), 0x77), ++ REG_SEQ0(LANE_REG(030c), 0x77), ++ REG_SEQ0(LANE_REG(030d), 0x77), ++ REG_SEQ0(LANE_REG(030e), 0x38), ++ REG_SEQ0(LANE_REG(0310), 0x03), ++ REG_SEQ0(LANE_REG(0311), 0x0f), ++ REG_SEQ0(LANE_REG(0316), 0x02), ++ REG_SEQ0(LANE_REG(031b), 0x01), ++ REG_SEQ0(LANE_REG(031f), 0x15), ++ REG_SEQ0(LANE_REG(0320), 0xa0), ++ REG_SEQ0(LANE_REG(0403), 0x0c), ++ REG_SEQ0(LANE_REG(0407), 0x20), ++ REG_SEQ0(LANE_REG(040a), 0x17), ++ REG_SEQ0(LANE_REG(040b), 0x77), ++ REG_SEQ0(LANE_REG(040c), 0x77), ++ REG_SEQ0(LANE_REG(040d), 0x77), ++ REG_SEQ0(LANE_REG(040e), 0x38), ++ REG_SEQ0(LANE_REG(0410), 0x03), ++ REG_SEQ0(LANE_REG(0411), 0x0f), ++ REG_SEQ0(LANE_REG(0416), 0x02), ++ REG_SEQ0(LANE_REG(041b), 0x01), ++ REG_SEQ0(LANE_REG(041f), 0x15), ++ REG_SEQ0(LANE_REG(0420), 0xa0), ++ REG_SEQ0(LANE_REG(0503), 0x0c), ++ REG_SEQ0(LANE_REG(0507), 0x20), ++ REG_SEQ0(LANE_REG(050a), 0x17), ++ REG_SEQ0(LANE_REG(050b), 0x77), ++ REG_SEQ0(LANE_REG(050c), 0x77), ++ REG_SEQ0(LANE_REG(050d), 0x77), ++ REG_SEQ0(LANE_REG(050e), 0x38), ++ REG_SEQ0(LANE_REG(0510), 0x03), ++ REG_SEQ0(LANE_REG(0511), 0x0f), ++ REG_SEQ0(LANE_REG(0516), 0x02), ++ REG_SEQ0(LANE_REG(051b), 0x01), ++ REG_SEQ0(LANE_REG(051f), 0x15), ++ REG_SEQ0(LANE_REG(0520), 0xa0), ++ REG_SEQ0(LANE_REG(0603), 0x0c), ++ REG_SEQ0(LANE_REG(0607), 0x20), ++ REG_SEQ0(LANE_REG(060a), 0x17), ++ REG_SEQ0(LANE_REG(060b), 0x77), ++ REG_SEQ0(LANE_REG(060c), 0x77), ++ REG_SEQ0(LANE_REG(060d), 0x77), ++ REG_SEQ0(LANE_REG(060e), 0x38), ++ REG_SEQ0(LANE_REG(0610), 0x03), ++ REG_SEQ0(LANE_REG(0611), 0x0f), ++ REG_SEQ0(LANE_REG(0616), 0x02), ++ REG_SEQ0(LANE_REG(061b), 0x01), ++ REG_SEQ0(LANE_REG(061f), 0x15), ++ REG_SEQ0(LANE_REG(0620), 0xa0), ++}; ++ ++static const struct reg_sequence rk_hdtpx_tmds_lane_init_seq[] = { ++ REG_SEQ0(LANE_REG(0312), 0x00), ++ REG_SEQ0(LANE_REG(031e), 0x00), ++ REG_SEQ0(LANE_REG(0412), 0x00), ++ REG_SEQ0(LANE_REG(041e), 0x00), ++ REG_SEQ0(LANE_REG(0512), 0x00), ++ REG_SEQ0(LANE_REG(051e), 0x00), ++ REG_SEQ0(LANE_REG(0612), 0x00), ++ REG_SEQ0(LANE_REG(061e), 0x08), ++ REG_SEQ0(LANE_REG(0303), 0x2f), ++ REG_SEQ0(LANE_REG(0403), 0x2f), ++ REG_SEQ0(LANE_REG(0503), 0x2f), ++ REG_SEQ0(LANE_REG(0603), 0x2f), ++ REG_SEQ0(LANE_REG(0305), 0x03), ++ REG_SEQ0(LANE_REG(0405), 0x03), ++ REG_SEQ0(LANE_REG(0505), 0x03), ++ REG_SEQ0(LANE_REG(0605), 0x03), ++ REG_SEQ0(LANE_REG(0306), 0x1c), ++ REG_SEQ0(LANE_REG(0406), 0x1c), ++ REG_SEQ0(LANE_REG(0506), 0x1c), ++ REG_SEQ0(LANE_REG(0606), 0x1c), ++}; ++ ++static bool rk_hdptx_phy_is_rw_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case 0x0000 ... 0x029c: ++ case 0x0400 ... 0x04a4: ++ case 0x0800 ... 0x08a4: ++ case 0x0c00 ... 0x0cb4: ++ case 0x1000 ... 0x10b4: ++ case 0x1400 ... 0x14b4: ++ case 0x1800 ... 0x18b4: ++ return true; ++ } ++ ++ return false; ++} ++ ++static const struct regmap_config rk_hdptx_phy_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .writeable_reg = rk_hdptx_phy_is_rw_reg, ++ .readable_reg = rk_hdptx_phy_is_rw_reg, ++ .fast_io = true, ++ .max_register = 0x18b4, ++}; ++ ++#define rk_hdptx_multi_reg_write(hdptx, seq) \ ++ regmap_multi_reg_write((hdptx)->regmap, seq, ARRAY_SIZE(seq)) ++ ++static void rk_hdptx_pre_power_up(struct rk_hdptx_phy *hdptx) ++{ ++ u32 val; ++ ++ reset_control_assert(hdptx->rsts[RST_APB].rstc); ++ usleep_range(20, 25); ++ reset_control_deassert(hdptx->rsts[RST_APB].rstc); ++ ++ reset_control_assert(hdptx->rsts[RST_LANE].rstc); ++ reset_control_assert(hdptx->rsts[RST_CMN].rstc); ++ reset_control_assert(hdptx->rsts[RST_INIT].rstc); ++ ++ val = (HDPTX_I_PLL_EN | HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16; ++ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); ++} ++ ++static int rk_hdptx_post_enable_lane(struct rk_hdptx_phy *hdptx) ++{ ++ u32 val; ++ int ret; ++ ++ reset_control_deassert(hdptx->rsts[RST_LANE].rstc); ++ ++ val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 | ++ HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN; ++ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); ++ ++ ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val, ++ (val & HDPTX_O_PHY_RDY) && ++ (val & HDPTX_O_PLL_LOCK_DONE), ++ 100, 5000); ++ if (ret) { ++ dev_err(hdptx->dev, "Failed to get PHY lane lock: %d\n", ret); ++ return ret; ++ } ++ ++ dev_dbg(hdptx->dev, "PHY lane locked\n"); ++ ++ return 0; ++} ++ ++static int rk_hdptx_post_enable_pll(struct rk_hdptx_phy *hdptx) ++{ ++ u32 val; ++ int ret; ++ ++ val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 | ++ HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN; ++ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); ++ ++ usleep_range(10, 15); ++ reset_control_deassert(hdptx->rsts[RST_INIT].rstc); ++ ++ usleep_range(10, 15); ++ val = HDPTX_I_PLL_EN << 16 | HDPTX_I_PLL_EN; ++ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); ++ ++ usleep_range(10, 15); ++ reset_control_deassert(hdptx->rsts[RST_CMN].rstc); ++ ++ ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val, ++ val & HDPTX_O_PHY_CLK_RDY, 20, 400); ++ if (ret) { ++ dev_err(hdptx->dev, "Failed to get PHY clk ready: %d\n", ret); ++ return ret; ++ } ++ ++ dev_dbg(hdptx->dev, "PHY clk ready\n"); ++ ++ return 0; ++} ++ ++static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx) ++{ ++ u32 val; ++ ++ /* reset phy and apb, or phy locked flag may keep 1 */ ++ reset_control_assert(hdptx->rsts[RST_PHY].rstc); ++ usleep_range(20, 30); ++ reset_control_deassert(hdptx->rsts[RST_PHY].rstc); ++ ++ reset_control_assert(hdptx->rsts[RST_APB].rstc); ++ usleep_range(20, 30); ++ reset_control_deassert(hdptx->rsts[RST_APB].rstc); ++ ++ regmap_write(hdptx->regmap, LANE_REG(0300), 0x82); ++ regmap_write(hdptx->regmap, SB_REG(010f), 0xc1); ++ regmap_write(hdptx->regmap, SB_REG(0110), 0x1); ++ regmap_write(hdptx->regmap, LANE_REG(0301), 0x80); ++ regmap_write(hdptx->regmap, LANE_REG(0401), 0x80); ++ regmap_write(hdptx->regmap, LANE_REG(0501), 0x80); ++ regmap_write(hdptx->regmap, LANE_REG(0601), 0x80); ++ ++ reset_control_assert(hdptx->rsts[RST_LANE].rstc); ++ reset_control_assert(hdptx->rsts[RST_CMN].rstc); ++ reset_control_assert(hdptx->rsts[RST_INIT].rstc); ++ ++ val = (HDPTX_I_PLL_EN | HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16; ++ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); ++} ++ ++static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate, ++ struct ropll_config *cfg) ++{ ++ const unsigned int fout = data_rate / 2, fref = 24000; ++ unsigned long k = 0, lc, k_sub, lc_sub; ++ unsigned int fvco, sdc; ++ u32 mdiv, sdiv, n = 8; ++ ++ if (fout > 0xfffffff) ++ return false; ++ ++ for (sdiv = 16; sdiv >= 1; sdiv--) { ++ if (sdiv % 2 && sdiv != 1) ++ continue; ++ ++ fvco = fout * sdiv; ++ ++ if (fvco < 2000000 || fvco > 4000000) ++ continue; ++ ++ mdiv = DIV_ROUND_UP(fvco, fref); ++ if (mdiv < 20 || mdiv > 255) ++ continue; ++ ++ if (fref * mdiv - fvco) { ++ for (sdc = 264000; sdc <= 750000; sdc += fref) ++ if (sdc * n > fref * mdiv) ++ break; ++ ++ if (sdc > 750000) ++ continue; ++ ++ rational_best_approximation(fref * mdiv - fvco, ++ sdc / 16, ++ GENMASK(6, 0), ++ GENMASK(7, 0), ++ &k, &lc); ++ ++ rational_best_approximation(sdc * n - fref * mdiv, ++ sdc, ++ GENMASK(6, 0), ++ GENMASK(7, 0), ++ &k_sub, &lc_sub); ++ } ++ ++ break; ++ } ++ ++ if (sdiv < 1) ++ return false; ++ ++ if (cfg) { ++ cfg->pms_mdiv = mdiv; ++ cfg->pms_mdiv_afc = mdiv; ++ cfg->pms_pdiv = 1; ++ cfg->pms_refdiv = 1; ++ cfg->pms_sdiv = sdiv - 1; ++ ++ cfg->sdm_en = k > 0 ? 1 : 0; ++ if (cfg->sdm_en) { ++ cfg->sdm_deno = lc; ++ cfg->sdm_num_sign = 1; ++ cfg->sdm_num = k; ++ cfg->sdc_n = n - 3; ++ cfg->sdc_num = k_sub; ++ cfg->sdc_deno = lc_sub; ++ } ++ } ++ ++ return true; ++} ++ ++static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, ++ unsigned int rate) ++{ ++ const struct ropll_config *cfg = NULL; ++ struct ropll_config rc = {0}; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) ++ if (rate == ropll_tmds_cfg[i].bit_rate) { ++ cfg = &ropll_tmds_cfg[i]; ++ break; ++ } ++ ++ if (!cfg) { ++ if (rk_hdptx_phy_clk_pll_calc(rate, &rc)) { ++ cfg = &rc; ++ } else { ++ dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__); ++ return -EINVAL; ++ } ++ } ++ ++ dev_dbg(hdptx->dev, "mdiv=%u, sdiv=%u, sdm_en=%u, k_sign=%u, k=%u, lc=%u\n", ++ cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en, ++ cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno); ++ ++ rk_hdptx_pre_power_up(hdptx); ++ ++ reset_control_assert(hdptx->rsts[RST_ROPLL].rstc); ++ usleep_range(20, 30); ++ reset_control_deassert(hdptx->rsts[RST_ROPLL].rstc); ++ ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_cmn_init_seq); ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_cmn_init_seq); ++ ++ regmap_write(hdptx->regmap, CMN_REG(0051), cfg->pms_mdiv); ++ regmap_write(hdptx->regmap, CMN_REG(0055), cfg->pms_mdiv_afc); ++ regmap_write(hdptx->regmap, CMN_REG(0059), ++ (cfg->pms_pdiv << 4) | cfg->pms_refdiv); ++ regmap_write(hdptx->regmap, CMN_REG(005a), cfg->pms_sdiv << 4); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDM_EN_MASK, ++ FIELD_PREP(ROPLL_SDM_EN_MASK, cfg->sdm_en)); ++ if (!cfg->sdm_en) ++ regmap_update_bits(hdptx->regmap, CMN_REG(005e), 0xf, 0); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(0064), ROPLL_SDM_NUM_SIGN_RBR_MASK, ++ FIELD_PREP(ROPLL_SDM_NUM_SIGN_RBR_MASK, cfg->sdm_num_sign)); ++ ++ regmap_write(hdptx->regmap, CMN_REG(0060), cfg->sdm_deno); ++ regmap_write(hdptx->regmap, CMN_REG(0065), cfg->sdm_num); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(0069), ROPLL_SDC_N_RBR_MASK, ++ FIELD_PREP(ROPLL_SDC_N_RBR_MASK, cfg->sdc_n)); ++ ++ regmap_write(hdptx->regmap, CMN_REG(006c), cfg->sdc_num); ++ regmap_write(hdptx->regmap, CMN_REG(0070), cfg->sdc_deno); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK, ++ FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv)); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN, ++ PLL_PCG_CLK_EN); ++ ++ return rk_hdptx_post_enable_pll(hdptx); ++} ++ ++static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, ++ unsigned int rate) ++{ ++ u32 val; ++ int ret; ++ ++ ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); ++ if (ret) ++ return ret; ++ ++ if (!(val & HDPTX_O_PLL_LOCK_DONE)) { ++ ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate); ++ if (ret) ++ return ret; ++ } ++ ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq); ++ ++ regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06); ++ ++ if (rate >= 3400000) { ++ /* For 1/40 bitrate clk */ ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq); ++ } else { ++ /* For 1/10 bitrate clk */ ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_lowbr_seq); ++ } ++ ++ regmap_write(hdptx->regmap, LNTOP_REG(0206), 0x07); ++ regmap_write(hdptx->regmap, LNTOP_REG(0207), 0x0f); ++ ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_lane_init_seq); ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lane_init_seq); ++ ++ return rk_hdptx_post_enable_lane(hdptx); ++} ++ ++static int rk_hdptx_phy_power_on(struct phy *phy) ++{ ++ struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); ++ int ret, bus_width = phy_get_bus_width(hdptx->phy); ++ /* ++ * FIXME: Temporary workaround to pass pixel_clk_rate ++ * from the HDMI bridge driver until phy_configure_opts_hdmi ++ * becomes available in the PHY API. ++ */ ++ unsigned int rate = bus_width & 0xfffffff; ++ ++ dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n", ++ __func__, bus_width, rate); ++ ++ ret = pm_runtime_resume_and_get(hdptx->dev); ++ if (ret) { ++ dev_err(hdptx->dev, "Failed to resume phy: %d\n", ret); ++ return ret; ++ } ++ ++ ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate); ++ if (ret) ++ pm_runtime_put(hdptx->dev); ++ ++ return ret; ++} ++ ++static int rk_hdptx_phy_power_off(struct phy *phy) ++{ ++ struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); ++ u32 val; ++ int ret; ++ ++ ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); ++ if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) ++ rk_hdptx_phy_disable(hdptx); ++ ++ pm_runtime_put(hdptx->dev); ++ ++ return ret; ++} ++ ++static const struct phy_ops rk_hdptx_phy_ops = { ++ .power_on = rk_hdptx_phy_power_on, ++ .power_off = rk_hdptx_phy_power_off, ++ .owner = THIS_MODULE, ++}; ++ ++static int rk_hdptx_phy_runtime_suspend(struct device *dev) ++{ ++ struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev); ++ ++ clk_bulk_disable_unprepare(hdptx->nr_clks, hdptx->clks); ++ ++ return 0; ++} ++ ++static int rk_hdptx_phy_runtime_resume(struct device *dev) ++{ ++ struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = clk_bulk_prepare_enable(hdptx->nr_clks, hdptx->clks); ++ if (ret) ++ dev_err(hdptx->dev, "Failed to enable clocks: %d\n", ret); ++ ++ return ret; ++} ++ ++static int rk_hdptx_phy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct device *dev = &pdev->dev; ++ struct rk_hdptx_phy *hdptx; ++ void __iomem *regs; ++ int ret; ++ ++ hdptx = devm_kzalloc(dev, sizeof(*hdptx), GFP_KERNEL); ++ if (!hdptx) ++ return -ENOMEM; ++ ++ hdptx->dev = dev; ++ ++ regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(regs)) ++ return dev_err_probe(dev, PTR_ERR(regs), ++ "Failed to ioremap resource\n"); ++ ++ ret = devm_clk_bulk_get_all(dev, &hdptx->clks); ++ if (ret < 0) ++ return dev_err_probe(dev, ret, "Failed to get clocks\n"); ++ if (ret == 0) ++ return dev_err_probe(dev, -EINVAL, "Missing clocks\n"); ++ ++ hdptx->nr_clks = ret; ++ ++ hdptx->regmap = devm_regmap_init_mmio(dev, regs, ++ &rk_hdptx_phy_regmap_config); ++ if (IS_ERR(hdptx->regmap)) ++ return dev_err_probe(dev, PTR_ERR(hdptx->regmap), ++ "Failed to init regmap\n"); ++ ++ hdptx->rsts[RST_PHY].id = "phy"; ++ hdptx->rsts[RST_APB].id = "apb"; ++ hdptx->rsts[RST_INIT].id = "init"; ++ hdptx->rsts[RST_CMN].id = "cmn"; ++ hdptx->rsts[RST_LANE].id = "lane"; ++ hdptx->rsts[RST_ROPLL].id = "ropll"; ++ hdptx->rsts[RST_LCPLL].id = "lcpll"; ++ ++ ret = devm_reset_control_bulk_get_exclusive(dev, RST_MAX, hdptx->rsts); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to get resets\n"); ++ ++ hdptx->grf = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "rockchip,grf"); ++ if (IS_ERR(hdptx->grf)) ++ return dev_err_probe(dev, PTR_ERR(hdptx->grf), ++ "Could not get GRF syscon\n"); ++ ++ hdptx->phy = devm_phy_create(dev, NULL, &rk_hdptx_phy_ops); ++ if (IS_ERR(hdptx->phy)) ++ return dev_err_probe(dev, PTR_ERR(hdptx->phy), ++ "Failed to create HDMI PHY\n"); ++ ++ platform_set_drvdata(pdev, hdptx); ++ phy_set_drvdata(hdptx->phy, hdptx); ++ phy_set_bus_width(hdptx->phy, 8); ++ ++ ret = devm_pm_runtime_enable(dev); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (IS_ERR(phy_provider)) ++ return dev_err_probe(dev, PTR_ERR(phy_provider), ++ "Failed to register PHY provider\n"); ++ ++ reset_control_deassert(hdptx->rsts[RST_APB].rstc); ++ reset_control_deassert(hdptx->rsts[RST_CMN].rstc); ++ reset_control_deassert(hdptx->rsts[RST_INIT].rstc); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops rk_hdptx_phy_pm_ops = { ++ RUNTIME_PM_OPS(rk_hdptx_phy_runtime_suspend, ++ rk_hdptx_phy_runtime_resume, NULL) ++}; ++ ++static const struct of_device_id rk_hdptx_phy_of_match[] = { ++ { .compatible = "rockchip,rk3588-hdptx-phy", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, rk_hdptx_phy_of_match); ++ ++static struct platform_driver rk_hdptx_phy_driver = { ++ .probe = rk_hdptx_phy_probe, ++ .driver = { ++ .name = "rockchip-hdptx-phy", ++ .pm = &rk_hdptx_phy_pm_ops, ++ .of_match_table = rk_hdptx_phy_of_match, ++ }, ++}; ++module_platform_driver(rk_hdptx_phy_driver); ++ ++MODULE_AUTHOR("Algea Cao "); ++MODULE_AUTHOR("Cristian Ciocaltea "); ++MODULE_DESCRIPTION("Samsung HDMI/eDP Transmitter Combo PHY Driver"); ++MODULE_LICENSE("GPL"); +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0136-arm64-dts-rockchip-Add-HDMI0-PHY-to-rk3588.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0136-arm64-dts-rockchip-Add-HDMI0-PHY-to-rk3588.patch new file mode 100644 index 000000000000..ffcff8fb7ff7 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0136-arm64-dts-rockchip-Add-HDMI0-PHY-to-rk3588.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Mon, 19 Feb 2024 22:46:25 +0200 +Subject: arm64: dts: rockchip: Add HDMI0 PHY to rk3588 + +Add DT nodes for HDMI0 PHY and related syscon found on RK3588 SoC. + +Signed-off-by: Cristian Ciocaltea +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 21 ++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -859,6 +859,11 @@ u2phy3_host: host-port { + }; + }; + ++ hdptxphy0_grf: syscon@fd5e0000 { ++ compatible = "rockchip,rk3588-hdptxphy-grf", "syscon"; ++ reg = <0x0 0xfd5e0000 0x0 0x100>; ++ }; ++ + ioc: syscon@fd5f0000 { + compatible = "rockchip,rk3588-ioc", "syscon"; + reg = <0x0 0xfd5f0000 0x0 0x10000>; +@@ -2848,6 +2853,22 @@ usbdp_phy0: phy@fed80000 { + status = "disabled"; + }; + ++ hdptxphy_hdmi0: phy@fed60000 { ++ compatible = "rockchip,rk3588-hdptx-phy"; ++ reg = <0x0 0xfed60000 0x0 0x2000>; ++ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>; ++ clock-names = "ref", "apb"; ++ #phy-cells = <0>; ++ resets = <&cru SRST_HDPTX0>, <&cru SRST_P_HDPTX0>, ++ <&cru SRST_HDPTX0_INIT>, <&cru SRST_HDPTX0_CMN>, ++ <&cru SRST_HDPTX0_LANE>, <&cru SRST_HDPTX0_ROPLL>, ++ <&cru SRST_HDPTX0_LCPLL>; ++ reset-names = "phy", "apb", "init", "cmn", "lane", "ropll", ++ "lcpll"; ++ rockchip,grf = <&hdptxphy0_grf>; ++ status = "disabled"; ++ }; ++ + combphy0_ps: phy@fee00000 { + compatible = "rockchip,rk3588-naneng-combphy"; + reg = <0x0 0xfee00000 0x0 0x100>; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0137-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0137-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-.patch new file mode 100644 index 000000000000..ada6d6073044 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0137-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-.patch @@ -0,0 +1,6616 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Wed, 1 Nov 2023 18:50:38 +0200 +Subject: [WIP] drm/bridge: synopsys: Add initial support for DW HDMI QP TX + Controller + +Co-developed-by: Algea Cao +Signed-off-by: Algea Cao +Signed-off-by: Cristian Ciocaltea +--- + drivers/gpu/drm/bridge/synopsys/Makefile | 2 +- + drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 2401 ++++++++ + drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h | 831 +++ + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 89 + + drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 4 + + drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2740 +++++++++- + include/drm/bridge/dw_hdmi.h | 101 + + 7 files changed, 6102 insertions(+), 66 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/Makefile b/drivers/gpu/drm/bridge/synopsys/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/bridge/synopsys/Makefile ++++ b/drivers/gpu/drm/bridge/synopsys/Makefile +@@ -1,5 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0-only +-obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o ++obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o dw-hdmi-qp.o + obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o + obj-$(CONFIG_DRM_DW_HDMI_GP_AUDIO) += dw-hdmi-gp-audio.o + obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +@@ -0,0 +1,2401 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (C) Rockchip Electronics Co.Ltd ++ * Author: ++ * Algea Cao ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "dw-hdmi-qp.h" ++ ++#define DDC_CI_ADDR 0x37 ++#define DDC_SEGMENT_ADDR 0x30 ++ ++#define HDMI_EDID_LEN 512 ++ ++/* DW-HDMI Controller >= 0x200a are at least compliant with SCDC version 1 */ ++#define SCDC_MIN_SOURCE_VERSION 0x1 ++ ++#define HDMI14_MAX_TMDSCLK 340000000 ++#define HDMI20_MAX_TMDSCLK_KHZ 600000 ++ ++static const unsigned int dw_hdmi_cable[] = { ++ EXTCON_DISP_HDMI, ++ EXTCON_NONE, ++}; ++ ++static const struct drm_display_mode dw_hdmi_default_modes[] = { ++ /* 16 - 1920x1080@60Hz 16:9 */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008, ++ 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), ++ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, ++ /* 2 - 720x480@60Hz 4:3 */ ++ { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736, ++ 798, 858, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), ++ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, }, ++ /* 4 - 1280x720@60Hz 16:9 */ ++ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390, ++ 1430, 1650, 0, 720, 725, 730, 750, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), ++ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, ++ /* 31 - 1920x1080@50Hz 16:9 */ ++ { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448, ++ 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), ++ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, ++ /* 19 - 1280x720@50Hz 16:9 */ ++ { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720, ++ 1760, 1980, 0, 720, 725, 730, 750, 0, ++ DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), ++ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, ++ /* 17 - 720x576@50Hz 4:3 */ ++ { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 720, 732, ++ 796, 864, 0, 576, 581, 586, 625, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), ++ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, }, ++ /* 2 - 720x480@60Hz 4:3 */ ++ { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 720, 736, ++ 798, 858, 0, 480, 489, 495, 525, 0, ++ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), ++ .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, }, ++}; ++ ++enum frl_mask { ++ FRL_3GBPS_3LANE = 1, ++ FRL_6GBPS_3LANE, ++ FRL_6GBPS_4LANE, ++ FRL_8GBPS_4LANE, ++ FRL_10GBPS_4LANE, ++ FRL_12GBPS_4LANE, ++}; ++ ++struct hdmi_vmode_qp { ++ bool mdataenablepolarity; ++ ++ unsigned int previous_pixelclock; ++ unsigned long mpixelclock; ++ unsigned int mpixelrepetitioninput; ++ unsigned int mpixelrepetitionoutput; ++ unsigned long previous_tmdsclock; ++ unsigned int mtmdsclock; ++}; ++ ++struct hdmi_qp_data_info { ++ unsigned int enc_in_bus_format; ++ unsigned int enc_out_bus_format; ++ unsigned int enc_in_encoding; ++ unsigned int enc_out_encoding; ++ unsigned int quant_range; ++ unsigned int pix_repet_factor; ++ struct hdmi_vmode_qp video_mode; ++ bool update; ++}; ++ ++struct dw_hdmi_qp_i2c { ++ struct i2c_adapter adap; ++ ++ struct mutex lock; /* used to serialize data transfers */ ++ struct completion cmp; ++ u32 stat; ++ ++ u8 slave_reg; ++ bool is_regaddr; ++ bool is_segment; ++ ++ unsigned int scl_high_ns; ++ unsigned int scl_low_ns; ++}; ++ ++struct dw_hdmi_qp { ++ struct drm_connector connector; ++ struct drm_bridge bridge; ++ struct platform_device *hdcp_dev; ++ struct platform_device *audio; ++ struct platform_device *cec; ++ struct device *dev; ++ struct dw_hdmi_qp_i2c *i2c; ++ ++ struct hdmi_qp_data_info hdmi_data; ++ const struct dw_hdmi_plat_data *plat_data; ++ ++ int vic; ++ int main_irq; ++ int avp_irq; ++ int earc_irq; ++ ++ u8 edid[HDMI_EDID_LEN]; ++ ++ struct { ++ const struct dw_hdmi_qp_phy_ops *ops; ++ const char *name; ++ void *data; ++ bool enabled; ++ } phy; ++ ++ struct drm_display_mode previous_mode; ++ ++ struct i2c_adapter *ddc; ++ void __iomem *regs; ++ bool sink_is_hdmi; ++ ++ struct mutex mutex; /* for state below and previous_mode */ ++ //[CC:] curr_conn should be removed ++ struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */ ++ enum drm_connector_force force; /* mutex-protected force state */ ++ bool disabled; /* DRM has disabled our bridge */ ++ bool bridge_is_on; /* indicates the bridge is on */ ++ bool rxsense; /* rxsense state */ ++ u8 phy_mask; /* desired phy int mask settings */ ++ u8 mc_clkdis; /* clock disable register */ ++ ++ u32 scdc_intr; ++ u32 flt_intr; ++ //[CC:] remove earc ++ u32 earc_intr; ++ ++ struct dentry *debugfs_dir; ++ bool scramble_low_rates; ++ ++ struct extcon_dev *extcon; ++ ++ struct regmap *regm; ++ ++ bool initialized; /* hdmi is enabled before bind */ ++ struct completion flt_cmp; ++ struct completion earc_cmp; ++ ++ hdmi_codec_plugged_cb plugged_cb; ++ struct device *codec_dev; ++ enum drm_connector_status last_connector_result; ++}; ++ ++static inline void hdmi_writel(struct dw_hdmi_qp *hdmi, u32 val, int offset) ++{ ++ regmap_write(hdmi->regm, offset, val); ++} ++ ++static inline u32 hdmi_readl(struct dw_hdmi_qp *hdmi, int offset) ++{ ++ unsigned int val = 0; ++ ++ regmap_read(hdmi->regm, offset, &val); ++ ++ return val; ++} ++ ++static void handle_plugged_change(struct dw_hdmi_qp *hdmi, bool plugged) ++{ ++ if (hdmi->plugged_cb && hdmi->codec_dev) ++ hdmi->plugged_cb(hdmi->codec_dev, plugged); ++} ++ ++static void hdmi_modb(struct dw_hdmi_qp *hdmi, u32 data, u32 mask, u32 reg) ++{ ++ regmap_update_bits(hdmi->regm, reg, mask, data); ++} ++ ++static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ case MEDIA_BUS_FMT_RGB101010_1X30: ++ case MEDIA_BUS_FMT_RGB121212_1X36: ++ case MEDIA_BUS_FMT_RGB161616_1X48: ++ return true; ++ ++ default: ++ return false; ++ } ++} ++ ++static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ case MEDIA_BUS_FMT_YUV12_1X36: ++ case MEDIA_BUS_FMT_YUV16_1X48: ++ return true; ++ ++ default: ++ return false; ++ } ++} ++ ++static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_UYVY8_1X16: ++ case MEDIA_BUS_FMT_UYVY10_1X20: ++ case MEDIA_BUS_FMT_UYVY12_1X24: ++ return true; ++ ++ default: ++ return false; ++ } ++} ++ ++static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ case MEDIA_BUS_FMT_UYYVYY12_0_5X36: ++ case MEDIA_BUS_FMT_UYYVYY16_0_5X48: ++ return true; ++ ++ default: ++ return false; ++ } ++} ++ ++static int hdmi_bus_fmt_color_depth(unsigned int bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ case MEDIA_BUS_FMT_UYVY8_1X16: ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ return 8; ++ ++ case MEDIA_BUS_FMT_RGB101010_1X30: ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ case MEDIA_BUS_FMT_UYVY10_1X20: ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ return 10; ++ ++ case MEDIA_BUS_FMT_RGB121212_1X36: ++ case MEDIA_BUS_FMT_YUV12_1X36: ++ case MEDIA_BUS_FMT_UYVY12_1X24: ++ case MEDIA_BUS_FMT_UYYVYY12_0_5X36: ++ return 12; ++ ++ case MEDIA_BUS_FMT_RGB161616_1X48: ++ case MEDIA_BUS_FMT_YUV16_1X48: ++ case MEDIA_BUS_FMT_UYYVYY16_0_5X48: ++ return 16; ++ ++ default: ++ return 0; ++ } ++} ++ ++static void dw_hdmi_i2c_init(struct dw_hdmi_qp *hdmi) ++{ ++ /* Software reset */ ++ hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); ++ ++ hdmi_writel(hdmi, 0x085c085c, I2CM_FM_SCL_CONFIG0); ++ ++ hdmi_modb(hdmi, 0, I2CM_FM_EN, I2CM_INTERFACE_CONTROL0); ++ ++ /* Clear DONE and ERROR interrupts */ ++ hdmi_writel(hdmi, I2CM_OP_DONE_CLEAR | I2CM_NACK_RCVD_CLEAR, ++ MAINUNIT_1_INT_CLEAR); ++} ++ ++static int dw_hdmi_i2c_read(struct dw_hdmi_qp *hdmi, ++ unsigned char *buf, unsigned int length) ++{ ++ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; ++ int stat; ++ ++ if (!i2c->is_regaddr) { ++ dev_dbg(hdmi->dev, "set read register address to 0\n"); ++ i2c->slave_reg = 0x00; ++ i2c->is_regaddr = true; ++ } ++ ++ while (length--) { ++ reinit_completion(&i2c->cmp); ++ ++ hdmi_modb(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR, ++ I2CM_INTERFACE_CONTROL0); ++ ++ hdmi_modb(hdmi, I2CM_FM_READ, I2CM_WR_MASK, ++ I2CM_INTERFACE_CONTROL0); ++ ++ stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); ++ if (!stat) { ++ dev_err(hdmi->dev, "i2c read time out!\n"); ++ hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); ++ return -EAGAIN; ++ } ++ ++ /* Check for error condition on the bus */ ++ if (i2c->stat & I2CM_NACK_RCVD_IRQ) { ++ dev_err(hdmi->dev, "i2c read err!\n"); ++ hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); ++ return -EIO; ++ } ++ ++ *buf++ = hdmi_readl(hdmi, I2CM_INTERFACE_RDDATA_0_3) & 0xff; ++ hdmi_modb(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0); ++ } ++ i2c->is_segment = false; ++ ++ return 0; ++} ++ ++static int dw_hdmi_i2c_write(struct dw_hdmi_qp *hdmi, ++ unsigned char *buf, unsigned int length) ++{ ++ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; ++ int stat; ++ ++ if (!i2c->is_regaddr) { ++ /* Use the first write byte as register address */ ++ i2c->slave_reg = buf[0]; ++ length--; ++ buf++; ++ i2c->is_regaddr = true; ++ } ++ ++ while (length--) { ++ reinit_completion(&i2c->cmp); ++ ++ hdmi_writel(hdmi, *buf++, I2CM_INTERFACE_WRDATA_0_3); ++ hdmi_modb(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR, ++ I2CM_INTERFACE_CONTROL0); ++ hdmi_modb(hdmi, I2CM_FM_WRITE, I2CM_WR_MASK, ++ I2CM_INTERFACE_CONTROL0); ++ ++ stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); ++ if (!stat) { ++ dev_err(hdmi->dev, "i2c write time out!\n"); ++ hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); ++ return -EAGAIN; ++ } ++ ++ /* Check for error condition on the bus */ ++ if (i2c->stat & I2CM_NACK_RCVD_IRQ) { ++ dev_err(hdmi->dev, "i2c write nack!\n"); ++ hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); ++ return -EIO; ++ } ++ hdmi_modb(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0); ++ } ++ ++ return 0; ++} ++ ++static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap, ++ struct i2c_msg *msgs, int num) ++{ ++ struct dw_hdmi_qp *hdmi = i2c_get_adapdata(adap); ++ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; ++ u8 addr = msgs[0].addr; ++ int i, ret = 0; ++ ++ if (addr == DDC_CI_ADDR) ++ /* ++ * The internal I2C controller does not support the multi-byte ++ * read and write operations needed for DDC/CI. ++ * TOFIX: Blacklist the DDC/CI address until we filter out ++ * unsupported I2C operations. ++ */ ++ return -EOPNOTSUPP; ++ ++ for (i = 0; i < num; i++) { ++ if (msgs[i].len == 0) { ++ dev_err(hdmi->dev, ++ "unsupported transfer %d/%d, no data\n", ++ i + 1, num); ++ return -EOPNOTSUPP; ++ } ++ } ++ ++ mutex_lock(&i2c->lock); ++ ++ /* Unmute DONE and ERROR interrupts */ ++ hdmi_modb(hdmi, I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N, ++ I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N, ++ MAINUNIT_1_INT_MASK_N); ++ ++ /* Set slave device address taken from the first I2C message */ ++ if (addr == DDC_SEGMENT_ADDR && msgs[0].len == 1) ++ addr = DDC_ADDR; ++ ++ hdmi_modb(hdmi, addr << 5, I2CM_SLVADDR, I2CM_INTERFACE_CONTROL0); ++ ++ /* Set slave device register address on transfer */ ++ i2c->is_regaddr = false; ++ ++ /* Set segment pointer for I2C extended read mode operation */ ++ i2c->is_segment = false; ++ ++ for (i = 0; i < num; i++) { ++ if (msgs[i].addr == DDC_SEGMENT_ADDR && msgs[i].len == 1) { ++ i2c->is_segment = true; ++ hdmi_modb(hdmi, DDC_SEGMENT_ADDR, I2CM_SEG_ADDR, ++ I2CM_INTERFACE_CONTROL1); ++ hdmi_modb(hdmi, *msgs[i].buf, I2CM_SEG_PTR, ++ I2CM_INTERFACE_CONTROL1); ++ } else { ++ if (msgs[i].flags & I2C_M_RD) ++ ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, ++ msgs[i].len); ++ else ++ ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, ++ msgs[i].len); ++ } ++ if (ret < 0) ++ break; ++ } ++ ++ if (!ret) ++ ret = num; ++ ++ /* Mute DONE and ERROR interrupts */ ++ hdmi_modb(hdmi, 0, I2CM_OP_DONE_MASK_N | I2CM_NACK_RCVD_MASK_N, ++ MAINUNIT_1_INT_MASK_N); ++ ++ mutex_unlock(&i2c->lock); ++ ++ return ret; ++} ++ ++static u32 dw_hdmi_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm dw_hdmi_algorithm = { ++ .master_xfer = dw_hdmi_i2c_xfer, ++ .functionality = dw_hdmi_i2c_func, ++}; ++ ++static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi_qp *hdmi) ++{ ++ struct i2c_adapter *adap; ++ struct dw_hdmi_qp_i2c *i2c; ++ int ret; ++ ++ i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL); ++ if (!i2c) ++ return ERR_PTR(-ENOMEM); ++ ++ mutex_init(&i2c->lock); ++ init_completion(&i2c->cmp); ++ ++ adap = &i2c->adap; ++ adap->owner = THIS_MODULE; ++ adap->dev.parent = hdmi->dev; ++ adap->algo = &dw_hdmi_algorithm; ++ strscpy(adap->name, "ddc", sizeof(adap->name)); ++ i2c_set_adapdata(adap, hdmi); ++ ++ ret = i2c_add_adapter(adap); ++ if (ret) { ++ dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name); ++ devm_kfree(hdmi->dev, i2c); ++ return ERR_PTR(ret); ++ } ++ ++ hdmi->i2c = i2c; ++ ++ dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name); ++ ++ return adap; ++} ++ ++#define HDMI_PHY_EARC_MASK BIT(29) ++ ++/* ----------------------------------------------------------------------------- ++ * HDMI TX Setup ++ */ ++ ++static void hdmi_infoframe_set_checksum(u8 *ptr, int size) ++{ ++ u8 csum = 0; ++ int i; ++ ++ ptr[3] = 0; ++ /* compute checksum */ ++ for (i = 0; i < size; i++) ++ csum += ptr[i]; ++ ++ ptr[3] = 256 - csum; ++} ++ ++static void hdmi_config_AVI(struct dw_hdmi_qp *hdmi, ++ const struct drm_connector *connector, ++ const struct drm_display_mode *mode) ++{ ++ struct hdmi_avi_infoframe frame; ++ u32 val, i, j; ++ u8 buff[17]; ++ enum hdmi_quantization_range rgb_quant_range = ++ hdmi->hdmi_data.quant_range; ++ ++ /* Initialise info frame from DRM mode */ ++ drm_hdmi_avi_infoframe_from_display_mode(&frame, connector, mode); ++ ++ /* ++ * Ignore monitor selectable quantization, use quantization set ++ * by the user ++ */ ++ drm_hdmi_avi_infoframe_quant_range(&frame, connector, mode, rgb_quant_range); ++ if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) ++ frame.colorspace = HDMI_COLORSPACE_YUV444; ++ else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) ++ frame.colorspace = HDMI_COLORSPACE_YUV422; ++ else if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) ++ frame.colorspace = HDMI_COLORSPACE_YUV420; ++ else ++ frame.colorspace = HDMI_COLORSPACE_RGB; ++ ++ /* Set up colorimetry */ ++ if (!hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { ++ switch (hdmi->hdmi_data.enc_out_encoding) { ++ case V4L2_YCBCR_ENC_601: ++ if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601) ++ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; ++ else ++ frame.colorimetry = HDMI_COLORIMETRY_ITU_601; ++ frame.extended_colorimetry = ++ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; ++ break; ++ case V4L2_YCBCR_ENC_709: ++ if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709) ++ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; ++ else ++ frame.colorimetry = HDMI_COLORIMETRY_ITU_709; ++ frame.extended_colorimetry = ++ HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; ++ break; ++ case V4L2_YCBCR_ENC_BT2020: ++ if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_BT2020) ++ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; ++ else ++ frame.colorimetry = HDMI_COLORIMETRY_ITU_709; ++ frame.extended_colorimetry = ++ HDMI_EXTENDED_COLORIMETRY_BT2020; ++ break; ++ default: /* Carries no data */ ++ frame.colorimetry = HDMI_COLORIMETRY_ITU_601; ++ frame.extended_colorimetry = ++ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; ++ break; ++ } ++ } else { ++ if (hdmi->hdmi_data.enc_out_encoding == V4L2_YCBCR_ENC_BT2020) { ++ frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; ++ frame.extended_colorimetry = ++ HDMI_EXTENDED_COLORIMETRY_BT2020; ++ } else { ++ frame.colorimetry = HDMI_COLORIMETRY_NONE; ++ frame.extended_colorimetry = ++ HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; ++ } ++ } ++ ++ frame.scan_mode = HDMI_SCAN_MODE_NONE; ++ frame.video_code = hdmi->vic; ++ ++ hdmi_avi_infoframe_pack_only(&frame, buff, 17); ++ ++ /* mode which vic >= 128 must use avi version 3 */ ++ if (hdmi->vic >= 128) { ++ frame.version = 3; ++ buff[1] = frame.version; ++ buff[4] &= 0x1f; ++ buff[4] |= ((frame.colorspace & 0x7) << 5); ++ buff[7] = frame.video_code; ++ hdmi_infoframe_set_checksum(buff, 17); ++ } ++ ++ /* ++ * The Designware IP uses a different byte format from standard ++ * AVI info frames, though generally the bits are in the correct ++ * bytes. ++ */ ++ ++ val = (frame.version << 8) | (frame.length << 16); ++ hdmi_writel(hdmi, val, PKT_AVI_CONTENTS0); ++ ++ for (i = 0; i < 4; i++) { ++ for (j = 0; j < 4; j++) { ++ if (i * 4 + j >= 14) ++ break; ++ if (!j) ++ val = buff[i * 4 + j + 3]; ++ val |= buff[i * 4 + j + 3] << (8 * j); ++ } ++ ++ hdmi_writel(hdmi, val, PKT_AVI_CONTENTS1 + i * 4); ++ } ++ ++ hdmi_modb(hdmi, 0, PKTSCHED_AVI_FIELDRATE, PKTSCHED_PKT_CONFIG1); ++ ++ hdmi_modb(hdmi, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, ++ PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, ++ PKTSCHED_PKT_EN); ++} ++ ++static void hdmi_config_CVTEM(struct dw_hdmi_qp *hdmi) ++{ ++ u8 ds_type = 0; ++ u8 sync = 1; ++ u8 vfr = 1; ++ u8 afr = 0; ++ u8 new = 1; ++ u8 end = 0; ++ u8 data_set_length = 136; ++ u8 hb1[6] = { 0x80, 0, 0, 0, 0, 0x40 }; ++ u8 *pps_body; ++ u32 val, i, reg; ++ struct drm_display_mode *mode = &hdmi->previous_mode; ++ int hsync, hfront, hback; ++ struct dw_hdmi_link_config *link_cfg; ++ void *data = hdmi->plat_data->phy_data; ++ ++ hdmi_modb(hdmi, 0, PKTSCHED_EMP_CVTEM_TX_EN, PKTSCHED_PKT_EN); ++ ++ if (hdmi->plat_data->get_link_cfg) { ++ link_cfg = hdmi->plat_data->get_link_cfg(data); ++ } else { ++ dev_err(hdmi->dev, "can't get frl link cfg\n"); ++ return; ++ } ++ ++ if (!link_cfg->dsc_mode) { ++ dev_info(hdmi->dev, "don't use dsc mode\n"); ++ return; ++ } ++ ++ pps_body = link_cfg->pps_payload; ++ ++ hsync = mode->hsync_end - mode->hsync_start; ++ hback = mode->htotal - mode->hsync_end; ++ hfront = mode->hsync_start - mode->hdisplay; ++ ++ for (i = 0; i < 6; i++) { ++ val = i << 16 | hb1[i] << 8; ++ hdmi_writel(hdmi, val, PKT0_EMP_CVTEM_CONTENTS0 + i * 0x20); ++ } ++ ++ val = new << 7 | end << 6 | ds_type << 4 | afr << 3 | ++ vfr << 2 | sync << 1; ++ hdmi_writel(hdmi, val, PKT0_EMP_CVTEM_CONTENTS1); ++ ++ val = data_set_length << 16 | pps_body[0] << 24; ++ hdmi_writel(hdmi, val, PKT0_EMP_CVTEM_CONTENTS2); ++ ++ reg = PKT0_EMP_CVTEM_CONTENTS3; ++ for (i = 1; i < 125; i++) { ++ if (reg == PKT1_EMP_CVTEM_CONTENTS0 || ++ reg == PKT2_EMP_CVTEM_CONTENTS0 || ++ reg == PKT3_EMP_CVTEM_CONTENTS0 || ++ reg == PKT4_EMP_CVTEM_CONTENTS0 || ++ reg == PKT5_EMP_CVTEM_CONTENTS0) { ++ reg += 4; ++ i--; ++ continue; ++ } ++ if (i % 4 == 1) ++ val = pps_body[i]; ++ if (i % 4 == 2) ++ val |= pps_body[i] << 8; ++ if (i % 4 == 3) ++ val |= pps_body[i] << 16; ++ if (!(i % 4)) { ++ val |= pps_body[i] << 24; ++ hdmi_writel(hdmi, val, reg); ++ reg += 4; ++ } ++ } ++ ++ val = (hfront & 0xff) << 24 | pps_body[127] << 16 | ++ pps_body[126] << 8 | pps_body[125]; ++ hdmi_writel(hdmi, val, PKT4_EMP_CVTEM_CONTENTS6); ++ ++ val = (hback & 0xff) << 24 | ((hsync >> 8) & 0xff) << 16 | ++ (hsync & 0xff) << 8 | ((hfront >> 8) & 0xff); ++ hdmi_writel(hdmi, val, PKT4_EMP_CVTEM_CONTENTS7); ++ ++ val = link_cfg->hcactive << 8 | ((hback >> 8) & 0xff); ++ hdmi_writel(hdmi, val, PKT5_EMP_CVTEM_CONTENTS1); ++ ++ for (i = PKT5_EMP_CVTEM_CONTENTS2; i <= PKT5_EMP_CVTEM_CONTENTS7; i += 4) ++ hdmi_writel(hdmi, 0, i); ++ ++ hdmi_modb(hdmi, PKTSCHED_EMP_CVTEM_TX_EN, PKTSCHED_EMP_CVTEM_TX_EN, ++ PKTSCHED_PKT_EN); ++} ++ ++static void hdmi_config_drm_infoframe(struct dw_hdmi_qp *hdmi, ++ const struct drm_connector *connector) ++{ ++ const struct drm_connector_state *conn_state = connector->state; ++ struct hdr_output_metadata *hdr_metadata; ++ struct hdmi_drm_infoframe frame; ++ u8 buffer[30]; ++ ssize_t err; ++ int i; ++ u32 val; ++ ++ if (!hdmi->plat_data->use_drm_infoframe) ++ return; ++ ++ hdmi_modb(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN); ++ ++ if (!hdmi->connector.hdr_sink_metadata.hdmi_type1.eotf) { ++ DRM_DEBUG("No need to set HDR metadata in infoframe\n"); ++ return; ++ } ++ ++ if (!conn_state->hdr_output_metadata) { ++ DRM_DEBUG("source metadata not set yet\n"); ++ return; ++ } ++ ++ hdr_metadata = (struct hdr_output_metadata *) ++ conn_state->hdr_output_metadata->data; ++ ++ if (!(hdmi->connector.hdr_sink_metadata.hdmi_type1.eotf & ++ BIT(hdr_metadata->hdmi_metadata_type1.eotf))) { ++ DRM_ERROR("Not support EOTF %d\n", ++ hdr_metadata->hdmi_metadata_type1.eotf); ++ return; ++ } ++ ++ err = drm_hdmi_infoframe_set_hdr_metadata(&frame, conn_state); ++ if (err < 0) ++ return; ++ ++ err = hdmi_drm_infoframe_pack(&frame, buffer, sizeof(buffer)); ++ if (err < 0) { ++ dev_err(hdmi->dev, "Failed to pack drm infoframe: %zd\n", err); ++ return; ++ } ++ ++ val = (frame.version << 8) | (frame.length << 16); ++ hdmi_writel(hdmi, val, PKT_DRMI_CONTENTS0); ++ ++ for (i = 0; i <= frame.length; i++) { ++ if (i % 4 == 0) ++ val = buffer[3 + i]; ++ val |= buffer[3 + i] << ((i % 4) * 8); ++ ++ if (i % 4 == 3 || (i == (frame.length))) ++ hdmi_writel(hdmi, val, PKT_DRMI_CONTENTS1 + ((i / 4) * 4)); ++ } ++ ++ hdmi_modb(hdmi, 0, PKTSCHED_DRMI_FIELDRATE, PKTSCHED_PKT_CONFIG1); ++ ++ hdmi_modb(hdmi, PKTSCHED_DRMI_TX_EN, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN); ++ ++ DRM_DEBUG("%s eotf %d end\n", __func__, ++ hdr_metadata->hdmi_metadata_type1.eotf); ++} ++ ++/* Filter out invalid setups to avoid configuring SCDC and scrambling */ ++static bool dw_hdmi_support_scdc(struct dw_hdmi_qp *hdmi, ++ const struct drm_display_info *display) ++{ ++ /* Disable if no DDC bus */ ++ if (!hdmi->ddc) ++ return false; ++ ++ /* Disable if SCDC is not supported, or if an HF-VSDB block is absent */ ++ if (!display->hdmi.scdc.supported || ++ !display->hdmi.scdc.scrambling.supported) ++ return false; ++ ++ /* ++ * Disable if display only support low TMDS rates and scrambling ++ * for low rates is not supported either ++ */ ++ if (!display->hdmi.scdc.scrambling.low_rates && ++ display->max_tmds_clock <= 340000) ++ return false; ++ ++ return true; ++} ++ ++static int hdmi_set_frl_mask(int frl_rate) ++{ ++ switch (frl_rate) { ++ case 48: ++ return FRL_12GBPS_4LANE; ++ case 40: ++ return FRL_10GBPS_4LANE; ++ case 32: ++ return FRL_8GBPS_4LANE; ++ case 24: ++ return FRL_6GBPS_4LANE; ++ case 18: ++ return FRL_6GBPS_3LANE; ++ case 9: ++ return FRL_3GBPS_3LANE; ++ } ++ ++ return 0; ++} ++ ++static int hdmi_start_flt(struct dw_hdmi_qp *hdmi, u8 rate) ++{ ++ u8 val; ++ u8 ffe_lv = 0; ++ int i = 0, stat; ++ ++ /* FLT_READY & FFE_LEVELS read */ ++ for (i = 0; i < 20; i++) { ++ drm_scdc_readb(hdmi->ddc, SCDC_STATUS_FLAGS_0, &val); ++ if (val & BIT(6)) ++ break; ++ msleep(20); ++ } ++ ++ if (i == 20) { ++ dev_err(hdmi->dev, "sink flt isn't ready\n"); ++ return -EINVAL; ++ } ++ ++ hdmi_modb(hdmi, SCDC_UPD_FLAGS_RD_IRQ, SCDC_UPD_FLAGS_RD_IRQ, ++ MAINUNIT_1_INT_MASK_N); ++ hdmi_modb(hdmi, SCDC_UPD_FLAGS_POLL_EN | SCDC_UPD_FLAGS_AUTO_CLR, ++ SCDC_UPD_FLAGS_POLL_EN | SCDC_UPD_FLAGS_AUTO_CLR, ++ SCDC_CONFIG0); ++ ++ /* max ffe level 3 */ ++ val = 3 << 4 | hdmi_set_frl_mask(rate); ++ drm_scdc_writeb(hdmi->ddc, 0x31, val); ++ ++ /* select FRL_RATE & FFE_LEVELS */ ++ hdmi_writel(hdmi, ffe_lv, FLT_CONFIG0); ++ ++ /* Start LTS_3 state in source DUT */ ++ reinit_completion(&hdmi->flt_cmp); ++ hdmi_modb(hdmi, FLT_EXIT_TO_LTSP_IRQ, FLT_EXIT_TO_LTSP_IRQ, ++ MAINUNIT_1_INT_MASK_N); ++ hdmi_writel(hdmi, 1, FLT_CONTROL0); ++ ++ /* wait for completed link training at source side */ ++ stat = wait_for_completion_timeout(&hdmi->flt_cmp, HZ * 2); ++ if (!stat) { ++ dev_err(hdmi->dev, "wait lts3 finish time out\n"); ++ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_POLL_EN | ++ SCDC_UPD_FLAGS_AUTO_CLR, SCDC_CONFIG0); ++ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_RD_IRQ, ++ MAINUNIT_1_INT_MASK_N); ++ return -EAGAIN; ++ } ++ ++ if (!(hdmi->flt_intr & FLT_EXIT_TO_LTSP_IRQ)) { ++ dev_err(hdmi->dev, "not to ltsp\n"); ++ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_POLL_EN | ++ SCDC_UPD_FLAGS_AUTO_CLR, SCDC_CONFIG0); ++ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_RD_IRQ, ++ MAINUNIT_1_INT_MASK_N); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++#define HDMI_MODE_FRL_MASK BIT(30) ++ ++static void hdmi_set_op_mode(struct dw_hdmi_qp *hdmi, ++ struct dw_hdmi_link_config *link_cfg, ++ const struct drm_connector *connector) ++{ ++ int frl_rate; ++ int i; ++ ++ /* set sink frl mode disable and wait sink ready */ ++ hdmi_writel(hdmi, 0, FLT_CONFIG0); ++ if (dw_hdmi_support_scdc(hdmi, &connector->display_info)) ++ drm_scdc_writeb(hdmi->ddc, 0x31, 0); ++ /* ++ * some TVs must wait a while before switching frl mode resolution, ++ * or the signal may not be recognized. ++ */ ++ msleep(200); ++ ++ if (!link_cfg->frl_mode) { ++ dev_info(hdmi->dev, "dw hdmi qp use tmds mode\n"); ++ hdmi_modb(hdmi, 0, OPMODE_FRL, LINK_CONFIG0); ++ hdmi_modb(hdmi, 0, OPMODE_FRL_4LANES, LINK_CONFIG0); ++ return; ++ } ++ ++ if (link_cfg->frl_lanes == 4) ++ hdmi_modb(hdmi, OPMODE_FRL_4LANES, OPMODE_FRL_4LANES, ++ LINK_CONFIG0); ++ else ++ hdmi_modb(hdmi, 0, OPMODE_FRL_4LANES, LINK_CONFIG0); ++ ++ hdmi_modb(hdmi, 1, OPMODE_FRL, LINK_CONFIG0); ++ ++ frl_rate = link_cfg->frl_lanes * link_cfg->rate_per_lane; ++ hdmi_start_flt(hdmi, frl_rate); ++ ++ for (i = 0; i < 50; i++) { ++ hdmi_modb(hdmi, PKTSCHED_NULL_TX_EN, PKTSCHED_NULL_TX_EN, PKTSCHED_PKT_EN); ++ mdelay(1); ++ hdmi_modb(hdmi, 0, PKTSCHED_NULL_TX_EN, PKTSCHED_PKT_EN); ++ } ++} ++ ++static unsigned long ++hdmi_get_tmdsclock(struct dw_hdmi_qp *hdmi, unsigned long mpixelclock) ++{ ++ unsigned long tmdsclock = mpixelclock; ++ unsigned int depth = ++ hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format); ++ ++ if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { ++ switch (depth) { ++ case 16: ++ tmdsclock = mpixelclock * 2; ++ break; ++ case 12: ++ tmdsclock = mpixelclock * 3 / 2; ++ break; ++ case 10: ++ tmdsclock = mpixelclock * 5 / 4; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return tmdsclock; ++} ++ ++//[CC:] is connector param different from hdmi->connector? ++//[CC:] probably it possible to hook the whole implementation into dw-hdmi.c ++static int dw_hdmi_qp_setup(struct dw_hdmi_qp *hdmi, ++ struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ int ret; ++ void *data = hdmi->plat_data->phy_data; ++ struct hdmi_vmode_qp *vmode = &hdmi->hdmi_data.video_mode; ++ struct dw_hdmi_link_config *link_cfg; ++ u8 bytes = 0; ++ ++ hdmi->vic = drm_match_cea_mode(mode); ++ if (!hdmi->vic) ++ dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n"); ++ else ++ dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic); ++ ++ if (hdmi->plat_data->get_enc_out_encoding) ++ hdmi->hdmi_data.enc_out_encoding = ++ hdmi->plat_data->get_enc_out_encoding(data); ++ else if ((hdmi->vic == 6) || (hdmi->vic == 7) || ++ (hdmi->vic == 21) || (hdmi->vic == 22) || ++ (hdmi->vic == 2) || (hdmi->vic == 3) || ++ (hdmi->vic == 17) || (hdmi->vic == 18)) ++ hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601; ++ else ++ hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_709; ++ ++ if (mode->flags & DRM_MODE_FLAG_DBLCLK) { ++ hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 1; ++ hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 1; ++ } else { ++ hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; ++ hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0; ++ } ++ /* Get input format from plat data or fallback to RGB888 */ ++ if (hdmi->plat_data->get_input_bus_format) ++ hdmi->hdmi_data.enc_in_bus_format = ++ hdmi->plat_data->get_input_bus_format(data); ++ else if (hdmi->plat_data->input_bus_format) ++ hdmi->hdmi_data.enc_in_bus_format = ++ hdmi->plat_data->input_bus_format; ++ else ++ hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24; ++ ++ /* Default to RGB888 output format */ ++ if (hdmi->plat_data->get_output_bus_format) ++ hdmi->hdmi_data.enc_out_bus_format = ++ hdmi->plat_data->get_output_bus_format(data); ++ else ++ hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24; ++ ++ /* Get input encoding from plat data or fallback to none */ ++ if (hdmi->plat_data->get_enc_in_encoding) ++ hdmi->hdmi_data.enc_in_encoding = ++ hdmi->plat_data->get_enc_in_encoding(data); ++ else if (hdmi->plat_data->input_bus_encoding) ++ hdmi->hdmi_data.enc_in_encoding = ++ hdmi->plat_data->input_bus_encoding; ++ else ++ hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT; ++ ++ if (hdmi->plat_data->get_quant_range) ++ hdmi->hdmi_data.quant_range = ++ hdmi->plat_data->get_quant_range(data); ++ else ++ hdmi->hdmi_data.quant_range = HDMI_QUANTIZATION_RANGE_DEFAULT; ++ ++ if (hdmi->plat_data->get_link_cfg) ++ link_cfg = hdmi->plat_data->get_link_cfg(data); ++ else ++ return -EINVAL; ++ ++ hdmi->phy.ops->set_mode(hdmi, hdmi->phy.data, HDMI_MODE_FRL_MASK, ++ link_cfg->frl_mode); ++ ++ /* ++ * According to the dw-hdmi specification 6.4.2 ++ * vp_pr_cd[3:0]: ++ * 0000b: No pixel repetition (pixel sent only once) ++ * 0001b: Pixel sent two times (pixel repeated once) ++ */ ++ hdmi->hdmi_data.pix_repet_factor = ++ (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 1 : 0; ++ hdmi->hdmi_data.video_mode.mdataenablepolarity = true; ++ ++ vmode->previous_pixelclock = vmode->mpixelclock; ++ //[CC:] no split mode ++ // if (hdmi->plat_data->split_mode) ++ // mode->crtc_clock /= 2; ++ vmode->mpixelclock = mode->crtc_clock * 1000; ++ if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING) ++ vmode->mpixelclock *= 2; ++ dev_dbg(hdmi->dev, "final pixclk = %ld\n", vmode->mpixelclock); ++ vmode->previous_tmdsclock = vmode->mtmdsclock; ++ vmode->mtmdsclock = hdmi_get_tmdsclock(hdmi, vmode->mpixelclock); ++ if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) ++ vmode->mtmdsclock /= 2; ++ dev_info(hdmi->dev, "final tmdsclk = %d\n", vmode->mtmdsclock); ++ ++ ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, &hdmi->previous_mode); ++ if (ret) ++ return ret; ++ ++ if (hdmi->plat_data->set_grf_cfg) ++ hdmi->plat_data->set_grf_cfg(data); ++ ++ /* not for DVI mode */ ++ if (hdmi->sink_is_hdmi) { ++ dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__); ++ hdmi_modb(hdmi, 0, OPMODE_DVI, LINK_CONFIG0); ++ hdmi_modb(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0); ++ if (!link_cfg->frl_mode) { ++ if (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK) { ++ drm_scdc_readb(hdmi->ddc, SCDC_SINK_VERSION, &bytes); ++ drm_scdc_writeb(hdmi->ddc, SCDC_SOURCE_VERSION, ++ min_t(u8, bytes, SCDC_MIN_SOURCE_VERSION)); ++ //[CC:] use dw_hdmi_set_high_tmds_clock_ratio() ++ drm_scdc_set_high_tmds_clock_ratio(connector, 1); ++ drm_scdc_set_scrambling(connector, 1); ++ hdmi_writel(hdmi, 1, SCRAMB_CONFIG0); ++ } else { ++ if (dw_hdmi_support_scdc(hdmi, &connector->display_info)) { ++ drm_scdc_set_high_tmds_clock_ratio(connector, 0); ++ drm_scdc_set_scrambling(connector, 0); ++ } ++ hdmi_writel(hdmi, 0, SCRAMB_CONFIG0); ++ } ++ } ++ /* HDMI Initialization Step F - Configure AVI InfoFrame */ ++ hdmi_config_AVI(hdmi, connector, mode); ++ hdmi_config_CVTEM(hdmi); ++ hdmi_config_drm_infoframe(hdmi, connector); ++ hdmi_set_op_mode(hdmi, link_cfg, connector); ++ } else { ++ hdmi_modb(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0); ++ hdmi_modb(hdmi, OPMODE_DVI, OPMODE_DVI, LINK_CONFIG0); ++ dev_info(hdmi->dev, "%s DVI mode\n", __func__); ++ } ++ ++ return 0; ++} ++ ++static enum drm_connector_status ++dw_hdmi_connector_detect(struct drm_connector *connector, bool force) ++{ ++ struct dw_hdmi_qp *hdmi = ++ container_of(connector, struct dw_hdmi_qp, connector); ++ struct dw_hdmi_qp *secondary = NULL; ++ enum drm_connector_status result, result_secondary; ++ ++ mutex_lock(&hdmi->mutex); ++ hdmi->force = DRM_FORCE_UNSPECIFIED; ++ mutex_unlock(&hdmi->mutex); ++ ++ if (hdmi->plat_data->left) ++ secondary = hdmi->plat_data->left; ++ else if (hdmi->plat_data->right) ++ secondary = hdmi->plat_data->right; ++ ++ result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data); ++ ++ if (secondary) { ++ result_secondary = secondary->phy.ops->read_hpd(secondary, secondary->phy.data); ++ if (result == connector_status_connected && ++ result_secondary == connector_status_connected) ++ result = connector_status_connected; ++ else ++ result = connector_status_disconnected; ++ } ++ ++ mutex_lock(&hdmi->mutex); ++ if (result != hdmi->last_connector_result) { ++ dev_dbg(hdmi->dev, "read_hpd result: %d", result); ++ handle_plugged_change(hdmi, ++ result == connector_status_connected); ++ hdmi->last_connector_result = result; ++ } ++ mutex_unlock(&hdmi->mutex); ++ ++ return result; ++} ++ ++static int ++dw_hdmi_update_hdr_property(struct drm_connector *connector) ++{ ++ struct drm_device *dev = connector->dev; ++ struct dw_hdmi_qp *hdmi = container_of(connector, struct dw_hdmi_qp, ++ connector); ++ void *data = hdmi->plat_data->phy_data; ++ const struct hdr_static_metadata *metadata = ++ &connector->hdr_sink_metadata.hdmi_type1; ++ size_t size = sizeof(*metadata); ++ struct drm_property *property = NULL; ++ struct drm_property_blob *blob; ++ int ret; ++ ++ if (hdmi->plat_data->get_hdr_property) ++ property = hdmi->plat_data->get_hdr_property(data); ++ ++ if (!property) ++ return -EINVAL; ++ ++ if (hdmi->plat_data->get_hdr_blob) ++ blob = hdmi->plat_data->get_hdr_blob(data); ++ else ++ return -EINVAL; ++ ++ ret = drm_property_replace_global_blob(dev, &blob, size, metadata, ++ &connector->base, property); ++ return ret; ++} ++ ++static int dw_hdmi_connector_get_modes(struct drm_connector *connector) ++{ ++ struct dw_hdmi_qp *hdmi = ++ container_of(connector, struct dw_hdmi_qp, connector); ++ struct hdr_static_metadata *metedata = ++ &connector->hdr_sink_metadata.hdmi_type1; ++ struct edid *edid; ++ struct drm_display_mode *mode; ++ struct drm_display_info *info = &connector->display_info; ++ // void *data = hdmi->plat_data->phy_data; ++ int i, ret = 0; ++ ++ if (!hdmi->ddc) ++ return 0; ++ ++ memset(metedata, 0, sizeof(*metedata)); ++ edid = drm_get_edid(connector, hdmi->ddc); ++ if (edid) { ++ dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", ++ edid->width_cm, edid->height_cm); ++ ++ hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); ++ drm_connector_update_edid_property(connector, edid); ++ // if (hdmi->plat_data->get_edid_dsc_info) ++ // hdmi->plat_data->get_edid_dsc_info(data, edid); ++ ret = drm_add_edid_modes(connector, edid); ++ dw_hdmi_update_hdr_property(connector); ++ // if (ret > 0 && hdmi->plat_data->split_mode) { ++ // struct dw_hdmi_qp *secondary = NULL; ++ // void *secondary_data; ++ // ++ // if (hdmi->plat_data->left) ++ // secondary = hdmi->plat_data->left; ++ // else if (hdmi->plat_data->right) ++ // secondary = hdmi->plat_data->right; ++ // ++ // if (!secondary) ++ // return -ENOMEM; ++ // secondary_data = secondary->plat_data->phy_data; ++ // ++ // list_for_each_entry(mode, &connector->probed_modes, head) ++ // hdmi->plat_data->convert_to_split_mode(mode); ++ // ++ // secondary->sink_is_hdmi = drm_detect_hdmi_monitor(edid); ++ // if (secondary->plat_data->get_edid_dsc_info) ++ // secondary->plat_data->get_edid_dsc_info(secondary_data, edid); ++ // } ++ kfree(edid); ++ } else { ++ hdmi->sink_is_hdmi = true; ++ ++ if (hdmi->plat_data->split_mode) { ++ if (hdmi->plat_data->left) { ++ hdmi->plat_data->left->sink_is_hdmi = true; ++ } else if (hdmi->plat_data->right) { ++ hdmi->plat_data->right->sink_is_hdmi = true; ++ } ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(dw_hdmi_default_modes); i++) { ++ const struct drm_display_mode *ptr = ++ &dw_hdmi_default_modes[i]; ++ ++ mode = drm_mode_duplicate(connector->dev, ptr); ++ if (mode) { ++ if (!i) ++ mode->type = DRM_MODE_TYPE_PREFERRED; ++ drm_mode_probed_add(connector, mode); ++ ret++; ++ } ++ } ++ if (ret > 0 && hdmi->plat_data->split_mode) { ++ struct drm_display_mode *mode; ++ ++ list_for_each_entry(mode, &connector->probed_modes, head) ++ hdmi->plat_data->convert_to_split_mode(mode); ++ } ++ info->edid_hdmi_rgb444_dc_modes = 0; ++ info->hdmi.y420_dc_modes = 0; ++ info->color_formats = 0; ++ ++ dev_info(hdmi->dev, "failed to get edid\n"); ++ } ++ ++ return ret; ++} ++ ++static int ++dw_hdmi_atomic_connector_set_property(struct drm_connector *connector, ++ struct drm_connector_state *state, ++ struct drm_property *property, ++ uint64_t val) ++{ ++ struct dw_hdmi_qp *hdmi = ++ container_of(connector, struct dw_hdmi_qp, connector); ++ const struct dw_hdmi_property_ops *ops = hdmi->plat_data->property_ops; ++ ++ if (ops && ops->set_property) ++ return ops->set_property(connector, state, property, ++ val, hdmi->plat_data->phy_data); ++ else ++ return -EINVAL; ++} ++ ++static int ++dw_hdmi_atomic_connector_get_property(struct drm_connector *connector, ++ const struct drm_connector_state *state, ++ struct drm_property *property, ++ uint64_t *val) ++{ ++ struct dw_hdmi_qp *hdmi = ++ container_of(connector, struct dw_hdmi_qp, connector); ++ const struct dw_hdmi_property_ops *ops = hdmi->plat_data->property_ops; ++ ++ if (ops && ops->get_property) ++ return ops->get_property(connector, state, property, ++ val, hdmi->plat_data->phy_data); ++ else ++ return -EINVAL; ++} ++ ++static int ++dw_hdmi_connector_set_property(struct drm_connector *connector, ++ struct drm_property *property, uint64_t val) ++{ ++ return dw_hdmi_atomic_connector_set_property(connector, NULL, ++ property, val); ++} ++ ++static void dw_hdmi_attach_properties(struct dw_hdmi_qp *hdmi) ++{ ++ unsigned int color = MEDIA_BUS_FMT_RGB888_1X24; ++ const struct dw_hdmi_property_ops *ops = ++ hdmi->plat_data->property_ops; ++ ++ if (ops && ops->attach_properties) ++ return ops->attach_properties(&hdmi->connector, color, 0, ++ hdmi->plat_data->phy_data); ++} ++ ++static void dw_hdmi_destroy_properties(struct dw_hdmi_qp *hdmi) ++{ ++ const struct dw_hdmi_property_ops *ops = ++ hdmi->plat_data->property_ops; ++ ++ if (ops && ops->destroy_properties) ++ return ops->destroy_properties(&hdmi->connector, ++ hdmi->plat_data->phy_data); ++} ++ ++static struct drm_encoder * ++dw_hdmi_connector_best_encoder(struct drm_connector *connector) ++{ ++ struct dw_hdmi_qp *hdmi = ++ container_of(connector, struct dw_hdmi_qp, connector); ++ ++ return hdmi->bridge.encoder; ++} ++ ++static bool dw_hdmi_color_changed(struct drm_connector *connector, ++ struct drm_atomic_state *state) ++{ ++ struct dw_hdmi_qp *hdmi = ++ container_of(connector, struct dw_hdmi_qp, connector); ++ void *data = hdmi->plat_data->phy_data; ++ struct drm_connector_state *old_state = ++ drm_atomic_get_old_connector_state(state, connector); ++ struct drm_connector_state *new_state = ++ drm_atomic_get_new_connector_state(state, connector); ++ bool ret = false; ++ ++ if (hdmi->plat_data->get_color_changed) ++ ret = hdmi->plat_data->get_color_changed(data); ++ ++ if (new_state->colorspace != old_state->colorspace) ++ ret = true; ++ ++ return ret; ++} ++ ++static bool hdr_metadata_equal(const struct drm_connector_state *old_state, ++ const struct drm_connector_state *new_state) ++{ ++ struct drm_property_blob *old_blob = old_state->hdr_output_metadata; ++ struct drm_property_blob *new_blob = new_state->hdr_output_metadata; ++ ++ if (!old_blob || !new_blob) ++ return old_blob == new_blob; ++ ++ if (old_blob->length != new_blob->length) ++ return false; ++ ++ return !memcmp(old_blob->data, new_blob->data, old_blob->length); ++} ++ ++static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, ++ struct drm_atomic_state *state) ++{ ++ struct drm_connector_state *old_state = ++ drm_atomic_get_old_connector_state(state, connector); ++ struct drm_connector_state *new_state = ++ drm_atomic_get_new_connector_state(state, connector); ++ struct drm_crtc *crtc = new_state->crtc; ++ struct drm_crtc_state *crtc_state; ++ struct dw_hdmi_qp *hdmi = ++ container_of(connector, struct dw_hdmi_qp, connector); ++ struct drm_display_mode *mode = NULL; ++ void *data = hdmi->plat_data->phy_data; ++ struct hdmi_vmode_qp *vmode = &hdmi->hdmi_data.video_mode; ++ ++ if (!crtc) ++ return 0; ++ ++ crtc_state = drm_atomic_get_crtc_state(state, crtc); ++ if (IS_ERR(crtc_state)) ++ return PTR_ERR(crtc_state); ++ ++ /* ++ * If HDMI is enabled in uboot, it's need to record ++ * drm_display_mode and set phy status to enabled. ++ */ ++ if (!vmode->mpixelclock) { ++ crtc_state = drm_atomic_get_crtc_state(state, crtc); ++ if (hdmi->plat_data->get_enc_in_encoding) ++ hdmi->hdmi_data.enc_in_encoding = ++ hdmi->plat_data->get_enc_in_encoding(data); ++ if (hdmi->plat_data->get_enc_out_encoding) ++ hdmi->hdmi_data.enc_out_encoding = ++ hdmi->plat_data->get_enc_out_encoding(data); ++ if (hdmi->plat_data->get_input_bus_format) ++ hdmi->hdmi_data.enc_in_bus_format = ++ hdmi->plat_data->get_input_bus_format(data); ++ if (hdmi->plat_data->get_output_bus_format) ++ hdmi->hdmi_data.enc_out_bus_format = ++ hdmi->plat_data->get_output_bus_format(data); ++ ++ mode = &crtc_state->mode; ++ if (hdmi->plat_data->split_mode) { ++ hdmi->plat_data->convert_to_origin_mode(mode); ++ mode->crtc_clock /= 2; ++ } ++ memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); ++ vmode->mpixelclock = mode->crtc_clock * 1000; ++ vmode->previous_pixelclock = mode->clock; ++ vmode->previous_tmdsclock = mode->clock; ++ vmode->mtmdsclock = hdmi_get_tmdsclock(hdmi, ++ vmode->mpixelclock); ++ if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) ++ vmode->mtmdsclock /= 2; ++ } ++ ++ if (!hdr_metadata_equal(old_state, new_state) || ++ dw_hdmi_color_changed(connector, state)) { ++ crtc_state = drm_atomic_get_crtc_state(state, crtc); ++ if (IS_ERR(crtc_state)) ++ return PTR_ERR(crtc_state); ++ ++ crtc_state->mode_changed = true; ++ } ++ ++ return 0; ++} ++ ++static void dw_hdmi_connector_force(struct drm_connector *connector) ++{ ++ struct dw_hdmi_qp *hdmi = ++ container_of(connector, struct dw_hdmi_qp, connector); ++ ++ mutex_lock(&hdmi->mutex); ++ ++ if (hdmi->force != connector->force) { ++ if (!hdmi->disabled && connector->force == DRM_FORCE_OFF) ++ extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, ++ false); ++ else if (hdmi->disabled && connector->force == DRM_FORCE_ON) ++ extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, ++ true); ++ } ++ ++ hdmi->force = connector->force; ++ mutex_unlock(&hdmi->mutex); ++} ++ ++static int dw_hdmi_qp_fill_modes(struct drm_connector *connector, u32 max_x, ++ u32 max_y) ++{ ++ return drm_helper_probe_single_connector_modes(connector, 9000, 9000); ++} ++ ++static const struct drm_connector_funcs dw_hdmi_connector_funcs = { ++ .fill_modes = dw_hdmi_qp_fill_modes, ++ .detect = dw_hdmi_connector_detect, ++ .destroy = drm_connector_cleanup, ++ .force = dw_hdmi_connector_force, ++ .reset = drm_atomic_helper_connector_reset, ++ .set_property = dw_hdmi_connector_set_property, ++ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, ++ .atomic_set_property = dw_hdmi_atomic_connector_set_property, ++ .atomic_get_property = dw_hdmi_atomic_connector_get_property, ++}; ++ ++static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = { ++ .get_modes = dw_hdmi_connector_get_modes, ++ .best_encoder = dw_hdmi_connector_best_encoder, ++ .atomic_check = dw_hdmi_connector_atomic_check, ++}; ++ ++static int dw_hdmi_qp_bridge_attach(struct drm_bridge *bridge, ++ enum drm_bridge_attach_flags flags) ++{ ++ struct dw_hdmi_qp *hdmi = bridge->driver_private; ++ struct drm_encoder *encoder = bridge->encoder; ++ struct drm_connector *connector = &hdmi->connector; ++ ++ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) ++ return 0; ++ ++ connector->interlace_allowed = 1; ++ connector->polled = DRM_CONNECTOR_POLL_HPD; ++ ++ drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs); ++ ++ // [CC:] use drm_connector_init_with_ddc or drmm_connector_init ++ // to provide ddc reference ++ drm_connector_init_with_ddc(bridge->dev, connector, ++ &dw_hdmi_connector_funcs, ++ DRM_MODE_CONNECTOR_HDMIA, ++ hdmi->ddc); ++ ++ drm_connector_attach_encoder(connector, encoder); ++ dw_hdmi_attach_properties(hdmi); ++ ++ return 0; ++} ++ ++static void dw_hdmi_qp_bridge_mode_set(struct drm_bridge *bridge, ++ const struct drm_display_mode *orig_mode, ++ const struct drm_display_mode *mode) ++{ ++ struct dw_hdmi_qp *hdmi = bridge->driver_private; ++ ++ mutex_lock(&hdmi->mutex); ++ ++ /* Store the display mode for plugin/DKMS poweron events */ ++ memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); ++ if (hdmi->plat_data->split_mode) ++ hdmi->plat_data->convert_to_origin_mode(&hdmi->previous_mode); ++ ++ mutex_unlock(&hdmi->mutex); ++} ++ ++static enum drm_mode_status ++dw_hdmi_qp_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, ++ const struct drm_display_mode *mode) ++{ ++ return MODE_OK; ++} ++ ++static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) ++{ ++ struct dw_hdmi_qp *hdmi = bridge->driver_private; ++ struct drm_atomic_state *state = old_state->base.state; ++ struct drm_connector *connector; ++ ++ connector = drm_atomic_get_new_connector_for_encoder(state, ++ bridge->encoder); ++ ++ mutex_lock(&hdmi->mutex); ++ hdmi->curr_conn = connector; ++ dw_hdmi_qp_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode); ++ hdmi->disabled = false; ++ mutex_unlock(&hdmi->mutex); ++ ++ extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, true); ++ handle_plugged_change(hdmi, true); ++} ++ ++static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_state) ++{ ++ struct dw_hdmi_qp *hdmi = bridge->driver_private; ++ ++ extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, false); ++ handle_plugged_change(hdmi, false); ++ mutex_lock(&hdmi->mutex); ++ ++ hdmi->curr_conn = NULL; ++ ++ if (hdmi->phy.ops->disable) ++ hdmi->phy.ops->disable(hdmi, hdmi->phy.data); ++ hdmi->disabled = true; ++ mutex_unlock(&hdmi->mutex); ++} ++ ++static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { ++ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, ++ .atomic_reset = drm_atomic_helper_bridge_reset, ++ .attach = dw_hdmi_qp_bridge_attach, ++ .mode_set = dw_hdmi_qp_bridge_mode_set, ++ .mode_valid = dw_hdmi_qp_bridge_mode_valid, ++ .atomic_enable = dw_hdmi_qp_bridge_atomic_enable, ++ .atomic_disable = dw_hdmi_qp_bridge_atomic_disable, ++}; ++ ++static irqreturn_t dw_hdmi_qp_main_hardirq(int irq, void *dev_id) ++{ ++ struct dw_hdmi_qp *hdmi = dev_id; ++ struct dw_hdmi_qp_i2c *i2c = hdmi->i2c; ++ u32 stat; ++ ++ stat = hdmi_readl(hdmi, MAINUNIT_1_INT_STATUS); ++ ++ i2c->stat = stat & (I2CM_OP_DONE_IRQ | I2CM_READ_REQUEST_IRQ | ++ I2CM_NACK_RCVD_IRQ); ++ hdmi->scdc_intr = stat & (SCDC_UPD_FLAGS_RD_IRQ | ++ SCDC_UPD_FLAGS_CHG_IRQ | ++ SCDC_UPD_FLAGS_CLR_IRQ | ++ SCDC_RR_REPLY_STOP_IRQ | ++ SCDC_NACK_RCVD_IRQ); ++ hdmi->flt_intr = stat & (FLT_EXIT_TO_LTSP_IRQ | ++ FLT_EXIT_TO_LTS4_IRQ | ++ FLT_EXIT_TO_LTSL_IRQ); ++ ++ if (i2c->stat) { ++ hdmi_writel(hdmi, i2c->stat, MAINUNIT_1_INT_CLEAR); ++ complete(&i2c->cmp); ++ } ++ ++ if (hdmi->flt_intr) { ++ dev_dbg(hdmi->dev, "i2c flt irq:%#x\n", hdmi->flt_intr); ++ hdmi_writel(hdmi, hdmi->flt_intr, MAINUNIT_1_INT_CLEAR); ++ complete(&hdmi->flt_cmp); ++ } ++ ++ if (hdmi->scdc_intr) { ++ u8 val; ++ ++ dev_dbg(hdmi->dev, "i2c scdc irq:%#x\n", hdmi->scdc_intr); ++ hdmi_writel(hdmi, hdmi->scdc_intr, MAINUNIT_1_INT_CLEAR); ++ val = hdmi_readl(hdmi, SCDC_STATUS0); ++ ++ /* frl start */ ++ if (val & BIT(4)) { ++ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_POLL_EN | ++ SCDC_UPD_FLAGS_AUTO_CLR, SCDC_CONFIG0); ++ hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_RD_IRQ, ++ MAINUNIT_1_INT_MASK_N); ++ dev_info(hdmi->dev, "frl start\n"); ++ } ++ ++ } ++ ++ if (stat) ++ return IRQ_HANDLED; ++ ++ return IRQ_NONE; ++} ++ ++static irqreturn_t dw_hdmi_qp_avp_hardirq(int irq, void *dev_id) ++{ ++ struct dw_hdmi_qp *hdmi = dev_id; ++ u32 stat; ++ ++ stat = hdmi_readl(hdmi, AVP_1_INT_STATUS); ++ if (stat) { ++ dev_dbg(hdmi->dev, "HDCP irq %#x\n", stat); ++ stat &= ~stat; ++ hdmi_writel(hdmi, stat, AVP_1_INT_MASK_N); ++ return IRQ_WAKE_THREAD; ++ } ++ ++ return IRQ_NONE; ++} ++ ++static irqreturn_t dw_hdmi_qp_earc_hardirq(int irq, void *dev_id) ++{ ++ struct dw_hdmi_qp *hdmi = dev_id; ++ u32 stat; ++ ++ stat = hdmi_readl(hdmi, EARCRX_0_INT_STATUS); ++ if (stat) { ++ dev_dbg(hdmi->dev, "earc irq %#x\n", stat); ++ stat &= ~stat; ++ hdmi_writel(hdmi, stat, EARCRX_0_INT_MASK_N); ++ return IRQ_WAKE_THREAD; ++ } ++ ++ return IRQ_NONE; ++} ++ ++static irqreturn_t dw_hdmi_qp_avp_irq(int irq, void *dev_id) ++{ ++ struct dw_hdmi_qp *hdmi = dev_id; ++ u32 stat; ++ ++ stat = hdmi_readl(hdmi, AVP_1_INT_STATUS); ++ ++ if (!stat) ++ return IRQ_NONE; ++ ++ hdmi_writel(hdmi, stat, AVP_1_INT_CLEAR); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t dw_hdmi_qp_earc_irq(int irq, void *dev_id) ++{ ++ struct dw_hdmi_qp *hdmi = dev_id; ++ u32 stat; ++ ++ stat = hdmi_readl(hdmi, EARCRX_0_INT_STATUS); ++ ++ if (!stat) ++ return IRQ_NONE; ++ ++ hdmi_writel(hdmi, stat, EARCRX_0_INT_CLEAR); ++ ++ hdmi->earc_intr = stat; ++ complete(&hdmi->earc_cmp); ++ ++ return IRQ_HANDLED; ++} ++ ++static int dw_hdmi_detect_phy(struct dw_hdmi_qp *hdmi) ++{ ++ u8 phy_type; ++ ++ phy_type = hdmi->plat_data->phy_force_vendor ? ++ DW_HDMI_PHY_VENDOR_PHY : 0; ++ ++ if (phy_type == DW_HDMI_PHY_VENDOR_PHY) { ++ /* Vendor PHYs require support from the glue layer. */ ++ if (!hdmi->plat_data->qp_phy_ops || !hdmi->plat_data->phy_name) { ++ dev_err(hdmi->dev, ++ "Vendor HDMI PHY not supported by glue layer\n"); ++ return -ENODEV; ++ } ++ ++ hdmi->phy.ops = hdmi->plat_data->qp_phy_ops; ++ hdmi->phy.data = hdmi->plat_data->phy_data; ++ hdmi->phy.name = hdmi->plat_data->phy_name; ++ } ++ ++ return 0; ++} ++ ++static const struct regmap_config hdmi_regmap_config = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .max_register = EARCRX_1_INT_FORCE, ++}; ++ ++struct dw_hdmi_qp_reg_table { ++ int reg_base; ++ int reg_end; ++}; ++ ++static const struct dw_hdmi_qp_reg_table hdmi_reg_table[] = { ++ {0x0, 0xc}, ++ {0x14, 0x1c}, ++ {0x44, 0x48}, ++ {0x50, 0x58}, ++ {0x80, 0x84}, ++ {0xa0, 0xc4}, ++ {0xe0, 0xe8}, ++ {0xf0, 0x118}, ++ {0x140, 0x140}, ++ {0x150, 0x150}, ++ {0x160, 0x168}, ++ {0x180, 0x180}, ++ {0x800, 0x800}, ++ {0x808, 0x808}, ++ {0x814, 0x814}, ++ {0x81c, 0x824}, ++ {0x834, 0x834}, ++ {0x840, 0x864}, ++ {0x86c, 0x86c}, ++ {0x880, 0x89c}, ++ {0x8e0, 0x8e8}, ++ {0x900, 0x900}, ++ {0x908, 0x90c}, ++ {0x920, 0x938}, ++ {0x920, 0x938}, ++ {0x960, 0x960}, ++ {0x968, 0x968}, ++ {0xa20, 0xa20}, ++ {0xa30, 0xa30}, ++ {0xa40, 0xa40}, ++ {0xa54, 0xa54}, ++ {0xa80, 0xaac}, ++ {0xab4, 0xab8}, ++ {0xb00, 0xcbc}, ++ {0xce0, 0xce0}, ++ {0xd00, 0xddc}, ++ {0xe20, 0xe24}, ++ {0xe40, 0xe44}, ++ {0xe4c, 0xe4c}, ++ {0xe60, 0xe80}, ++ {0xea0, 0xf24}, ++ {0x1004, 0x100c}, ++ {0x1020, 0x1030}, ++ {0x1040, 0x1050}, ++ {0x1060, 0x1068}, ++ {0x1800, 0x1820}, ++ {0x182c, 0x182c}, ++ {0x1840, 0x1940}, ++ {0x1960, 0x1a60}, ++ {0x1b00, 0x1b00}, ++ {0x1c00, 0x1c00}, ++ {0x3000, 0x3000}, ++ {0x3010, 0x3014}, ++ {0x3020, 0x3024}, ++ {0x3800, 0x3800}, ++ {0x3810, 0x3814}, ++ {0x3820, 0x3824}, ++ {0x3830, 0x3834}, ++ {0x3840, 0x3844}, ++ {0x3850, 0x3854}, ++ {0x3860, 0x3864}, ++ {0x3870, 0x3874}, ++ {0x4000, 0x4004}, ++ {0x4800, 0x4800}, ++ {0x4810, 0x4814}, ++}; ++ ++static int dw_hdmi_ctrl_show(struct seq_file *s, void *v) ++{ ++ struct dw_hdmi_qp *hdmi = s->private; ++ u32 i = 0, j = 0, val = 0; ++ ++ seq_puts(s, "\n---------------------------------------------------"); ++ ++ for (i = 0; i < ARRAY_SIZE(hdmi_reg_table); i++) { ++ for (j = hdmi_reg_table[i].reg_base; ++ j <= hdmi_reg_table[i].reg_end; j += 4) { ++ val = hdmi_readl(hdmi, j); ++ ++ if ((j - hdmi_reg_table[i].reg_base) % 16 == 0) ++ seq_printf(s, "\n>>>hdmi_ctl %04x:", j); ++ seq_printf(s, " %08x", val); ++ } ++ } ++ seq_puts(s, "\n---------------------------------------------------\n"); ++ ++ return 0; ++} ++ ++static int dw_hdmi_ctrl_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, dw_hdmi_ctrl_show, inode->i_private); ++} ++ ++static ssize_t ++dw_hdmi_ctrl_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dw_hdmi_qp *hdmi = ++ ((struct seq_file *)file->private_data)->private; ++ u32 reg, val; ++ char kbuf[25]; ++ ++ if (count > 24) { ++ dev_err(hdmi->dev, "out of buf range\n"); ++ return count; ++ } ++ ++ if (copy_from_user(kbuf, buf, count)) ++ return -EFAULT; ++ kbuf[count - 1] = '\0'; ++ ++ if (sscanf(kbuf, "%x %x", ®, &val) == -1) ++ return -EFAULT; ++ if (reg > EARCRX_1_INT_FORCE) { ++ dev_err(hdmi->dev, "it is no a hdmi register\n"); ++ return count; ++ } ++ dev_info(hdmi->dev, "/**********hdmi register config******/"); ++ dev_info(hdmi->dev, "\n reg=%x val=%x\n", reg, val); ++ hdmi_writel(hdmi, val, reg); ++ return count; ++} ++ ++static const struct file_operations dw_hdmi_ctrl_fops = { ++ .owner = THIS_MODULE, ++ .open = dw_hdmi_ctrl_open, ++ .read = seq_read, ++ .write = dw_hdmi_ctrl_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int dw_hdmi_status_show(struct seq_file *s, void *v) ++{ ++ struct dw_hdmi_qp *hdmi = s->private; ++ u32 val; ++ ++ seq_puts(s, "PHY: "); ++ if (hdmi->disabled) { ++ seq_puts(s, "disabled\n"); ++ return 0; ++ } ++ seq_puts(s, "enabled\t\t\tMode: "); ++ if (hdmi->sink_is_hdmi) ++ seq_puts(s, "HDMI\n"); ++ else ++ seq_puts(s, "DVI\n"); ++ ++ if (hdmi->hdmi_data.video_mode.mpixelclock > 600000000) { ++ seq_printf(s, "FRL Mode Pixel Clk: %luHz\n", ++ hdmi->hdmi_data.video_mode.mpixelclock); ++ } else { ++ if (hdmi->hdmi_data.video_mode.mtmdsclock > 340000000) ++ val = hdmi->hdmi_data.video_mode.mtmdsclock / 4; ++ else ++ val = hdmi->hdmi_data.video_mode.mtmdsclock; ++ seq_printf(s, "TMDS Mode Pixel Clk: %luHz\t\tTMDS Clk: %uHz\n", ++ hdmi->hdmi_data.video_mode.mpixelclock, val); ++ } ++ ++ seq_puts(s, "Color Format: "); ++ if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) ++ seq_puts(s, "RGB"); ++ else if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) ++ seq_puts(s, "YUV444"); ++ else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) ++ seq_puts(s, "YUV422"); ++ else if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) ++ seq_puts(s, "YUV420"); ++ else ++ seq_puts(s, "UNKNOWN"); ++ val = hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format); ++ seq_printf(s, "\t\tColor Depth: %d bit\n", val); ++ seq_puts(s, "Colorimetry: "); ++ switch (hdmi->hdmi_data.enc_out_encoding) { ++ case V4L2_YCBCR_ENC_601: ++ seq_puts(s, "ITU.BT601"); ++ break; ++ case V4L2_YCBCR_ENC_709: ++ seq_puts(s, "ITU.BT709"); ++ break; ++ case V4L2_YCBCR_ENC_BT2020: ++ seq_puts(s, "ITU.BT2020"); ++ break; ++ default: /* Carries no data */ ++ seq_puts(s, "ITU.BT601"); ++ break; ++ } ++ ++ seq_puts(s, "\t\tEOTF: "); ++ ++ val = hdmi_readl(hdmi, PKTSCHED_PKT_EN); ++ if (!(val & PKTSCHED_DRMI_TX_EN)) { ++ seq_puts(s, "Off\n"); ++ return 0; ++ } ++ ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS1); ++ val = (val >> 8) & 0x7; ++ switch (val) { ++ case HDMI_EOTF_TRADITIONAL_GAMMA_SDR: ++ seq_puts(s, "SDR"); ++ break; ++ case HDMI_EOTF_TRADITIONAL_GAMMA_HDR: ++ seq_puts(s, "HDR"); ++ break; ++ case HDMI_EOTF_SMPTE_ST2084: ++ seq_puts(s, "ST2084"); ++ break; ++ case HDMI_EOTF_BT_2100_HLG: ++ seq_puts(s, "HLG"); ++ break; ++ default: ++ seq_puts(s, "Not Defined\n"); ++ return 0; ++ } ++ ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS1); ++ val = (val >> 16) & 0xffff; ++ seq_printf(s, "\nx0: %d", val); ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS2); ++ val = val & 0xffff; ++ seq_printf(s, "\t\t\t\ty0: %d\n", val); ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS2); ++ val = (val >> 16) & 0xffff; ++ seq_printf(s, "x1: %d", val); ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS3); ++ val = val & 0xffff; ++ seq_printf(s, "\t\t\t\ty1: %d\n", val); ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS3); ++ val = (val >> 16) & 0xffff; ++ seq_printf(s, "x2: %d", val); ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS4); ++ val = val & 0xffff; ++ seq_printf(s, "\t\t\t\ty2: %d\n", val); ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS4); ++ val = (val >> 16) & 0xffff; ++ seq_printf(s, "white x: %d", val); ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS5); ++ val = val & 0xffff; ++ seq_printf(s, "\t\t\twhite y: %d\n", val); ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS5); ++ val = (val >> 16) & 0xffff; ++ seq_printf(s, "max lum: %d", val); ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS6); ++ val = val & 0xffff; ++ seq_printf(s, "\t\t\tmin lum: %d\n", val); ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS6); ++ val = (val >> 16) & 0xffff; ++ seq_printf(s, "max cll: %d", val); ++ val = hdmi_readl(hdmi, PKT_DRMI_CONTENTS7); ++ val = val & 0xffff; ++ seq_printf(s, "\t\t\tmax fall: %d\n", val); ++ return 0; ++} ++ ++static int dw_hdmi_status_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, dw_hdmi_status_show, inode->i_private); ++} ++ ++static const struct file_operations dw_hdmi_status_fops = { ++ .owner = THIS_MODULE, ++ .open = dw_hdmi_status_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static void dw_hdmi_register_debugfs(struct device *dev, struct dw_hdmi_qp *hdmi) ++{ ++ u8 buf[11]; ++ ++ snprintf(buf, sizeof(buf), "dw-hdmi%d", hdmi->plat_data->id); ++ hdmi->debugfs_dir = debugfs_create_dir(buf, NULL); ++ if (IS_ERR(hdmi->debugfs_dir)) { ++ dev_err(dev, "failed to create debugfs dir!\n"); ++ return; ++ } ++ ++ debugfs_create_file("status", 0400, hdmi->debugfs_dir, ++ hdmi, &dw_hdmi_status_fops); ++ debugfs_create_file("ctrl", 0600, hdmi->debugfs_dir, ++ hdmi, &dw_hdmi_ctrl_fops); ++} ++ ++static struct dw_hdmi_qp * ++__dw_hdmi_probe(struct platform_device *pdev, ++ const struct dw_hdmi_plat_data *plat_data) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct device_node *ddc_node; ++ struct dw_hdmi_qp *hdmi; ++ struct resource *iores = NULL; ++ int irq; ++ int ret; ++ ++ hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); ++ if (!hdmi) ++ return ERR_PTR(-ENOMEM); ++ ++ hdmi->connector.stereo_allowed = 1; ++ hdmi->plat_data = plat_data; ++ hdmi->dev = dev; ++ hdmi->disabled = true; ++ ++ mutex_init(&hdmi->mutex); ++ ++ ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); ++ if (ddc_node) { ++ hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node); ++ of_node_put(ddc_node); ++ if (!hdmi->ddc) { ++ dev_dbg(hdmi->dev, "failed to read ddc node\n"); ++ return ERR_PTR(-EPROBE_DEFER); ++ } ++ ++ } else { ++ dev_dbg(hdmi->dev, "no ddc property found\n"); ++ } ++ ++ if (!plat_data->regm) { ++ const struct regmap_config *reg_config; ++ ++ reg_config = &hdmi_regmap_config; ++ ++ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ hdmi->regs = devm_ioremap_resource(dev, iores); ++ if (IS_ERR(hdmi->regs)) { ++ ret = PTR_ERR(hdmi->regs); ++ goto err_res; ++ } ++ ++ hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config); ++ if (IS_ERR(hdmi->regm)) { ++ dev_err(dev, "Failed to configure regmap\n"); ++ ret = PTR_ERR(hdmi->regm); ++ goto err_res; ++ } ++ } else { ++ hdmi->regm = plat_data->regm; ++ } ++ ++ ret = dw_hdmi_detect_phy(hdmi); ++ if (ret < 0) ++ goto err_res; ++ ++ hdmi_writel(hdmi, 0, MAINUNIT_0_INT_MASK_N); ++ hdmi_writel(hdmi, 0, MAINUNIT_1_INT_MASK_N); ++ hdmi_writel(hdmi, 428571429, TIMER_BASE_CONFIG0); ++ if ((hdmi_readl(hdmi, CMU_STATUS) & DISPLAY_CLK_MONITOR) == DISPLAY_CLK_LOCKED) { ++ hdmi->initialized = true; ++ hdmi->disabled = false; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ ret = irq; ++ goto err_res; ++ } ++ ++ hdmi->avp_irq = irq; ++ ret = devm_request_threaded_irq(dev, hdmi->avp_irq, ++ dw_hdmi_qp_avp_hardirq, ++ dw_hdmi_qp_avp_irq, IRQF_SHARED, ++ dev_name(dev), hdmi); ++ if (ret) ++ goto err_res; ++ ++ irq = platform_get_irq(pdev, 1); ++ if (irq < 0) { ++ ret = irq; ++ goto err_res; ++ } ++ ++ irq = platform_get_irq(pdev, 2); ++ if (irq < 0) { ++ ret = irq; ++ goto err_res; ++ } ++ ++ hdmi->earc_irq = irq; ++ ret = devm_request_threaded_irq(dev, hdmi->earc_irq, ++ dw_hdmi_qp_earc_hardirq, ++ dw_hdmi_qp_earc_irq, IRQF_SHARED, ++ dev_name(dev), hdmi); ++ if (ret) ++ goto err_res; ++ ++ irq = platform_get_irq(pdev, 3); ++ if (irq < 0) { ++ ret = irq; ++ goto err_res; ++ } ++ ++ hdmi->main_irq = irq; ++ ret = devm_request_threaded_irq(dev, hdmi->main_irq, ++ dw_hdmi_qp_main_hardirq, NULL, ++ IRQF_SHARED, dev_name(dev), hdmi); ++ if (ret) ++ goto err_res; ++ ++ /* If DDC bus is not specified, try to register HDMI I2C bus */ ++ if (!hdmi->ddc) { ++ hdmi->ddc = dw_hdmi_i2c_adapter(hdmi); ++ if (IS_ERR(hdmi->ddc)) ++ hdmi->ddc = NULL; ++ /* ++ * Read high and low time from device tree. If not available use ++ * the default timing scl clock rate is about 99.6KHz. ++ */ ++ if (of_property_read_u32(np, "ddc-i2c-scl-high-time-ns", ++ &hdmi->i2c->scl_high_ns)) ++ hdmi->i2c->scl_high_ns = 4708; ++ if (of_property_read_u32(np, "ddc-i2c-scl-low-time-ns", ++ &hdmi->i2c->scl_low_ns)) ++ hdmi->i2c->scl_low_ns = 4916; ++ } ++ ++ hdmi->bridge.driver_private = hdmi; ++ hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; ++#ifdef CONFIG_OF ++ hdmi->bridge.of_node = pdev->dev.of_node; ++#endif ++ ++ if (hdmi->phy.ops->setup_hpd) ++ hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data); ++ ++ hdmi->connector.ycbcr_420_allowed = hdmi->plat_data->ycbcr_420_allowed; ++ ++ hdmi->extcon = devm_extcon_dev_allocate(hdmi->dev, dw_hdmi_cable); ++ if (IS_ERR(hdmi->extcon)) { ++ dev_err(hdmi->dev, "allocate extcon failed\n"); ++ ret = PTR_ERR(hdmi->extcon); ++ goto err_res; ++ } ++ ++ ret = devm_extcon_dev_register(hdmi->dev, hdmi->extcon); ++ if (ret) { ++ dev_err(hdmi->dev, "failed to register extcon: %d\n", ret); ++ goto err_res; ++ } ++ ++ ret = extcon_set_property_capability(hdmi->extcon, EXTCON_DISP_HDMI, ++ EXTCON_PROP_DISP_HPD); ++ if (ret) { ++ dev_err(hdmi->dev, ++ "failed to set USB property capability: %d\n", ret); ++ goto err_res; ++ } ++ ++ /* Reset HDMI DDC I2C master controller and mute I2CM interrupts */ ++ if (hdmi->i2c) ++ dw_hdmi_i2c_init(hdmi); ++ ++ init_completion(&hdmi->flt_cmp); ++ init_completion(&hdmi->earc_cmp); ++ ++ if (of_property_read_bool(np, "scramble-low-rates")) ++ hdmi->scramble_low_rates = true; ++ ++ dw_hdmi_register_debugfs(dev, hdmi); ++ ++ return hdmi; ++ ++err_res: ++ if (hdmi->i2c) ++ i2c_del_adapter(&hdmi->i2c->adap); ++ else ++ i2c_put_adapter(hdmi->ddc); ++ ++ return ERR_PTR(ret); ++} ++ ++static void __dw_hdmi_remove(struct dw_hdmi_qp *hdmi) ++{ ++ if (hdmi->avp_irq) ++ disable_irq(hdmi->avp_irq); ++ ++ if (hdmi->main_irq) ++ disable_irq(hdmi->main_irq); ++ ++ if (hdmi->earc_irq) ++ disable_irq(hdmi->earc_irq); ++ ++ debugfs_remove_recursive(hdmi->debugfs_dir); ++ ++ if (!hdmi->plat_data->first_screen) { ++ dw_hdmi_destroy_properties(hdmi); ++ hdmi->connector.funcs->destroy(&hdmi->connector); ++ } ++ ++ if (hdmi->audio && !IS_ERR(hdmi->audio)) ++ platform_device_unregister(hdmi->audio); ++ ++ // [CC:] dw_hdmi_rockchip_unbind() also calls drm_encoder_cleanup() ++ // and causes a seg fault due to NULL ptr dererence ++ // if (hdmi->bridge.encoder && !hdmi->plat_data->first_screen) ++ // hdmi->bridge.encoder->funcs->destroy(hdmi->bridge.encoder); ++ // ++ if (!IS_ERR(hdmi->cec)) ++ platform_device_unregister(hdmi->cec); ++ if (hdmi->i2c) ++ i2c_del_adapter(&hdmi->i2c->adap); ++ else ++ i2c_put_adapter(hdmi->ddc); ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Bind/unbind API, used from platforms based on the component framework. ++ */ ++struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, ++ struct drm_encoder *encoder, ++ struct dw_hdmi_plat_data *plat_data) ++{ ++ struct dw_hdmi_qp *hdmi; ++ int ret; ++ ++ hdmi = __dw_hdmi_probe(pdev, plat_data); ++ if (IS_ERR(hdmi)) ++ return hdmi; ++ ++ if (!plat_data->first_screen) { ++ ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL, 0); ++ if (ret) { ++ __dw_hdmi_remove(hdmi); ++ dev_err(hdmi->dev, "Failed to initialize bridge with drm\n"); ++ return ERR_PTR(ret); ++ } ++ ++ plat_data->connector = &hdmi->connector; ++ } ++ ++ if (plat_data->split_mode && !hdmi->plat_data->first_screen) { ++ struct dw_hdmi_qp *secondary = NULL; ++ ++ if (hdmi->plat_data->left) ++ secondary = hdmi->plat_data->left; ++ else if (hdmi->plat_data->right) ++ secondary = hdmi->plat_data->right; ++ ++ if (!secondary) ++ return ERR_PTR(-ENOMEM); ++ ret = drm_bridge_attach(encoder, &secondary->bridge, &hdmi->bridge, ++ DRM_BRIDGE_ATTACH_NO_CONNECTOR); ++ if (ret) ++ return ERR_PTR(ret); ++ } ++ ++ return hdmi; ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind); ++ ++void dw_hdmi_qp_unbind(struct dw_hdmi_qp *hdmi) ++{ ++ __dw_hdmi_remove(hdmi); ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_qp_unbind); ++ ++void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi) ++{ ++ if (!hdmi) { ++ dev_warn(dev, "Hdmi has not been initialized\n"); ++ return; ++ } ++ ++ mutex_lock(&hdmi->mutex); ++ ++ /* ++ * When system shutdown, hdmi should be disabled. ++ * When system suspend, dw_hdmi_qp_bridge_disable will disable hdmi first. ++ * To prevent duplicate operation, we should determine whether hdmi ++ * has been disabled. ++ */ ++ if (!hdmi->disabled) ++ hdmi->disabled = true; ++ mutex_unlock(&hdmi->mutex); ++ ++ if (hdmi->avp_irq) ++ disable_irq(hdmi->avp_irq); ++ ++ if (hdmi->main_irq) ++ disable_irq(hdmi->main_irq); ++ ++ if (hdmi->earc_irq) ++ disable_irq(hdmi->earc_irq); ++ ++ pinctrl_pm_select_sleep_state(dev); ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_qp_suspend); ++ ++void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi) ++{ ++ if (!hdmi) { ++ dev_warn(dev, "Hdmi has not been initialized\n"); ++ return; ++ } ++ ++ hdmi_writel(hdmi, 0, MAINUNIT_0_INT_MASK_N); ++ hdmi_writel(hdmi, 0, MAINUNIT_1_INT_MASK_N); ++ hdmi_writel(hdmi, 428571429, TIMER_BASE_CONFIG0); ++ ++ pinctrl_pm_select_default_state(dev); ++ ++ mutex_lock(&hdmi->mutex); ++ if (hdmi->i2c) ++ dw_hdmi_i2c_init(hdmi); ++ if (hdmi->avp_irq) ++ enable_irq(hdmi->avp_irq); ++ ++ if (hdmi->main_irq) ++ enable_irq(hdmi->main_irq); ++ ++ if (hdmi->earc_irq) ++ enable_irq(hdmi->earc_irq); ++ ++ mutex_unlock(&hdmi->mutex); ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume); ++ ++MODULE_AUTHOR("Algea Cao "); ++MODULE_DESCRIPTION("DW HDMI QP transmitter driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:dw-hdmi-qp"); +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h +@@ -0,0 +1,831 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) Rockchip Electronics Co.Ltd ++ * Author: ++ * Algea Cao ++ */ ++#ifndef __DW_HDMI_QP_H__ ++#define __DW_HDMI_QP_H__ ++/* Main Unit Registers */ ++#define CORE_ID 0x0 ++#define VER_NUMBER 0x4 ++#define VER_TYPE 0x8 ++#define CONFIG_REG 0xc ++#define CONFIG_CEC BIT(28) ++#define CONFIG_AUD_UD BIT(23) ++#define CORE_TIMESTAMP_HHMM 0x14 ++#define CORE_TIMESTAMP_MMDD 0x18 ++#define CORE_TIMESTAMP_YYYY 0x1c ++/* Reset Manager Registers */ ++#define GLOBAL_SWRESET_REQUEST 0x40 ++#define EARCRX_CMDC_SWINIT_P BIT(27) ++#define AVP_DATAPATH_PACKET_AUDIO_SWINIT_P BIT(10) ++#define GLOBAL_SWDISABLE 0x44 ++#define CEC_SWDISABLE BIT(17) ++#define AVP_DATAPATH_PACKET_AUDIO_SWDISABLE BIT(10) ++#define AVP_DATAPATH_VIDEO_SWDISABLE BIT(6) ++#define RESET_MANAGER_CONFIG0 0x48 ++#define RESET_MANAGER_STATUS0 0x50 ++#define RESET_MANAGER_STATUS1 0x54 ++#define RESET_MANAGER_STATUS2 0x58 ++/* Timer Base Registers */ ++#define TIMER_BASE_CONFIG0 0x80 ++#define TIMER_BASE_STATUS0 0x84 ++/* CMU Registers */ ++#define CMU_CONFIG0 0xa0 ++#define CMU_CONFIG1 0xa4 ++#define CMU_CONFIG2 0xa8 ++#define CMU_CONFIG3 0xac ++#define CMU_STATUS 0xb0 ++#define DISPLAY_CLK_MONITOR 0x3f ++#define DISPLAY_CLK_LOCKED 0X15 ++#define EARC_BPCLK_OFF BIT(9) ++#define AUDCLK_OFF BIT(7) ++#define LINKQPCLK_OFF BIT(5) ++#define VIDQPCLK_OFF BIT(3) ++#define IPI_CLK_OFF BIT(1) ++#define CMU_IPI_CLK_FREQ 0xb4 ++#define CMU_VIDQPCLK_FREQ 0xb8 ++#define CMU_LINKQPCLK_FREQ 0xbc ++#define CMU_AUDQPCLK_FREQ 0xc0 ++#define CMU_EARC_BPCLK_FREQ 0xc4 ++/* I2CM Registers */ ++#define I2CM_SM_SCL_CONFIG0 0xe0 ++#define I2CM_FM_SCL_CONFIG0 0xe4 ++#define I2CM_CONFIG0 0xe8 ++#define I2CM_CONTROL0 0xec ++#define I2CM_STATUS0 0xf0 ++#define I2CM_INTERFACE_CONTROL0 0xf4 ++#define I2CM_ADDR 0xff000 ++#define I2CM_SLVADDR 0xfe0 ++#define I2CM_WR_MASK 0x1e ++#define I2CM_EXT_READ BIT(4) ++#define I2CM_SHORT_READ BIT(3) ++#define I2CM_FM_READ BIT(2) ++#define I2CM_FM_WRITE BIT(1) ++#define I2CM_FM_EN BIT(0) ++#define I2CM_INTERFACE_CONTROL1 0xf8 ++#define I2CM_SEG_PTR 0x7f80 ++#define I2CM_SEG_ADDR 0x7f ++#define I2CM_INTERFACE_WRDATA_0_3 0xfc ++#define I2CM_INTERFACE_WRDATA_4_7 0x100 ++#define I2CM_INTERFACE_WRDATA_8_11 0x104 ++#define I2CM_INTERFACE_WRDATA_12_15 0x108 ++#define I2CM_INTERFACE_RDDATA_0_3 0x10c ++#define I2CM_INTERFACE_RDDATA_4_7 0x110 ++#define I2CM_INTERFACE_RDDATA_8_11 0x114 ++#define I2CM_INTERFACE_RDDATA_12_15 0x118 ++/* SCDC Registers */ ++#define SCDC_CONFIG0 0x140 ++#define SCDC_I2C_FM_EN BIT(12) ++#define SCDC_UPD_FLAGS_AUTO_CLR BIT(6) ++#define SCDC_UPD_FLAGS_POLL_EN BIT(4) ++#define SCDC_CONTROL0 0x148 ++#define SCDC_STATUS0 0x150 ++#define STATUS_UPDATE BIT(0) ++#define FRL_START BIT(4) ++#define FLT_UPDATE BIT(5) ++/* FLT Registers */ ++#define FLT_CONFIG0 0x160 ++#define FLT_CONFIG1 0x164 ++#define FLT_CONFIG2 0x168 ++#define FLT_CONTROL0 0x170 ++/* Main Unit 2 Registers */ ++#define MAINUNIT_STATUS0 0x180 ++/* Video Interface Registers */ ++#define VIDEO_INTERFACE_CONFIG0 0x800 ++#define VIDEO_INTERFACE_CONFIG1 0x804 ++#define VIDEO_INTERFACE_CONFIG2 0x808 ++#define VIDEO_INTERFACE_CONTROL0 0x80c ++#define VIDEO_INTERFACE_STATUS0 0x814 ++/* Video Packing Registers */ ++#define VIDEO_PACKING_CONFIG0 0x81c ++/* Audio Interface Registers */ ++#define AUDIO_INTERFACE_CONFIG0 0x820 ++#define AUD_IF_SEL_MSK 0x3 ++#define AUD_IF_SPDIF 0x2 ++#define AUD_IF_I2S 0x1 ++#define AUD_IF_PAI 0x0 ++#define AUD_FIFO_INIT_ON_OVF_MSK BIT(2) ++#define AUD_FIFO_INIT_ON_OVF_EN BIT(2) ++#define I2S_LINES_EN_MSK GENMASK(7, 4) ++#define I2S_LINES_EN(x) BIT(x + 4) ++#define I2S_BPCUV_RCV_MSK BIT(12) ++#define I2S_BPCUV_RCV_EN BIT(12) ++#define I2S_BPCUV_RCV_DIS 0 ++#define SPDIF_LINES_EN GENMASK(19, 16) ++#define AUD_FORMAT_MSK GENMASK(26, 24) ++#define AUD_3DOBA (0x7 << 24) ++#define AUD_3DASP (0x6 << 24) ++#define AUD_MSOBA (0x5 << 24) ++#define AUD_MSASP (0x4 << 24) ++#define AUD_HBR (0x3 << 24) ++#define AUD_DST (0x2 << 24) ++#define AUD_OBA (0x1 << 24) ++#define AUD_ASP (0x0 << 24) ++#define AUDIO_INTERFACE_CONFIG1 0x824 ++#define AUDIO_INTERFACE_CONTROL0 0x82c ++#define AUDIO_FIFO_CLR_P BIT(0) ++#define AUDIO_INTERFACE_STATUS0 0x834 ++/* Frame Composer Registers */ ++#define FRAME_COMPOSER_CONFIG0 0x840 ++#define FRAME_COMPOSER_CONFIG1 0x844 ++#define FRAME_COMPOSER_CONFIG2 0x848 ++#define FRAME_COMPOSER_CONFIG3 0x84c ++#define FRAME_COMPOSER_CONFIG4 0x850 ++#define FRAME_COMPOSER_CONFIG5 0x854 ++#define FRAME_COMPOSER_CONFIG6 0x858 ++#define FRAME_COMPOSER_CONFIG7 0x85c ++#define FRAME_COMPOSER_CONFIG8 0x860 ++#define FRAME_COMPOSER_CONFIG9 0x864 ++#define FRAME_COMPOSER_CONTROL0 0x86c ++/* Video Monitor Registers */ ++#define VIDEO_MONITOR_CONFIG0 0x880 ++#define VIDEO_MONITOR_STATUS0 0x884 ++#define VIDEO_MONITOR_STATUS1 0x888 ++#define VIDEO_MONITOR_STATUS2 0x88c ++#define VIDEO_MONITOR_STATUS3 0x890 ++#define VIDEO_MONITOR_STATUS4 0x894 ++#define VIDEO_MONITOR_STATUS5 0x898 ++#define VIDEO_MONITOR_STATUS6 0x89c ++/* HDCP2 Logic Registers */ ++#define HDCP2LOGIC_CONFIG0 0x8e0 ++#define HDCP2_BYPASS BIT(0) ++#define HDCP2LOGIC_ESM_GPIO_IN 0x8e4 ++#define HDCP2LOGIC_ESM_GPIO_OUT 0x8e8 ++/* HDCP14 Registers */ ++#define HDCP14_CONFIG0 0x900 ++#define HDCP14_CONFIG1 0x904 ++#define HDCP14_CONFIG2 0x908 ++#define HDCP14_CONFIG3 0x90c ++#define HDCP14_KEY_SEED 0x914 ++#define HDCP14_KEY_H 0x918 ++#define HDCP14_KEY_L 0x91c ++#define HDCP14_KEY_STATUS 0x920 ++#define HDCP14_AKSV_H 0x924 ++#define HDCP14_AKSV_L 0x928 ++#define HDCP14_AN_H 0x92c ++#define HDCP14_AN_L 0x930 ++#define HDCP14_STATUS0 0x934 ++#define HDCP14_STATUS1 0x938 ++/* Scrambler Registers */ ++#define SCRAMB_CONFIG0 0x960 ++/* Video Configuration Registers */ ++#define LINK_CONFIG0 0x968 ++#define OPMODE_FRL_4LANES BIT(8) ++#define OPMODE_DVI BIT(4) ++#define OPMODE_FRL BIT(0) ++/* TMDS FIFO Registers */ ++#define TMDS_FIFO_CONFIG0 0x970 ++#define TMDS_FIFO_CONTROL0 0x974 ++/* FRL RSFEC Registers */ ++#define FRL_RSFEC_CONFIG0 0xa20 ++#define FRL_RSFEC_STATUS0 0xa30 ++/* FRL Packetizer Registers */ ++#define FRL_PKTZ_CONFIG0 0xa40 ++#define FRL_PKTZ_CONTROL0 0xa44 ++#define FRL_PKTZ_CONTROL1 0xa50 ++#define FRL_PKTZ_STATUS1 0xa54 ++/* Packet Scheduler Registers */ ++#define PKTSCHED_CONFIG0 0xa80 ++#define PKTSCHED_PRQUEUE0_CONFIG0 0xa84 ++#define PKTSCHED_PRQUEUE1_CONFIG0 0xa88 ++#define PKTSCHED_PRQUEUE2_CONFIG0 0xa8c ++#define PKTSCHED_PRQUEUE2_CONFIG1 0xa90 ++#define PKTSCHED_PRQUEUE2_CONFIG2 0xa94 ++#define PKTSCHED_PKT_CONFIG0 0xa98 ++#define PKTSCHED_PKT_CONFIG1 0xa9c ++#define PKTSCHED_DRMI_FIELDRATE BIT(13) ++#define PKTSCHED_AVI_FIELDRATE BIT(12) ++#define PKTSCHED_PKT_CONFIG2 0xaa0 ++#define PKTSCHED_PKT_CONFIG3 0xaa4 ++#define PKTSCHED_PKT_EN 0xaa8 ++#define PKTSCHED_DRMI_TX_EN BIT(17) ++#define PKTSCHED_AUDI_TX_EN BIT(15) ++#define PKTSCHED_AVI_TX_EN BIT(13) ++#define PKTSCHED_EMP_CVTEM_TX_EN BIT(10) ++#define PKTSCHED_AMD_TX_EN BIT(8) ++#define PKTSCHED_GCP_TX_EN BIT(3) ++#define PKTSCHED_AUDS_TX_EN BIT(2) ++#define PKTSCHED_ACR_TX_EN BIT(1) ++#define PKTSCHED_NULL_TX_EN BIT(0) ++#define PKTSCHED_PKT_CONTROL0 0xaac ++#define PKTSCHED_PKT_SEND 0xab0 ++#define PKTSCHED_PKT_STATUS0 0xab4 ++#define PKTSCHED_PKT_STATUS1 0xab8 ++#define PKT_NULL_CONTENTS0 0xb00 ++#define PKT_NULL_CONTENTS1 0xb04 ++#define PKT_NULL_CONTENTS2 0xb08 ++#define PKT_NULL_CONTENTS3 0xb0c ++#define PKT_NULL_CONTENTS4 0xb10 ++#define PKT_NULL_CONTENTS5 0xb14 ++#define PKT_NULL_CONTENTS6 0xb18 ++#define PKT_NULL_CONTENTS7 0xb1c ++#define PKT_ACP_CONTENTS0 0xb20 ++#define PKT_ACP_CONTENTS1 0xb24 ++#define PKT_ACP_CONTENTS2 0xb28 ++#define PKT_ACP_CONTENTS3 0xb2c ++#define PKT_ACP_CONTENTS4 0xb30 ++#define PKT_ACP_CONTENTS5 0xb34 ++#define PKT_ACP_CONTENTS6 0xb38 ++#define PKT_ACP_CONTENTS7 0xb3c ++#define PKT_ISRC1_CONTENTS0 0xb40 ++#define PKT_ISRC1_CONTENTS1 0xb44 ++#define PKT_ISRC1_CONTENTS2 0xb48 ++#define PKT_ISRC1_CONTENTS3 0xb4c ++#define PKT_ISRC1_CONTENTS4 0xb50 ++#define PKT_ISRC1_CONTENTS5 0xb54 ++#define PKT_ISRC1_CONTENTS6 0xb58 ++#define PKT_ISRC1_CONTENTS7 0xb5c ++#define PKT_ISRC2_CONTENTS0 0xb60 ++#define PKT_ISRC2_CONTENTS1 0xb64 ++#define PKT_ISRC2_CONTENTS2 0xb68 ++#define PKT_ISRC2_CONTENTS3 0xb6c ++#define PKT_ISRC2_CONTENTS4 0xb70 ++#define PKT_ISRC2_CONTENTS5 0xb74 ++#define PKT_ISRC2_CONTENTS6 0xb78 ++#define PKT_ISRC2_CONTENTS7 0xb7c ++#define PKT_GMD_CONTENTS0 0xb80 ++#define PKT_GMD_CONTENTS1 0xb84 ++#define PKT_GMD_CONTENTS2 0xb88 ++#define PKT_GMD_CONTENTS3 0xb8c ++#define PKT_GMD_CONTENTS4 0xb90 ++#define PKT_GMD_CONTENTS5 0xb94 ++#define PKT_GMD_CONTENTS6 0xb98 ++#define PKT_GMD_CONTENTS7 0xb9c ++#define PKT_AMD_CONTENTS0 0xba0 ++#define PKT_AMD_CONTENTS1 0xba4 ++#define PKT_AMD_CONTENTS2 0xba8 ++#define PKT_AMD_CONTENTS3 0xbac ++#define PKT_AMD_CONTENTS4 0xbb0 ++#define PKT_AMD_CONTENTS5 0xbb4 ++#define PKT_AMD_CONTENTS6 0xbb8 ++#define PKT_AMD_CONTENTS7 0xbbc ++#define PKT_VSI_CONTENTS0 0xbc0 ++#define PKT_VSI_CONTENTS1 0xbc4 ++#define PKT_VSI_CONTENTS2 0xbc8 ++#define PKT_VSI_CONTENTS3 0xbcc ++#define PKT_VSI_CONTENTS4 0xbd0 ++#define PKT_VSI_CONTENTS5 0xbd4 ++#define PKT_VSI_CONTENTS6 0xbd8 ++#define PKT_VSI_CONTENTS7 0xbdc ++#define PKT_AVI_CONTENTS0 0xbe0 ++#define HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT BIT(4) ++#define HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR 0x04 ++#define HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR 0x08 ++#define HDMI_FC_AVICONF2_IT_CONTENT_VALID 0x80 ++#define PKT_AVI_CONTENTS1 0xbe4 ++#define PKT_AVI_CONTENTS2 0xbe8 ++#define PKT_AVI_CONTENTS3 0xbec ++#define PKT_AVI_CONTENTS4 0xbf0 ++#define PKT_AVI_CONTENTS5 0xbf4 ++#define PKT_AVI_CONTENTS6 0xbf8 ++#define PKT_AVI_CONTENTS7 0xbfc ++#define PKT_SPDI_CONTENTS0 0xc00 ++#define PKT_SPDI_CONTENTS1 0xc04 ++#define PKT_SPDI_CONTENTS2 0xc08 ++#define PKT_SPDI_CONTENTS3 0xc0c ++#define PKT_SPDI_CONTENTS4 0xc10 ++#define PKT_SPDI_CONTENTS5 0xc14 ++#define PKT_SPDI_CONTENTS6 0xc18 ++#define PKT_SPDI_CONTENTS7 0xc1c ++#define PKT_AUDI_CONTENTS0 0xc20 ++#define PKT_AUDI_CONTENTS1 0xc24 ++#define PKT_AUDI_CONTENTS2 0xc28 ++#define PKT_AUDI_CONTENTS3 0xc2c ++#define PKT_AUDI_CONTENTS4 0xc30 ++#define PKT_AUDI_CONTENTS5 0xc34 ++#define PKT_AUDI_CONTENTS6 0xc38 ++#define PKT_AUDI_CONTENTS7 0xc3c ++#define PKT_NVI_CONTENTS0 0xc40 ++#define PKT_NVI_CONTENTS1 0xc44 ++#define PKT_NVI_CONTENTS2 0xc48 ++#define PKT_NVI_CONTENTS3 0xc4c ++#define PKT_NVI_CONTENTS4 0xc50 ++#define PKT_NVI_CONTENTS5 0xc54 ++#define PKT_NVI_CONTENTS6 0xc58 ++#define PKT_NVI_CONTENTS7 0xc5c ++#define PKT_DRMI_CONTENTS0 0xc60 ++#define PKT_DRMI_CONTENTS1 0xc64 ++#define PKT_DRMI_CONTENTS2 0xc68 ++#define PKT_DRMI_CONTENTS3 0xc6c ++#define PKT_DRMI_CONTENTS4 0xc70 ++#define PKT_DRMI_CONTENTS5 0xc74 ++#define PKT_DRMI_CONTENTS6 0xc78 ++#define PKT_DRMI_CONTENTS7 0xc7c ++#define PKT_GHDMI1_CONTENTS0 0xc80 ++#define PKT_GHDMI1_CONTENTS1 0xc84 ++#define PKT_GHDMI1_CONTENTS2 0xc88 ++#define PKT_GHDMI1_CONTENTS3 0xc8c ++#define PKT_GHDMI1_CONTENTS4 0xc90 ++#define PKT_GHDMI1_CONTENTS5 0xc94 ++#define PKT_GHDMI1_CONTENTS6 0xc98 ++#define PKT_GHDMI1_CONTENTS7 0xc9c ++#define PKT_GHDMI2_CONTENTS0 0xca0 ++#define PKT_GHDMI2_CONTENTS1 0xca4 ++#define PKT_GHDMI2_CONTENTS2 0xca8 ++#define PKT_GHDMI2_CONTENTS3 0xcac ++#define PKT_GHDMI2_CONTENTS4 0xcb0 ++#define PKT_GHDMI2_CONTENTS5 0xcb4 ++#define PKT_GHDMI2_CONTENTS6 0xcb8 ++#define PKT_GHDMI2_CONTENTS7 0xcbc ++/* EMP Packetizer Registers */ ++#define PKT_EMP_CONFIG0 0xce0 ++#define PKT_EMP_CONTROL0 0xcec ++#define PKT_EMP_CONTROL1 0xcf0 ++#define PKT_EMP_CONTROL2 0xcf4 ++#define PKT_EMP_VTEM_CONTENTS0 0xd00 ++#define PKT_EMP_VTEM_CONTENTS1 0xd04 ++#define PKT_EMP_VTEM_CONTENTS2 0xd08 ++#define PKT_EMP_VTEM_CONTENTS3 0xd0c ++#define PKT_EMP_VTEM_CONTENTS4 0xd10 ++#define PKT_EMP_VTEM_CONTENTS5 0xd14 ++#define PKT_EMP_VTEM_CONTENTS6 0xd18 ++#define PKT_EMP_VTEM_CONTENTS7 0xd1c ++#define PKT0_EMP_CVTEM_CONTENTS0 0xd20 ++#define PKT0_EMP_CVTEM_CONTENTS1 0xd24 ++#define PKT0_EMP_CVTEM_CONTENTS2 0xd28 ++#define PKT0_EMP_CVTEM_CONTENTS3 0xd2c ++#define PKT0_EMP_CVTEM_CONTENTS4 0xd30 ++#define PKT0_EMP_CVTEM_CONTENTS5 0xd34 ++#define PKT0_EMP_CVTEM_CONTENTS6 0xd38 ++#define PKT0_EMP_CVTEM_CONTENTS7 0xd3c ++#define PKT1_EMP_CVTEM_CONTENTS0 0xd40 ++#define PKT1_EMP_CVTEM_CONTENTS1 0xd44 ++#define PKT1_EMP_CVTEM_CONTENTS2 0xd48 ++#define PKT1_EMP_CVTEM_CONTENTS3 0xd4c ++#define PKT1_EMP_CVTEM_CONTENTS4 0xd50 ++#define PKT1_EMP_CVTEM_CONTENTS5 0xd54 ++#define PKT1_EMP_CVTEM_CONTENTS6 0xd58 ++#define PKT1_EMP_CVTEM_CONTENTS7 0xd5c ++#define PKT2_EMP_CVTEM_CONTENTS0 0xd60 ++#define PKT2_EMP_CVTEM_CONTENTS1 0xd64 ++#define PKT2_EMP_CVTEM_CONTENTS2 0xd68 ++#define PKT2_EMP_CVTEM_CONTENTS3 0xd6c ++#define PKT2_EMP_CVTEM_CONTENTS4 0xd70 ++#define PKT2_EMP_CVTEM_CONTENTS5 0xd74 ++#define PKT2_EMP_CVTEM_CONTENTS6 0xd78 ++#define PKT2_EMP_CVTEM_CONTENTS7 0xd7c ++#define PKT3_EMP_CVTEM_CONTENTS0 0xd80 ++#define PKT3_EMP_CVTEM_CONTENTS1 0xd84 ++#define PKT3_EMP_CVTEM_CONTENTS2 0xd88 ++#define PKT3_EMP_CVTEM_CONTENTS3 0xd8c ++#define PKT3_EMP_CVTEM_CONTENTS4 0xd90 ++#define PKT3_EMP_CVTEM_CONTENTS5 0xd94 ++#define PKT3_EMP_CVTEM_CONTENTS6 0xd98 ++#define PKT3_EMP_CVTEM_CONTENTS7 0xd9c ++#define PKT4_EMP_CVTEM_CONTENTS0 0xda0 ++#define PKT4_EMP_CVTEM_CONTENTS1 0xda4 ++#define PKT4_EMP_CVTEM_CONTENTS2 0xda8 ++#define PKT4_EMP_CVTEM_CONTENTS3 0xdac ++#define PKT4_EMP_CVTEM_CONTENTS4 0xdb0 ++#define PKT4_EMP_CVTEM_CONTENTS5 0xdb4 ++#define PKT4_EMP_CVTEM_CONTENTS6 0xdb8 ++#define PKT4_EMP_CVTEM_CONTENTS7 0xdbc ++#define PKT5_EMP_CVTEM_CONTENTS0 0xdc0 ++#define PKT5_EMP_CVTEM_CONTENTS1 0xdc4 ++#define PKT5_EMP_CVTEM_CONTENTS2 0xdc8 ++#define PKT5_EMP_CVTEM_CONTENTS3 0xdcc ++#define PKT5_EMP_CVTEM_CONTENTS4 0xdd0 ++#define PKT5_EMP_CVTEM_CONTENTS5 0xdd4 ++#define PKT5_EMP_CVTEM_CONTENTS6 0xdd8 ++#define PKT5_EMP_CVTEM_CONTENTS7 0xddc ++/* Audio Packetizer Registers */ ++#define AUDPKT_CONTROL0 0xe20 ++#define AUDPKT_PBIT_FORCE_EN_MASK BIT(12) ++#define AUDPKT_PBIT_FORCE_EN BIT(12) ++#define AUDPKT_CHSTATUS_OVR_EN_MASK BIT(0) ++#define AUDPKT_CHSTATUS_OVR_EN BIT(0) ++#define AUDPKT_CONTROL1 0xe24 ++#define AUDPKT_ACR_CONTROL0 0xe40 ++#define AUDPKT_ACR_N_VALUE 0xfffff ++#define AUDPKT_ACR_CONTROL1 0xe44 ++#define AUDPKT_ACR_CTS_OVR_VAL_MSK GENMASK(23, 4) ++#define AUDPKT_ACR_CTS_OVR_VAL(x) ((x) << 4) ++#define AUDPKT_ACR_CTS_OVR_EN_MSK BIT(1) ++#define AUDPKT_ACR_CTS_OVR_EN BIT(1) ++#define AUDPKT_ACR_STATUS0 0xe4c ++#define AUDPKT_CHSTATUS_OVR0 0xe60 ++#define AUDPKT_CHSTATUS_OVR1 0xe64 ++/* IEC60958 Byte 3: Sampleing frenuency Bits 24 to 27 */ ++#define AUDPKT_CHSTATUS_SR_MASK GENMASK(3, 0) ++#define AUDPKT_CHSTATUS_SR_22050 0x4 ++#define AUDPKT_CHSTATUS_SR_24000 0x6 ++#define AUDPKT_CHSTATUS_SR_32000 0x3 ++#define AUDPKT_CHSTATUS_SR_44100 0x0 ++#define AUDPKT_CHSTATUS_SR_48000 0x2 ++#define AUDPKT_CHSTATUS_SR_88200 0x8 ++#define AUDPKT_CHSTATUS_SR_96000 0xa ++#define AUDPKT_CHSTATUS_SR_176400 0xc ++#define AUDPKT_CHSTATUS_SR_192000 0xe ++#define AUDPKT_CHSTATUS_SR_768000 0x9 ++#define AUDPKT_CHSTATUS_SR_NOT_INDICATED 0x1 ++/* IEC60958 Byte 4: Original Sampleing frenuency Bits 36 to 39 */ ++#define AUDPKT_CHSTATUS_0SR_MASK GENMASK(15, 12) ++#define AUDPKT_CHSTATUS_OSR_8000 0x6 ++#define AUDPKT_CHSTATUS_OSR_11025 0xa ++#define AUDPKT_CHSTATUS_OSR_12000 0x2 ++#define AUDPKT_CHSTATUS_OSR_16000 0x8 ++#define AUDPKT_CHSTATUS_OSR_22050 0xb ++#define AUDPKT_CHSTATUS_OSR_24000 0x9 ++#define AUDPKT_CHSTATUS_OSR_32000 0xc ++#define AUDPKT_CHSTATUS_OSR_44100 0xf ++#define AUDPKT_CHSTATUS_OSR_48000 0xd ++#define AUDPKT_CHSTATUS_OSR_88200 0x7 ++#define AUDPKT_CHSTATUS_OSR_96000 0x5 ++#define AUDPKT_CHSTATUS_OSR_176400 0x3 ++#define AUDPKT_CHSTATUS_OSR_192000 0x1 ++#define AUDPKT_CHSTATUS_OSR_NOT_INDICATED 0x0 ++#define AUDPKT_CHSTATUS_OVR2 0xe68 ++#define AUDPKT_CHSTATUS_OVR3 0xe6c ++#define AUDPKT_CHSTATUS_OVR4 0xe70 ++#define AUDPKT_CHSTATUS_OVR5 0xe74 ++#define AUDPKT_CHSTATUS_OVR6 0xe78 ++#define AUDPKT_CHSTATUS_OVR7 0xe7c ++#define AUDPKT_CHSTATUS_OVR8 0xe80 ++#define AUDPKT_CHSTATUS_OVR9 0xe84 ++#define AUDPKT_CHSTATUS_OVR10 0xe88 ++#define AUDPKT_CHSTATUS_OVR11 0xe8c ++#define AUDPKT_CHSTATUS_OVR12 0xe90 ++#define AUDPKT_CHSTATUS_OVR13 0xe94 ++#define AUDPKT_CHSTATUS_OVR14 0xe98 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC0 0xea0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC1 0xea4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC2 0xea8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC3 0xeac ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC4 0xeb0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC5 0xeb4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC6 0xeb8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC7 0xebc ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC8 0xec0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC9 0xec4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC10 0xec8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC11 0xecc ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC12 0xed0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC13 0xed4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC14 0xed8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC15 0xedc ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC16 0xee0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC17 0xee4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC18 0xee8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC19 0xeec ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC20 0xef0 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC21 0xef4 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC22 0xef8 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC23 0xefc ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC24 0xf00 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC25 0xf04 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC26 0xf08 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC27 0xf0c ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC28 0xf10 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC29 0xf14 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC30 0xf18 ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC31 0xf1c ++#define AUDPKT_USRDATA_OVR_MSG_GENERIC32 0xf20 ++#define AUDPKT_VBIT_OVR0 0xf24 ++/* CEC Registers */ ++#define CEC_TX_CONTROL 0x1000 ++#define CEC_STATUS 0x1004 ++#define CEC_CONFIG 0x1008 ++#define CEC_ADDR 0x100c ++#define CEC_TX_COUNT 0x1020 ++#define CEC_TX_DATA3_0 0x1024 ++#define CEC_TX_DATA7_4 0x1028 ++#define CEC_TX_DATA11_8 0x102c ++#define CEC_TX_DATA15_12 0x1030 ++#define CEC_RX_COUNT_STATUS 0x1040 ++#define CEC_RX_DATA3_0 0x1044 ++#define CEC_RX_DATA7_4 0x1048 ++#define CEC_RX_DATA11_8 0x104c ++#define CEC_RX_DATA15_12 0x1050 ++#define CEC_LOCK_CONTROL 0x1054 ++#define CEC_RXQUAL_BITTIME_CONFIG 0x1060 ++#define CEC_RX_BITTIME_CONFIG 0x1064 ++#define CEC_TX_BITTIME_CONFIG 0x1068 ++/* eARC RX CMDC Registers */ ++#define EARCRX_CMDC_CONFIG0 0x1800 ++#define EARCRX_XACTREAD_STOP_CFG BIT(26) ++#define EARCRX_XACTREAD_RETRY_CFG BIT(25) ++#define EARCRX_CMDC_DSCVR_EARCVALID0_TO_DISC1 BIT(24) ++#define EARCRX_CMDC_XACT_RESTART_EN BIT(18) ++#define EARCRX_CMDC_CONFIG1 0x1804 ++#define EARCRX_CMDC_CONTROL 0x1808 ++#define EARCRX_CMDC_HEARTBEAT_LOSS_EN BIT(4) ++#define EARCRX_CMDC_DISCOVERY_EN BIT(3) ++#define EARCRX_CONNECTOR_HPD BIT(1) ++#define EARCRX_CMDC_WHITELIST0_CONFIG 0x180c ++#define EARCRX_CMDC_WHITELIST1_CONFIG 0x1810 ++#define EARCRX_CMDC_WHITELIST2_CONFIG 0x1814 ++#define EARCRX_CMDC_WHITELIST3_CONFIG 0x1818 ++#define EARCRX_CMDC_STATUS 0x181c ++#define EARCRX_CMDC_XACT_INFO 0x1820 ++#define EARCRX_CMDC_XACT_ACTION 0x1824 ++#define EARCRX_CMDC_HEARTBEAT_RXSTAT_SE 0x1828 ++#define EARCRX_CMDC_HEARTBEAT_STATUS 0x182c ++#define EARCRX_CMDC_XACT_WR0 0x1840 ++#define EARCRX_CMDC_XACT_WR1 0x1844 ++#define EARCRX_CMDC_XACT_WR2 0x1848 ++#define EARCRX_CMDC_XACT_WR3 0x184c ++#define EARCRX_CMDC_XACT_WR4 0x1850 ++#define EARCRX_CMDC_XACT_WR5 0x1854 ++#define EARCRX_CMDC_XACT_WR6 0x1858 ++#define EARCRX_CMDC_XACT_WR7 0x185c ++#define EARCRX_CMDC_XACT_WR8 0x1860 ++#define EARCRX_CMDC_XACT_WR9 0x1864 ++#define EARCRX_CMDC_XACT_WR10 0x1868 ++#define EARCRX_CMDC_XACT_WR11 0x186c ++#define EARCRX_CMDC_XACT_WR12 0x1870 ++#define EARCRX_CMDC_XACT_WR13 0x1874 ++#define EARCRX_CMDC_XACT_WR14 0x1878 ++#define EARCRX_CMDC_XACT_WR15 0x187c ++#define EARCRX_CMDC_XACT_WR16 0x1880 ++#define EARCRX_CMDC_XACT_WR17 0x1884 ++#define EARCRX_CMDC_XACT_WR18 0x1888 ++#define EARCRX_CMDC_XACT_WR19 0x188c ++#define EARCRX_CMDC_XACT_WR20 0x1890 ++#define EARCRX_CMDC_XACT_WR21 0x1894 ++#define EARCRX_CMDC_XACT_WR22 0x1898 ++#define EARCRX_CMDC_XACT_WR23 0x189c ++#define EARCRX_CMDC_XACT_WR24 0x18a0 ++#define EARCRX_CMDC_XACT_WR25 0x18a4 ++#define EARCRX_CMDC_XACT_WR26 0x18a8 ++#define EARCRX_CMDC_XACT_WR27 0x18ac ++#define EARCRX_CMDC_XACT_WR28 0x18b0 ++#define EARCRX_CMDC_XACT_WR29 0x18b4 ++#define EARCRX_CMDC_XACT_WR30 0x18b8 ++#define EARCRX_CMDC_XACT_WR31 0x18bc ++#define EARCRX_CMDC_XACT_WR32 0x18c0 ++#define EARCRX_CMDC_XACT_WR33 0x18c4 ++#define EARCRX_CMDC_XACT_WR34 0x18c8 ++#define EARCRX_CMDC_XACT_WR35 0x18cc ++#define EARCRX_CMDC_XACT_WR36 0x18d0 ++#define EARCRX_CMDC_XACT_WR37 0x18d4 ++#define EARCRX_CMDC_XACT_WR38 0x18d8 ++#define EARCRX_CMDC_XACT_WR39 0x18dc ++#define EARCRX_CMDC_XACT_WR40 0x18e0 ++#define EARCRX_CMDC_XACT_WR41 0x18e4 ++#define EARCRX_CMDC_XACT_WR42 0x18e8 ++#define EARCRX_CMDC_XACT_WR43 0x18ec ++#define EARCRX_CMDC_XACT_WR44 0x18f0 ++#define EARCRX_CMDC_XACT_WR45 0x18f4 ++#define EARCRX_CMDC_XACT_WR46 0x18f8 ++#define EARCRX_CMDC_XACT_WR47 0x18fc ++#define EARCRX_CMDC_XACT_WR48 0x1900 ++#define EARCRX_CMDC_XACT_WR49 0x1904 ++#define EARCRX_CMDC_XACT_WR50 0x1908 ++#define EARCRX_CMDC_XACT_WR51 0x190c ++#define EARCRX_CMDC_XACT_WR52 0x1910 ++#define EARCRX_CMDC_XACT_WR53 0x1914 ++#define EARCRX_CMDC_XACT_WR54 0x1918 ++#define EARCRX_CMDC_XACT_WR55 0x191c ++#define EARCRX_CMDC_XACT_WR56 0x1920 ++#define EARCRX_CMDC_XACT_WR57 0x1924 ++#define EARCRX_CMDC_XACT_WR58 0x1928 ++#define EARCRX_CMDC_XACT_WR59 0x192c ++#define EARCRX_CMDC_XACT_WR60 0x1930 ++#define EARCRX_CMDC_XACT_WR61 0x1934 ++#define EARCRX_CMDC_XACT_WR62 0x1938 ++#define EARCRX_CMDC_XACT_WR63 0x193c ++#define EARCRX_CMDC_XACT_WR64 0x1940 ++#define EARCRX_CMDC_XACT_RD0 0x1960 ++#define EARCRX_CMDC_XACT_RD1 0x1964 ++#define EARCRX_CMDC_XACT_RD2 0x1968 ++#define EARCRX_CMDC_XACT_RD3 0x196c ++#define EARCRX_CMDC_XACT_RD4 0x1970 ++#define EARCRX_CMDC_XACT_RD5 0x1974 ++#define EARCRX_CMDC_XACT_RD6 0x1978 ++#define EARCRX_CMDC_XACT_RD7 0x197c ++#define EARCRX_CMDC_XACT_RD8 0x1980 ++#define EARCRX_CMDC_XACT_RD9 0x1984 ++#define EARCRX_CMDC_XACT_RD10 0x1988 ++#define EARCRX_CMDC_XACT_RD11 0x198c ++#define EARCRX_CMDC_XACT_RD12 0x1990 ++#define EARCRX_CMDC_XACT_RD13 0x1994 ++#define EARCRX_CMDC_XACT_RD14 0x1998 ++#define EARCRX_CMDC_XACT_RD15 0x199c ++#define EARCRX_CMDC_XACT_RD16 0x19a0 ++#define EARCRX_CMDC_XACT_RD17 0x19a4 ++#define EARCRX_CMDC_XACT_RD18 0x19a8 ++#define EARCRX_CMDC_XACT_RD19 0x19ac ++#define EARCRX_CMDC_XACT_RD20 0x19b0 ++#define EARCRX_CMDC_XACT_RD21 0x19b4 ++#define EARCRX_CMDC_XACT_RD22 0x19b8 ++#define EARCRX_CMDC_XACT_RD23 0x19bc ++#define EARCRX_CMDC_XACT_RD24 0x19c0 ++#define EARCRX_CMDC_XACT_RD25 0x19c4 ++#define EARCRX_CMDC_XACT_RD26 0x19c8 ++#define EARCRX_CMDC_XACT_RD27 0x19cc ++#define EARCRX_CMDC_XACT_RD28 0x19d0 ++#define EARCRX_CMDC_XACT_RD29 0x19d4 ++#define EARCRX_CMDC_XACT_RD30 0x19d8 ++#define EARCRX_CMDC_XACT_RD31 0x19dc ++#define EARCRX_CMDC_XACT_RD32 0x19e0 ++#define EARCRX_CMDC_XACT_RD33 0x19e4 ++#define EARCRX_CMDC_XACT_RD34 0x19e8 ++#define EARCRX_CMDC_XACT_RD35 0x19ec ++#define EARCRX_CMDC_XACT_RD36 0x19f0 ++#define EARCRX_CMDC_XACT_RD37 0x19f4 ++#define EARCRX_CMDC_XACT_RD38 0x19f8 ++#define EARCRX_CMDC_XACT_RD39 0x19fc ++#define EARCRX_CMDC_XACT_RD40 0x1a00 ++#define EARCRX_CMDC_XACT_RD41 0x1a04 ++#define EARCRX_CMDC_XACT_RD42 0x1a08 ++#define EARCRX_CMDC_XACT_RD43 0x1a0c ++#define EARCRX_CMDC_XACT_RD44 0x1a10 ++#define EARCRX_CMDC_XACT_RD45 0x1a14 ++#define EARCRX_CMDC_XACT_RD46 0x1a18 ++#define EARCRX_CMDC_XACT_RD47 0x1a1c ++#define EARCRX_CMDC_XACT_RD48 0x1a20 ++#define EARCRX_CMDC_XACT_RD49 0x1a24 ++#define EARCRX_CMDC_XACT_RD50 0x1a28 ++#define EARCRX_CMDC_XACT_RD51 0x1a2c ++#define EARCRX_CMDC_XACT_RD52 0x1a30 ++#define EARCRX_CMDC_XACT_RD53 0x1a34 ++#define EARCRX_CMDC_XACT_RD54 0x1a38 ++#define EARCRX_CMDC_XACT_RD55 0x1a3c ++#define EARCRX_CMDC_XACT_RD56 0x1a40 ++#define EARCRX_CMDC_XACT_RD57 0x1a44 ++#define EARCRX_CMDC_XACT_RD58 0x1a48 ++#define EARCRX_CMDC_XACT_RD59 0x1a4c ++#define EARCRX_CMDC_XACT_RD60 0x1a50 ++#define EARCRX_CMDC_XACT_RD61 0x1a54 ++#define EARCRX_CMDC_XACT_RD62 0x1a58 ++#define EARCRX_CMDC_XACT_RD63 0x1a5c ++#define EARCRX_CMDC_XACT_RD64 0x1a60 ++#define EARCRX_CMDC_SYNC_CONFIG 0x1b00 ++/* eARC RX DMAC Registers */ ++#define EARCRX_DMAC_PHY_CONTROL 0x1c00 ++#define EARCRX_DMAC_CONFIG 0x1c08 ++#define EARCRX_DMAC_CONTROL0 0x1c0c ++#define EARCRX_DMAC_AUDIO_EN BIT(1) ++#define EARCRX_DMAC_EN BIT(0) ++#define EARCRX_DMAC_CONTROL1 0x1c10 ++#define EARCRX_DMAC_STATUS 0x1c14 ++#define EARCRX_DMAC_CHSTATUS0 0x1c18 ++#define EARCRX_DMAC_CHSTATUS1 0x1c1c ++#define EARCRX_DMAC_CHSTATUS2 0x1c20 ++#define EARCRX_DMAC_CHSTATUS3 0x1c24 ++#define EARCRX_DMAC_CHSTATUS4 0x1c28 ++#define EARCRX_DMAC_CHSTATUS5 0x1c2c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC0 0x1c30 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC1 0x1c34 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC2 0x1c38 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC3 0x1c3c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC4 0x1c40 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC5 0x1c44 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC6 0x1c48 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC7 0x1c4c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC8 0x1c50 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC9 0x1c54 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC10 0x1c58 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC11 0x1c5c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT0 0x1c60 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT1 0x1c64 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT2 0x1c68 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT3 0x1c6c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT4 0x1c70 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT5 0x1c74 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT6 0x1c78 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT7 0x1c7c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT8 0x1c80 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT9 0x1c84 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT10 0x1c88 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT11 0x1c8c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT0 0x1c90 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT1 0x1c94 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT2 0x1c98 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT3 0x1c9c ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT4 0x1ca0 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT5 0x1ca4 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT6 0x1ca8 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT7 0x1cac ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT8 0x1cb0 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT9 0x1cb4 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT10 0x1cb8 ++#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT11 0x1cbc ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC0 0x1cc0 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC1 0x1cc4 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC2 0x1cc8 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC3 0x1ccc ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC4 0x1cd0 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC5 0x1cd4 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC6 0x1cd8 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC7 0x1cdc ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC8 0x1ce0 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC9 0x1ce4 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC10 0x1ce8 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC11 0x1cec ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC12 0x1cf0 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC13 0x1cf4 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC14 0x1cf8 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC15 0x1cfc ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC16 0x1d00 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC17 0x1d04 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC18 0x1d08 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC19 0x1d0c ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC20 0x1d10 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC21 0x1d14 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC22 0x1d18 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC23 0x1d1c ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC24 0x1d20 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC25 0x1d24 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC26 0x1d28 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC27 0x1d2c ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC28 0x1d30 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC29 0x1d34 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC30 0x1d38 ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC31 0x1d3c ++#define EARCRX_DMAC_USRDATA_MSG_GENERIC32 0x1d40 ++#define EARCRX_DMAC_CHSTATUS_STREAMER0 0x1d44 ++#define EARCRX_DMAC_CHSTATUS_STREAMER1 0x1d48 ++#define EARCRX_DMAC_CHSTATUS_STREAMER2 0x1d4c ++#define EARCRX_DMAC_CHSTATUS_STREAMER3 0x1d50 ++#define EARCRX_DMAC_CHSTATUS_STREAMER4 0x1d54 ++#define EARCRX_DMAC_CHSTATUS_STREAMER5 0x1d58 ++#define EARCRX_DMAC_CHSTATUS_STREAMER6 0x1d5c ++#define EARCRX_DMAC_CHSTATUS_STREAMER7 0x1d60 ++#define EARCRX_DMAC_CHSTATUS_STREAMER8 0x1d64 ++#define EARCRX_DMAC_CHSTATUS_STREAMER9 0x1d68 ++#define EARCRX_DMAC_CHSTATUS_STREAMER10 0x1d6c ++#define EARCRX_DMAC_CHSTATUS_STREAMER11 0x1d70 ++#define EARCRX_DMAC_CHSTATUS_STREAMER12 0x1d74 ++#define EARCRX_DMAC_CHSTATUS_STREAMER13 0x1d78 ++#define EARCRX_DMAC_CHSTATUS_STREAMER14 0x1d7c ++#define EARCRX_DMAC_USRDATA_STREAMER0 0x1d80 ++/* Main Unit Interrupt Registers */ ++#define MAIN_INTVEC_INDEX 0x3000 ++#define MAINUNIT_0_INT_STATUS 0x3010 ++#define MAINUNIT_0_INT_MASK_N 0x3014 ++#define MAINUNIT_0_INT_CLEAR 0x3018 ++#define MAINUNIT_0_INT_FORCE 0x301c ++#define MAINUNIT_1_INT_STATUS 0x3020 ++#define FLT_EXIT_TO_LTSL_IRQ BIT(22) ++#define FLT_EXIT_TO_LTS4_IRQ BIT(21) ++#define FLT_EXIT_TO_LTSP_IRQ BIT(20) ++#define SCDC_NACK_RCVD_IRQ BIT(12) ++#define SCDC_RR_REPLY_STOP_IRQ BIT(11) ++#define SCDC_UPD_FLAGS_CLR_IRQ BIT(10) ++#define SCDC_UPD_FLAGS_CHG_IRQ BIT(9) ++#define SCDC_UPD_FLAGS_RD_IRQ BIT(8) ++#define I2CM_NACK_RCVD_IRQ BIT(2) ++#define I2CM_READ_REQUEST_IRQ BIT(1) ++#define I2CM_OP_DONE_IRQ BIT(0) ++#define MAINUNIT_1_INT_MASK_N 0x3024 ++#define I2CM_NACK_RCVD_MASK_N BIT(2) ++#define I2CM_READ_REQUEST_MASK_N BIT(1) ++#define I2CM_OP_DONE_MASK_N BIT(0) ++#define MAINUNIT_1_INT_CLEAR 0x3028 ++#define I2CM_NACK_RCVD_CLEAR BIT(2) ++#define I2CM_READ_REQUEST_CLEAR BIT(1) ++#define I2CM_OP_DONE_CLEAR BIT(0) ++#define MAINUNIT_1_INT_FORCE 0x302c ++/* AVPUNIT Interrupt Registers */ ++#define AVP_INTVEC_INDEX 0x3800 ++#define AVP_0_INT_STATUS 0x3810 ++#define AVP_0_INT_MASK_N 0x3814 ++#define AVP_0_INT_CLEAR 0x3818 ++#define AVP_0_INT_FORCE 0x381c ++#define AVP_1_INT_STATUS 0x3820 ++#define AVP_1_INT_MASK_N 0x3824 ++#define HDCP14_AUTH_CHG_MASK_N BIT(6) ++#define AVP_1_INT_CLEAR 0x3828 ++#define AVP_1_INT_FORCE 0x382c ++#define AVP_2_INT_STATUS 0x3830 ++#define AVP_2_INT_MASK_N 0x3834 ++#define AVP_2_INT_CLEAR 0x3838 ++#define AVP_2_INT_FORCE 0x383c ++#define AVP_3_INT_STATUS 0x3840 ++#define AVP_3_INT_MASK_N 0x3844 ++#define AVP_3_INT_CLEAR 0x3848 ++#define AVP_3_INT_FORCE 0x384c ++#define AVP_4_INT_STATUS 0x3850 ++#define AVP_4_INT_MASK_N 0x3854 ++#define AVP_4_INT_CLEAR 0x3858 ++#define AVP_4_INT_FORCE 0x385c ++#define AVP_5_INT_STATUS 0x3860 ++#define AVP_5_INT_MASK_N 0x3864 ++#define AVP_5_INT_CLEAR 0x3868 ++#define AVP_5_INT_FORCE 0x386c ++#define AVP_6_INT_STATUS 0x3870 ++#define AVP_6_INT_MASK_N 0x3874 ++#define AVP_6_INT_CLEAR 0x3878 ++#define AVP_6_INT_FORCE 0x387c ++/* CEC Interrupt Registers */ ++#define CEC_INT_STATUS 0x4000 ++#define CEC_INT_MASK_N 0x4004 ++#define CEC_INT_CLEAR 0x4008 ++#define CEC_INT_FORCE 0x400c ++/* eARC RX Interrupt Registers */ ++#define EARCRX_INTVEC_INDEX 0x4800 ++#define EARCRX_0_INT_STATUS 0x4810 ++#define EARCRX_CMDC_DISCOVERY_TIMEOUT_IRQ BIT(9) ++#define EARCRX_CMDC_DISCOVERY_DONE_IRQ BIT(8) ++#define EARCRX_0_INT_MASK_N 0x4814 ++#define EARCRX_0_INT_CLEAR 0x4818 ++#define EARCRX_0_INT_FORCE 0x481c ++#define EARCRX_1_INT_STATUS 0x4820 ++#define EARCRX_1_INT_MASK_N 0x4824 ++#define EARCRX_1_INT_CLEAR 0x4828 ++#define EARCRX_1_INT_FORCE 0x482c ++ ++#endif /* __DW_HDMI_QP_H__ */ +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -162,6 +162,8 @@ struct dw_hdmi { + void __iomem *regs; + bool sink_is_hdmi; + bool sink_has_audio; ++ bool support_hdmi; ++ int force_output; + + struct pinctrl *pinctrl; + struct pinctrl_state *default_state; +@@ -254,6 +256,25 @@ static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, + hdmi_modb(hdmi, data << shift, mask, reg); + } + ++static bool dw_hdmi_check_output_type_changed(struct dw_hdmi *hdmi) ++{ ++ bool sink_hdmi; ++ ++ sink_hdmi = hdmi->sink_is_hdmi; ++ ++ if (hdmi->force_output == 1) ++ hdmi->sink_is_hdmi = true; ++ else if (hdmi->force_output == 2) ++ hdmi->sink_is_hdmi = false; ++ else ++ hdmi->sink_is_hdmi = hdmi->support_hdmi; ++ ++ if (sink_hdmi != hdmi->sink_is_hdmi) ++ return true; ++ ++ return false; ++} ++ + static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi) + { + hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL, +@@ -2531,6 +2552,45 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, + return 0; + } + ++void dw_hdmi_set_quant_range(struct dw_hdmi *hdmi) ++{ ++ if (!hdmi->bridge_is_on) ++ return; ++ ++ hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP); ++ dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode); ++ hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP); ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_set_quant_range); ++ ++void dw_hdmi_set_output_type(struct dw_hdmi *hdmi, u64 val) ++{ ++ hdmi->force_output = val; ++ ++ if (!dw_hdmi_check_output_type_changed(hdmi)) ++ return; ++ ++ if (!hdmi->bridge_is_on) ++ return; ++ ++ hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP); ++ dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode); ++ hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP); ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_set_output_type); ++ ++bool dw_hdmi_get_output_whether_hdmi(struct dw_hdmi *hdmi) ++{ ++ return hdmi->sink_is_hdmi; ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_get_output_whether_hdmi); ++ ++int dw_hdmi_get_output_type_cap(struct dw_hdmi *hdmi) ++{ ++ return hdmi->support_hdmi; ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_get_output_type_cap); ++ + static void dw_hdmi_connector_force(struct drm_connector *connector) + { + struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, +@@ -3682,6 +3742,35 @@ void dw_hdmi_unbind(struct dw_hdmi *hdmi) + } + EXPORT_SYMBOL_GPL(dw_hdmi_unbind); + ++void dw_hdmi_suspend(struct dw_hdmi *hdmi) ++{ ++ if (!hdmi) ++ return; ++ ++ mutex_lock(&hdmi->mutex); ++ ++ /* ++ * When system shutdown, hdmi should be disabled. ++ * When system suspend, dw_hdmi_bridge_disable will disable hdmi first. ++ * To prevent duplicate operation, we should determine whether hdmi ++ * has been disabled. ++ */ ++ if (!hdmi->disabled) { ++ hdmi->disabled = true; ++ dw_hdmi_update_power(hdmi); ++ dw_hdmi_update_phy_mask(hdmi); ++ } ++ mutex_unlock(&hdmi->mutex); ++ ++ //[CC: needed?] ++ // if (hdmi->irq) ++ // disable_irq(hdmi->irq); ++ // cancel_delayed_work(&hdmi->work); ++ // flush_workqueue(hdmi->workqueue); ++ pinctrl_pm_select_sleep_state(hdmi->dev); ++} ++EXPORT_SYMBOL_GPL(dw_hdmi_suspend); ++ + void dw_hdmi_resume(struct dw_hdmi *hdmi) + { + dw_hdmi_init_hw(hdmi); +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h +@@ -851,6 +851,10 @@ enum { + HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00, + HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04, + ++/* HDMI_FC_GCP */ ++ HDMI_FC_GCP_SET_AVMUTE = 0x2, ++ HDMI_FC_GCP_CLEAR_AVMUTE = 0x1, ++ + /* FC_DBGFORCE field values */ + HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10, + HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1, +diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c ++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +@@ -4,21 +4,32 @@ + */ + + #include ++#include ++#include + #include + #include + #include + #include ++#include + #include + #include + ++#include ++#include ++#include ++#include + #include + #include + #include + #include + #include + ++#include ++ + #include "rockchip_drm_drv.h" + ++#define HIWORD_UPDATE(val, mask) (val | (mask) << 16) ++ + #define RK3228_GRF_SOC_CON2 0x0408 + #define RK3228_HDMI_SDAIN_MSK BIT(14) + #define RK3228_HDMI_SCLIN_MSK BIT(13) +@@ -29,8 +40,11 @@ + + #define RK3288_GRF_SOC_CON6 0x025C + #define RK3288_HDMI_LCDC_SEL BIT(4) +-#define RK3328_GRF_SOC_CON2 0x0408 ++#define RK3288_GRF_SOC_CON16 0x03a8 ++#define RK3288_HDMI_LCDC0_YUV420 BIT(2) ++#define RK3288_HDMI_LCDC1_YUV420 BIT(3) + ++#define RK3328_GRF_SOC_CON2 0x0408 + #define RK3328_HDMI_SDAIN_MSK BIT(11) + #define RK3328_HDMI_SCLIN_MSK BIT(10) + #define RK3328_HDMI_HPD_IOE BIT(2) +@@ -54,32 +68,177 @@ + #define RK3568_HDMI_SDAIN_MSK BIT(15) + #define RK3568_HDMI_SCLIN_MSK BIT(14) + +-#define HIWORD_UPDATE(val, mask) (val | (mask) << 16) ++#define RK3588_GRF_SOC_CON2 0x0308 ++#define RK3588_HDMI1_HPD_INT_MSK BIT(15) ++#define RK3588_HDMI1_HPD_INT_CLR BIT(14) ++#define RK3588_HDMI0_HPD_INT_MSK BIT(13) ++#define RK3588_HDMI0_HPD_INT_CLR BIT(12) ++#define RK3588_GRF_SOC_CON7 0x031c ++#define RK3588_SET_HPD_PATH_MASK (0x3 << 12) ++#define RK3588_GRF_SOC_STATUS1 0x0384 ++#define RK3588_HDMI0_LOW_MORETHAN100MS BIT(20) ++#define RK3588_HDMI0_HPD_PORT_LEVEL BIT(19) ++#define RK3588_HDMI0_IHPD_PORT BIT(18) ++#define RK3588_HDMI0_OHPD_INT BIT(17) ++#define RK3588_HDMI0_LEVEL_INT BIT(16) ++#define RK3588_HDMI0_INTR_CHANGE_CNT (0x7 << 13) ++#define RK3588_HDMI1_LOW_MORETHAN100MS BIT(28) ++#define RK3588_HDMI1_HPD_PORT_LEVEL BIT(27) ++#define RK3588_HDMI1_IHPD_PORT BIT(26) ++#define RK3588_HDMI1_OHPD_INT BIT(25) ++#define RK3588_HDMI1_LEVEL_INT BIT(24) ++#define RK3588_HDMI1_INTR_CHANGE_CNT (0x7 << 21) ++ ++#define RK3588_GRF_VO1_CON3 0x000c ++#define RK3588_COLOR_FORMAT_MASK 0xf ++#define RK3588_YUV444 0x2 ++#define RK3588_YUV420 0x3 ++#define RK3588_COMPRESSED_DATA 0xb ++#define RK3588_COLOR_DEPTH_MASK (0xf << 4) ++#define RK3588_8BPC (0x5 << 4) ++#define RK3588_10BPC (0x6 << 4) ++#define RK3588_CECIN_MASK BIT(8) ++#define RK3588_SCLIN_MASK BIT(9) ++#define RK3588_SDAIN_MASK BIT(10) ++#define RK3588_MODE_MASK BIT(11) ++#define RK3588_COMPRESS_MODE_MASK BIT(12) ++#define RK3588_I2S_SEL_MASK BIT(13) ++#define RK3588_SPDIF_SEL_MASK BIT(14) ++#define RK3588_GRF_VO1_CON4 0x0010 ++#define RK3588_HDMI21_MASK BIT(0) ++#define RK3588_GRF_VO1_CON9 0x0024 ++#define RK3588_HDMI0_GRANT_SEL BIT(10) ++#define RK3588_HDMI0_GRANT_SW BIT(11) ++#define RK3588_HDMI1_GRANT_SEL BIT(12) ++#define RK3588_HDMI1_GRANT_SW BIT(13) ++#define RK3588_GRF_VO1_CON6 0x0018 ++#define RK3588_GRF_VO1_CON7 0x001c ++ ++#define COLOR_DEPTH_10BIT BIT(31) ++#define HDMI_FRL_MODE BIT(30) ++#define HDMI_EARC_MODE BIT(29) ++ ++#define HDMI20_MAX_RATE 600000 ++#define HDMI_8K60_RATE 2376000 + + /** + * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips + * @lcdsel_grf_reg: grf register offset of lcdc select ++ * @ddc_en_reg: grf register offset of hdmi ddc enable + * @lcdsel_big: reg value of selecting vop big for HDMI + * @lcdsel_lit: reg value of selecting vop little for HDMI ++ * @split_mode: flag indicating split mode capability + */ + struct rockchip_hdmi_chip_data { + int lcdsel_grf_reg; ++ int ddc_en_reg; + u32 lcdsel_big; + u32 lcdsel_lit; ++ bool split_mode; ++}; ++ ++enum hdmi_frl_rate_per_lane { ++ FRL_12G_PER_LANE = 12, ++ FRL_10G_PER_LANE = 10, ++ FRL_8G_PER_LANE = 8, ++ FRL_6G_PER_LANE = 6, ++ FRL_3G_PER_LANE = 3, ++}; ++ ++enum rk_if_color_depth { ++ RK_IF_DEPTH_8, ++ RK_IF_DEPTH_10, ++ RK_IF_DEPTH_12, ++ RK_IF_DEPTH_16, ++ RK_IF_DEPTH_420_10, ++ RK_IF_DEPTH_420_12, ++ RK_IF_DEPTH_420_16, ++ RK_IF_DEPTH_6, ++ RK_IF_DEPTH_MAX, ++}; ++ ++enum rk_if_color_format { ++ RK_IF_FORMAT_RGB, /* default RGB */ ++ RK_IF_FORMAT_YCBCR444, /* YCBCR 444 */ ++ RK_IF_FORMAT_YCBCR422, /* YCBCR 422 */ ++ RK_IF_FORMAT_YCBCR420, /* YCBCR 420 */ ++ RK_IF_FORMAT_YCBCR_HQ, /* Highest subsampled YUV */ ++ RK_IF_FORMAT_YCBCR_LQ, /* Lowest subsampled YUV */ ++ RK_IF_FORMAT_MAX, + }; + + struct rockchip_hdmi { + struct device *dev; + struct regmap *regmap; ++ struct regmap *vo1_regmap; + struct rockchip_encoder encoder; ++ struct drm_device *drm_dev; + const struct rockchip_hdmi_chip_data *chip_data; +- const struct dw_hdmi_plat_data *plat_data; ++ struct dw_hdmi_plat_data *plat_data; ++ struct clk *aud_clk; + struct clk *ref_clk; + struct clk *grf_clk; ++ struct clk *hclk_vio; ++ struct clk *hclk_vo1; ++ struct clk *hclk_vop; ++ struct clk *hpd_clk; ++ struct clk *pclk; ++ struct clk *earc_clk; ++ struct clk *hdmitx_ref; + struct dw_hdmi *hdmi; ++ struct dw_hdmi_qp *hdmi_qp; ++ + struct regulator *avdd_0v9; + struct regulator *avdd_1v8; + struct phy *phy; ++ ++ u32 max_tmdsclk; ++ bool unsupported_yuv_input; ++ bool unsupported_deep_color; ++ bool skip_check_420_mode; ++ u8 force_output; ++ u8 id; ++ bool hpd_stat; ++ bool is_hdmi_qp; ++ bool user_split_mode; ++ ++ unsigned long bus_format; ++ unsigned long output_bus_format; ++ unsigned long enc_out_encoding; ++ int color_changed; ++ int hpd_irq; ++ int vp_id; ++ ++ struct drm_property *color_depth_property; ++ struct drm_property *hdmi_output_property; ++ struct drm_property *colordepth_capacity; ++ struct drm_property *outputmode_capacity; ++ struct drm_property *quant_range; ++ struct drm_property *hdr_panel_metadata_property; ++ struct drm_property *next_hdr_sink_data_property; ++ struct drm_property *output_hdmi_dvi; ++ struct drm_property *output_type_capacity; ++ struct drm_property *user_split_mode_prop; ++ ++ struct drm_property_blob *hdr_panel_blob_ptr; ++ struct drm_property_blob *next_hdr_data_ptr; ++ ++ unsigned int colordepth; ++ unsigned int colorimetry; ++ unsigned int hdmi_quant_range; ++ unsigned int phy_bus_width; ++ enum rk_if_color_format hdmi_output; ++ // struct rockchip_drm_sub_dev sub_dev; ++ ++ u8 max_frl_rate_per_lane; ++ u8 max_lanes; ++ // struct rockchip_drm_dsc_cap dsc_cap; ++ // struct next_hdr_sink_data next_hdr_data; ++ struct dw_hdmi_link_config link_cfg; ++ struct gpio_desc *enable_gpio; ++ ++ struct delayed_work work; ++ struct workqueue_struct *workqueue; + }; + + static struct rockchip_hdmi *to_rockchip_hdmi(struct drm_encoder *encoder) +@@ -202,13 +361,830 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = { + /*pixelclk symbol term vlev*/ + { 74250000, 0x8009, 0x0004, 0x0272}, + { 148500000, 0x802b, 0x0004, 0x028d}, ++ { 165000000, 0x802b, 0x0004, 0x0209}, + { 297000000, 0x8039, 0x0005, 0x028d}, ++ { 594000000, 0x8039, 0x0000, 0x019d}, + { ~0UL, 0x0000, 0x0000, 0x0000} + }; + ++enum ROW_INDEX_BPP { ++ ROW_INDEX_6BPP = 0, ++ ROW_INDEX_8BPP, ++ ROW_INDEX_10BPP, ++ ROW_INDEX_12BPP, ++ ROW_INDEX_23BPP, ++ MAX_ROW_INDEX ++}; ++ ++enum COLUMN_INDEX_BPC { ++ COLUMN_INDEX_8BPC = 0, ++ COLUMN_INDEX_10BPC, ++ COLUMN_INDEX_12BPC, ++ COLUMN_INDEX_14BPC, ++ COLUMN_INDEX_16BPC, ++ MAX_COLUMN_INDEX ++}; ++ ++#define PPS_TABLE_LEN 8 ++#define PPS_BPP_LEN 4 ++#define PPS_BPC_LEN 2 ++ ++struct pps_data { ++ u32 pic_width; ++ u32 pic_height; ++ u32 slice_width; ++ u32 slice_height; ++ bool convert_rgb; ++ u8 bpc; ++ u8 bpp; ++ u8 raw_pps[128]; ++}; ++ ++#if 0 ++/* ++ * Selected Rate Control Related Parameter Recommended Values ++ * from DSC_v1.11 spec & C Model release: DSC_model_20161212 ++ */ ++static struct pps_data pps_datas[PPS_TABLE_LEN] = { ++ { ++ /* 7680x4320/960X96 rgb 8bpc 12bpp */ ++ 7680, 4320, 960, 96, 1, 8, 192, ++ { ++ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xc0, 0x10, 0xe0, ++ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0, ++ 0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9, ++ 0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa, ++ 0x08, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00, ++ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38, ++ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, ++ 0x7d, 0x7e, 0x00, 0x82, 0x00, 0xc0, 0x09, 0x00, ++ 0x09, 0x7e, 0x19, 0xbc, 0x19, 0xba, 0x19, 0xf8, ++ 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76, ++ 0x2a, 0x76, 0x2a, 0x74, 0x3a, 0xb4, 0x52, 0xf4, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ }, ++ }, ++ { ++ /* 7680x4320/960X96 rgb 8bpc 11bpp */ ++ 7680, 4320, 960, 96, 1, 8, 176, ++ { ++ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xb0, 0x10, 0xe0, ++ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28, ++ 0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0, ++ 0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33, ++ 0x0f, 0x00, 0x10, 0xf4, 0x03, 0x0c, 0x20, 0x00, ++ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38, ++ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, ++ 0x7d, 0x7e, 0x00, 0x82, 0x01, 0x00, 0x09, 0x40, ++ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8, ++ 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x76, 0x2a, 0x76, ++ 0x2a, 0x76, 0x2a, 0xb4, 0x3a, 0xb4, 0x52, 0xf4, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ }, ++ }, ++ { ++ /* 7680x4320/960X96 rgb 8bpc 10bpp */ ++ 7680, 4320, 960, 96, 1, 8, 160, ++ { ++ 0x12, 0x00, 0x00, 0x8d, 0x30, 0xa0, 0x10, 0xe0, ++ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0, ++ 0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0, ++ 0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb, ++ 0x16, 0x00, 0x10, 0xec, 0x03, 0x0c, 0x20, 0x00, ++ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38, ++ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, ++ 0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40, ++ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8, ++ 0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6, ++ 0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x5b, 0x34, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ }, ++ }, ++ { ++ /* 7680x4320/960X96 rgb 8bpc 9bpp */ ++ 7680, 4320, 960, 96, 1, 8, 144, ++ { ++ 0x12, 0x00, 0x00, 0x8d, 0x30, 0x90, 0x10, 0xe0, ++ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38, ++ 0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7, ++ 0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa, ++ 0x17, 0x00, 0x10, 0xf1, 0x03, 0x0c, 0x20, 0x00, ++ 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a, 0x38, ++ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, ++ 0x7d, 0x7e, 0x00, 0xc2, 0x01, 0x00, 0x09, 0x40, ++ 0x09, 0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8, ++ 0x1a, 0x38, 0x1a, 0x78, 0x1a, 0x76, 0x2a, 0xb6, ++ 0x2a, 0xb6, 0x2a, 0xf4, 0x3a, 0xf4, 0x63, 0x74, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ }, ++ }, ++ { ++ /* 7680x4320/960X96 rgb 10bpc 12bpp */ ++ 7680, 4320, 960, 96, 1, 10, 192, ++ { ++ 0x12, 0x00, 0x00, 0xad, 0x30, 0xc0, 0x10, 0xe0, ++ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0xa0, ++ 0x01, 0x55, 0x03, 0x90, 0x00, 0x0a, 0x05, 0xc9, ++ 0x00, 0xa0, 0x00, 0x0f, 0x01, 0x44, 0x01, 0xaa, ++ 0x08, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00, ++ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38, ++ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, ++ 0x7d, 0x7e, 0x01, 0x02, 0x11, 0x80, 0x22, 0x00, ++ 0x22, 0x7e, 0x32, 0xbc, 0x32, 0xba, 0x3a, 0xf8, ++ 0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76, ++ 0x4b, 0x76, 0x4b, 0x74, 0x5b, 0xb4, 0x73, 0xf4, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ }, ++ }, ++ { ++ /* 7680x4320/960X96 rgb 10bpc 11bpp */ ++ 7680, 4320, 960, 96, 1, 10, 176, ++ { ++ 0x12, 0x00, 0x00, 0xad, 0x30, 0xb0, 0x10, 0xe0, ++ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x05, 0x28, ++ 0x01, 0x74, 0x03, 0x40, 0x00, 0x0f, 0x06, 0xe0, ++ 0x00, 0x2d, 0x00, 0x0f, 0x01, 0x44, 0x01, 0x33, ++ 0x0f, 0x00, 0x10, 0xf4, 0x07, 0x10, 0x20, 0x00, ++ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38, ++ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, ++ 0x7d, 0x7e, 0x01, 0x42, 0x19, 0xc0, 0x2a, 0x40, ++ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8, ++ 0x3b, 0x38, 0x3b, 0x38, 0x3b, 0x76, 0x4b, 0x76, ++ 0x4b, 0x76, 0x4b, 0xb4, 0x5b, 0xb4, 0x73, 0xf4, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ }, ++ }, ++ { ++ /* 7680x4320/960X96 rgb 10bpc 10bpp */ ++ 7680, 4320, 960, 96, 1, 10, 160, ++ { ++ 0x12, 0x00, 0x00, 0xad, 0x30, 0xa0, 0x10, 0xe0, ++ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0xb0, ++ 0x01, 0x9a, 0x02, 0xe0, 0x00, 0x19, 0x09, 0xb0, ++ 0x00, 0x12, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xbb, ++ 0x16, 0x00, 0x10, 0xec, 0x07, 0x10, 0x20, 0x00, ++ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38, ++ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, ++ 0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40, ++ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8, ++ 0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6, ++ 0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x7c, 0x34, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ }, ++ }, ++ { ++ /* 7680x4320/960X96 rgb 10bpc 9bpp */ ++ 7680, 4320, 960, 96, 1, 10, 144, ++ { ++ 0x12, 0x00, 0x00, 0xad, 0x30, 0x90, 0x10, 0xe0, ++ 0x1e, 0x00, 0x00, 0x60, 0x03, 0xc0, 0x04, 0x38, ++ 0x01, 0xc7, 0x03, 0x16, 0x00, 0x1c, 0x08, 0xc7, ++ 0x00, 0x10, 0x00, 0x0f, 0x01, 0x44, 0x00, 0xaa, ++ 0x17, 0x00, 0x10, 0xf1, 0x07, 0x10, 0x20, 0x00, ++ 0x06, 0x0f, 0x0f, 0x33, 0x0e, 0x1c, 0x2a, 0x38, ++ 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, ++ 0x7d, 0x7e, 0x01, 0xc2, 0x22, 0x00, 0x2a, 0x40, ++ 0x2a, 0xbe, 0x3a, 0xfc, 0x3a, 0xfa, 0x3a, 0xf8, ++ 0x3b, 0x38, 0x3b, 0x78, 0x3b, 0x76, 0x4b, 0xb6, ++ 0x4b, 0xb6, 0x4b, 0xf4, 0x63, 0xf4, 0x84, 0x74, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++ }, ++ }, ++}; ++ ++static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ case MEDIA_BUS_FMT_RGB101010_1X30: ++ case MEDIA_BUS_FMT_RGB121212_1X36: ++ case MEDIA_BUS_FMT_RGB161616_1X48: ++ return true; ++ ++ default: ++ return false; ++ } ++} ++ ++static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ case MEDIA_BUS_FMT_YUV12_1X36: ++ case MEDIA_BUS_FMT_YUV16_1X48: ++ return true; ++ ++ default: ++ return false; ++ } ++} ++#endif ++ ++static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_UYVY8_1X16: ++ case MEDIA_BUS_FMT_UYVY10_1X20: ++ case MEDIA_BUS_FMT_UYVY12_1X24: ++ return true; ++ ++ default: ++ return false; ++ } ++} ++ ++static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ case MEDIA_BUS_FMT_UYYVYY12_0_5X36: ++ case MEDIA_BUS_FMT_UYYVYY16_0_5X48: ++ return true; ++ ++ default: ++ return false; ++ } ++} ++ ++static int hdmi_bus_fmt_color_depth(unsigned int bus_format) ++{ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ case MEDIA_BUS_FMT_UYVY8_1X16: ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ return 8; ++ ++ case MEDIA_BUS_FMT_RGB101010_1X30: ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ case MEDIA_BUS_FMT_UYVY10_1X20: ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ return 10; ++ ++ case MEDIA_BUS_FMT_RGB121212_1X36: ++ case MEDIA_BUS_FMT_YUV12_1X36: ++ case MEDIA_BUS_FMT_UYVY12_1X24: ++ case MEDIA_BUS_FMT_UYYVYY12_0_5X36: ++ return 12; ++ ++ case MEDIA_BUS_FMT_RGB161616_1X48: ++ case MEDIA_BUS_FMT_YUV16_1X48: ++ case MEDIA_BUS_FMT_UYYVYY16_0_5X48: ++ return 16; ++ ++ default: ++ return 0; ++ } ++} ++ ++static unsigned int ++hdmi_get_tmdsclock(struct rockchip_hdmi *hdmi, unsigned long pixelclock) ++{ ++ unsigned int tmdsclock = pixelclock; ++ unsigned int depth = ++ hdmi_bus_fmt_color_depth(hdmi->output_bus_format); ++ ++ if (!hdmi_bus_fmt_is_yuv422(hdmi->output_bus_format)) { ++ switch (depth) { ++ case 16: ++ tmdsclock = pixelclock * 2; ++ break; ++ case 12: ++ tmdsclock = pixelclock * 3 / 2; ++ break; ++ case 10: ++ tmdsclock = pixelclock * 5 / 4; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return tmdsclock; ++} ++ ++static int rockchip_hdmi_match_by_id(struct device *dev, const void *data) ++{ ++ struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); ++ const unsigned int *id = data; ++ ++ return hdmi->id == *id; ++} ++ ++static struct rockchip_hdmi * ++rockchip_hdmi_find_by_id(struct device_driver *drv, unsigned int id) ++{ ++ struct device *dev; ++ ++ dev = driver_find_device(drv, NULL, &id, rockchip_hdmi_match_by_id); ++ if (!dev) ++ return NULL; ++ ++ return dev_get_drvdata(dev); ++} ++ ++static void hdmi_select_link_config(struct rockchip_hdmi *hdmi, ++ struct drm_crtc_state *crtc_state, ++ unsigned int tmdsclk) ++{ ++ struct drm_display_mode mode; ++ int max_lanes, max_rate_per_lane; ++ // int max_dsc_lanes, max_dsc_rate_per_lane; ++ unsigned long max_frl_rate; ++ ++ drm_mode_copy(&mode, &crtc_state->mode); ++ ++ max_lanes = hdmi->max_lanes; ++ max_rate_per_lane = hdmi->max_frl_rate_per_lane; ++ max_frl_rate = max_lanes * max_rate_per_lane * 1000000; ++ ++ hdmi->link_cfg.dsc_mode = false; ++ hdmi->link_cfg.frl_lanes = max_lanes; ++ hdmi->link_cfg.rate_per_lane = max_rate_per_lane; ++ ++ if (!max_frl_rate || (tmdsclk < HDMI20_MAX_RATE && mode.clock < HDMI20_MAX_RATE)) { ++ hdmi->link_cfg.frl_mode = false; ++ return; ++ } ++ ++ hdmi->link_cfg.frl_mode = true; ++ dev_warn(hdmi->dev, "use unsupported frl hdmi mode\n"); ++ ++ // if (!hdmi->dsc_cap.v_1p2) ++ // return; ++ // ++ // max_dsc_lanes = hdmi->dsc_cap.max_lanes; ++ // max_dsc_rate_per_lane = ++ // hdmi->dsc_cap.max_frl_rate_per_lane; ++ // ++ // if (mode.clock >= HDMI_8K60_RATE && ++ // !hdmi_bus_fmt_is_yuv420(hdmi->bus_format) && ++ // !hdmi_bus_fmt_is_yuv422(hdmi->bus_format)) { ++ // hdmi->link_cfg.dsc_mode = true; ++ // hdmi->link_cfg.frl_lanes = max_dsc_lanes; ++ // hdmi->link_cfg.rate_per_lane = max_dsc_rate_per_lane; ++ // } else { ++ // hdmi->link_cfg.dsc_mode = false; ++ // hdmi->link_cfg.frl_lanes = max_lanes; ++ // hdmi->link_cfg.rate_per_lane = max_rate_per_lane; ++ // } ++} ++ ++///////////////////////////////////////////////////////////////////////////////////// ++/* CC: disable DSC */ ++#if 0 ++static int hdmi_dsc_get_slice_height(int vactive) ++{ ++ int slice_height; ++ ++ /* ++ * Slice Height determination : HDMI2.1 Section 7.7.5.2 ++ * Select smallest slice height >=96, that results in a valid PPS and ++ * requires minimum padding lines required for final slice. ++ * ++ * Assumption : Vactive is even. ++ */ ++ for (slice_height = 96; slice_height <= vactive; slice_height += 2) ++ if (vactive % slice_height == 0) ++ return slice_height; ++ ++ return 0; ++} ++ ++static int hdmi_dsc_get_num_slices(struct rockchip_hdmi *hdmi, ++ struct drm_crtc_state *crtc_state, ++ int src_max_slices, int src_max_slice_width, ++ int hdmi_max_slices, int hdmi_throughput) ++{ ++/* Pixel rates in KPixels/sec */ ++#define HDMI_DSC_PEAK_PIXEL_RATE 2720000 ++/* ++ * Rates at which the source and sink are required to process pixels in each ++ * slice, can be two levels: either at least 340000KHz or at least 40000KHz. ++ */ ++#define HDMI_DSC_MAX_ENC_THROUGHPUT_0 340000 ++#define HDMI_DSC_MAX_ENC_THROUGHPUT_1 400000 ++ ++/* Spec limits the slice width to 2720 pixels */ ++#define MAX_HDMI_SLICE_WIDTH 2720 ++ int kslice_adjust; ++ int adjusted_clk_khz; ++ int min_slices; ++ int target_slices; ++ int max_throughput; /* max clock freq. in khz per slice */ ++ int max_slice_width; ++ int slice_width; ++ int pixel_clock = crtc_state->mode.clock; ++ ++ if (!hdmi_throughput) ++ return 0; ++ ++ /* ++ * Slice Width determination : HDMI2.1 Section 7.7.5.1 ++ * kslice_adjust factor for 4:2:0, and 4:2:2 formats is 0.5, where as ++ * for 4:4:4 is 1.0. Multiplying these factors by 10 and later ++ * dividing adjusted clock value by 10. ++ */ ++ if (hdmi_bus_fmt_is_yuv444(hdmi->output_bus_format) || ++ hdmi_bus_fmt_is_rgb(hdmi->output_bus_format)) ++ kslice_adjust = 10; ++ else ++ kslice_adjust = 5; ++ ++ /* ++ * As per spec, the rate at which the source and the sink process ++ * the pixels per slice are at two levels: at least 340Mhz or 400Mhz. ++ * This depends upon the pixel clock rate and output formats ++ * (kslice adjust). ++ * If pixel clock * kslice adjust >= 2720MHz slices can be processed ++ * at max 340MHz, otherwise they can be processed at max 400MHz. ++ */ ++ ++ adjusted_clk_khz = DIV_ROUND_UP(kslice_adjust * pixel_clock, 10); ++ ++ if (adjusted_clk_khz <= HDMI_DSC_PEAK_PIXEL_RATE) ++ max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_0; ++ else ++ max_throughput = HDMI_DSC_MAX_ENC_THROUGHPUT_1; ++ ++ /* ++ * Taking into account the sink's capability for maximum ++ * clock per slice (in MHz) as read from HF-VSDB. ++ */ ++ max_throughput = min(max_throughput, hdmi_throughput * 1000); ++ ++ min_slices = DIV_ROUND_UP(adjusted_clk_khz, max_throughput); ++ max_slice_width = min(MAX_HDMI_SLICE_WIDTH, src_max_slice_width); ++ ++ /* ++ * Keep on increasing the num of slices/line, starting from min_slices ++ * per line till we get such a number, for which the slice_width is ++ * just less than max_slice_width. The slices/line selected should be ++ * less than or equal to the max horizontal slices that the combination ++ * of PCON encoder and HDMI decoder can support. ++ */ ++ do { ++ if (min_slices <= 1 && src_max_slices >= 1 && hdmi_max_slices >= 1) ++ target_slices = 1; ++ else if (min_slices <= 2 && src_max_slices >= 2 && hdmi_max_slices >= 2) ++ target_slices = 2; ++ else if (min_slices <= 4 && src_max_slices >= 4 && hdmi_max_slices >= 4) ++ target_slices = 4; ++ else if (min_slices <= 8 && src_max_slices >= 8 && hdmi_max_slices >= 8) ++ target_slices = 8; ++ else if (min_slices <= 12 && src_max_slices >= 12 && hdmi_max_slices >= 12) ++ target_slices = 12; ++ else if (min_slices <= 16 && src_max_slices >= 16 && hdmi_max_slices >= 16) ++ target_slices = 16; ++ else ++ return 0; ++ ++ slice_width = DIV_ROUND_UP(crtc_state->mode.hdisplay, target_slices); ++ if (slice_width > max_slice_width) ++ min_slices = target_slices + 1; ++ } while (slice_width > max_slice_width); ++ ++ return target_slices; ++} ++ ++static int hdmi_dsc_slices(struct rockchip_hdmi *hdmi, ++ struct drm_crtc_state *crtc_state) ++{ ++ int hdmi_throughput = hdmi->dsc_cap.clk_per_slice; ++ int hdmi_max_slices = hdmi->dsc_cap.max_slices; ++ int rk_max_slices = 8; ++ int rk_max_slice_width = 2048; ++ ++ return hdmi_dsc_get_num_slices(hdmi, crtc_state, rk_max_slices, ++ rk_max_slice_width, ++ hdmi_max_slices, hdmi_throughput); ++} ++ ++static int ++hdmi_dsc_get_bpp(struct rockchip_hdmi *hdmi, int src_fractional_bpp, ++ int slice_width, int num_slices, bool hdmi_all_bpp, ++ int hdmi_max_chunk_bytes) ++{ ++ int max_dsc_bpp, min_dsc_bpp; ++ int target_bytes; ++ bool bpp_found = false; ++ int bpp_decrement_x16; ++ int bpp_target; ++ int bpp_target_x16; ++ ++ /* ++ * Get min bpp and max bpp as per Table 7.23, in HDMI2.1 spec ++ * Start with the max bpp and keep on decrementing with ++ * fractional bpp, if supported by PCON DSC encoder ++ * ++ * for each bpp we check if no of bytes can be supported by HDMI sink ++ */ ++ ++ /* only 9\10\12 bpp was tested */ ++ min_dsc_bpp = 9; ++ max_dsc_bpp = 12; ++ ++ /* ++ * Taking into account if all dsc_all_bpp supported by HDMI2.1 sink ++ * Section 7.7.34 : Source shall not enable compressed Video ++ * Transport with bpp_target settings above 12 bpp unless ++ * DSC_all_bpp is set to 1. ++ */ ++ if (!hdmi_all_bpp) ++ max_dsc_bpp = min(max_dsc_bpp, 12); ++ ++ /* ++ * The Sink has a limit of compressed data in bytes for a scanline, ++ * as described in max_chunk_bytes field in HFVSDB block of edid. ++ * The no. of bytes depend on the target bits per pixel that the ++ * source configures. So we start with the max_bpp and calculate ++ * the target_chunk_bytes. We keep on decrementing the target_bpp, ++ * till we get the target_chunk_bytes just less than what the sink's ++ * max_chunk_bytes, or else till we reach the min_dsc_bpp. ++ * ++ * The decrement is according to the fractional support from PCON DSC ++ * encoder. For fractional BPP we use bpp_target as a multiple of 16. ++ * ++ * bpp_target_x16 = bpp_target * 16 ++ * So we need to decrement by {1, 2, 4, 8, 16} for fractional bpps ++ * {1/16, 1/8, 1/4, 1/2, 1} respectively. ++ */ ++ ++ bpp_target = max_dsc_bpp; ++ ++ /* src does not support fractional bpp implies decrement by 16 for bppx16 */ ++ if (!src_fractional_bpp) ++ src_fractional_bpp = 1; ++ bpp_decrement_x16 = DIV_ROUND_UP(16, src_fractional_bpp); ++ bpp_target_x16 = bpp_target * 16; ++ ++ while (bpp_target_x16 > (min_dsc_bpp * 16)) { ++ int bpp; ++ ++ bpp = DIV_ROUND_UP(bpp_target_x16, 16); ++ target_bytes = DIV_ROUND_UP((num_slices * slice_width * bpp), 8); ++ if (target_bytes <= hdmi_max_chunk_bytes) { ++ bpp_found = true; ++ break; ++ } ++ bpp_target_x16 -= bpp_decrement_x16; ++ } ++ if (bpp_found) ++ return bpp_target_x16; ++ ++ return 0; ++} ++ ++static int ++dw_hdmi_dsc_bpp(struct rockchip_hdmi *hdmi, ++ int num_slices, int slice_width) ++{ ++ bool hdmi_all_bpp = hdmi->dsc_cap.all_bpp; ++ int fractional_bpp = 0; ++ int hdmi_max_chunk_bytes = hdmi->dsc_cap.total_chunk_kbytes * 1024; ++ ++ return hdmi_dsc_get_bpp(hdmi, fractional_bpp, slice_width, ++ num_slices, hdmi_all_bpp, ++ hdmi_max_chunk_bytes); ++} ++ ++static int dw_hdmi_qp_set_link_cfg(struct rockchip_hdmi *hdmi, ++ u16 pic_width, u16 pic_height, ++ u16 slice_width, u16 slice_height, ++ u16 bits_per_pixel, u8 bits_per_component) ++{ ++ int i; ++ ++ for (i = 0; i < PPS_TABLE_LEN; i++) ++ if (pic_width == pps_datas[i].pic_width && ++ pic_height == pps_datas[i].pic_height && ++ slice_width == pps_datas[i].slice_width && ++ slice_height == pps_datas[i].slice_height && ++ bits_per_component == pps_datas[i].bpc && ++ bits_per_pixel == pps_datas[i].bpp && ++ hdmi_bus_fmt_is_rgb(hdmi->output_bus_format) == pps_datas[i].convert_rgb) ++ break; ++ ++ if (i == PPS_TABLE_LEN) { ++ dev_err(hdmi->dev, "can't find pps cfg!\n"); ++ return -EINVAL; ++ } ++ ++ memcpy(hdmi->link_cfg.pps_payload, pps_datas[i].raw_pps, 128); ++ hdmi->link_cfg.hcactive = DIV_ROUND_UP(slice_width * (bits_per_pixel / 16), 8) * ++ (pic_width / slice_width); ++ ++ return 0; ++} ++ ++static void dw_hdmi_qp_dsc_configure(struct rockchip_hdmi *hdmi, ++ struct rockchip_crtc_state *s, ++ struct drm_crtc_state *crtc_state) ++{ ++ int ret; ++ int slice_height; ++ int slice_width; ++ int bits_per_pixel; ++ int slice_count; ++ bool hdmi_is_dsc_1_2; ++ unsigned int depth = hdmi_bus_fmt_color_depth(hdmi->output_bus_format); ++ ++ if (!crtc_state) ++ return; ++ ++ hdmi_is_dsc_1_2 = hdmi->dsc_cap.v_1p2; ++ ++ if (!hdmi_is_dsc_1_2) ++ return; ++ ++ slice_height = hdmi_dsc_get_slice_height(crtc_state->mode.vdisplay); ++ if (!slice_height) ++ return; ++ ++ slice_count = hdmi_dsc_slices(hdmi, crtc_state); ++ if (!slice_count) ++ return; ++ ++ slice_width = DIV_ROUND_UP(crtc_state->mode.hdisplay, slice_count); ++ ++ bits_per_pixel = dw_hdmi_dsc_bpp(hdmi, slice_count, slice_width); ++ if (!bits_per_pixel) ++ return; ++ ++ ret = dw_hdmi_qp_set_link_cfg(hdmi, crtc_state->mode.hdisplay, ++ crtc_state->mode.vdisplay, slice_width, ++ slice_height, bits_per_pixel, depth); ++ ++ if (ret) { ++ dev_err(hdmi->dev, "set vdsc cfg failed\n"); ++ return; ++ } ++ dev_info(hdmi->dev, "dsc_enable\n"); ++ s->dsc_enable = 1; ++ s->dsc_sink_cap.version_major = 1; ++ s->dsc_sink_cap.version_minor = 2; ++ s->dsc_sink_cap.slice_width = slice_width; ++ s->dsc_sink_cap.slice_height = slice_height; ++ s->dsc_sink_cap.target_bits_per_pixel_x16 = bits_per_pixel; ++ s->dsc_sink_cap.block_pred = 1; ++ s->dsc_sink_cap.native_420 = 0; ++ ++ memcpy(&s->pps, hdmi->link_cfg.pps_payload, 128); ++} ++#endif ++///////////////////////////////////////////////////////////////////////////////////////// ++ ++// static int rockchip_hdmi_update_phy_table(struct rockchip_hdmi *hdmi, ++// u32 *config, ++// int phy_table_size) ++// { ++// int i; ++// ++// if (phy_table_size > ARRAY_SIZE(rockchip_phy_config)) { ++// dev_err(hdmi->dev, "phy table array number is out of range\n"); ++// return -E2BIG; ++// } ++// ++// for (i = 0; i < phy_table_size; i++) { ++// if (config[i * 4] != 0) ++// rockchip_phy_config[i].mpixelclock = (u64)config[i * 4]; ++// else ++// rockchip_phy_config[i].mpixelclock = ~0UL; ++// rockchip_phy_config[i].sym_ctr = (u16)config[i * 4 + 1]; ++// rockchip_phy_config[i].term = (u16)config[i * 4 + 2]; ++// rockchip_phy_config[i].vlev_ctr = (u16)config[i * 4 + 3]; ++// } ++// ++// return 0; ++// } ++ ++static void repo_hpd_event(struct work_struct *p_work) ++{ ++ struct rockchip_hdmi *hdmi = container_of(p_work, struct rockchip_hdmi, work.work); ++ bool change; ++ ++ change = drm_helper_hpd_irq_event(hdmi->drm_dev); ++ if (change) { ++ dev_dbg(hdmi->dev, "hpd stat changed:%d\n", hdmi->hpd_stat); ++ // dw_hdmi_qp_cec_set_hpd(hdmi->hdmi_qp, hdmi->hpd_stat, change); ++ } ++} ++ ++static irqreturn_t rockchip_hdmi_hardirq(int irq, void *dev_id) ++{ ++ struct rockchip_hdmi *hdmi = dev_id; ++ u32 intr_stat, val; ++ ++ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat); ++ ++ if (intr_stat) { ++ dev_dbg(hdmi->dev, "hpd irq %#x\n", intr_stat); ++ ++ if (!hdmi->id) ++ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, ++ RK3588_HDMI0_HPD_INT_MSK); ++ else ++ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK, ++ RK3588_HDMI1_HPD_INT_MSK); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); ++ return IRQ_WAKE_THREAD; ++ } ++ ++ return IRQ_NONE; ++} ++ ++static irqreturn_t rockchip_hdmi_irq(int irq, void *dev_id) ++{ ++ struct rockchip_hdmi *hdmi = dev_id; ++ u32 intr_stat, val; ++ int msecs; ++ bool stat; ++ ++ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat); ++ ++ if (!intr_stat) ++ return IRQ_NONE; ++ ++ if (!hdmi->id) { ++ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR, ++ RK3588_HDMI0_HPD_INT_CLR); ++ if (intr_stat & RK3588_HDMI0_LEVEL_INT) ++ stat = true; ++ else ++ stat = false; ++ } else { ++ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR, ++ RK3588_HDMI1_HPD_INT_CLR); ++ if (intr_stat & RK3588_HDMI1_LEVEL_INT) ++ stat = true; ++ else ++ stat = false; ++ } ++ ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); ++ ++ if (stat) { ++ hdmi->hpd_stat = true; ++ msecs = 150; ++ } else { ++ hdmi->hpd_stat = false; ++ msecs = 20; ++ } ++ mod_delayed_work(hdmi->workqueue, &hdmi->work, msecs_to_jiffies(msecs)); ++ ++ if (!hdmi->id) { ++ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR, ++ RK3588_HDMI0_HPD_INT_CLR) | ++ HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK); ++ } else { ++ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR, ++ RK3588_HDMI1_HPD_INT_CLR) | ++ HIWORD_UPDATE(0, RK3588_HDMI1_HPD_INT_MSK); ++ } ++ ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); ++ ++ return IRQ_HANDLED; ++} ++ + static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) + { + struct device_node *np = hdmi->dev->of_node; ++ int ret; + + hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); + if (IS_ERR(hdmi->regmap)) { +@@ -216,6 +1192,14 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) + return PTR_ERR(hdmi->regmap); + } + ++ if (hdmi->is_hdmi_qp) { ++ hdmi->vo1_regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,vo1_grf"); ++ if (IS_ERR(hdmi->vo1_regmap)) { ++ DRM_DEV_ERROR(hdmi->dev, "Unable to get rockchip,vo1_grf\n"); ++ return PTR_ERR(hdmi->vo1_regmap); ++ } ++ } ++ + hdmi->ref_clk = devm_clk_get_optional(hdmi->dev, "ref"); + if (!hdmi->ref_clk) + hdmi->ref_clk = devm_clk_get_optional(hdmi->dev, "vpll"); +@@ -245,6 +1229,79 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) + if (IS_ERR(hdmi->avdd_1v8)) + return PTR_ERR(hdmi->avdd_1v8); + ++ hdmi->hclk_vio = devm_clk_get(hdmi->dev, "hclk_vio"); ++ if (PTR_ERR(hdmi->hclk_vio) == -ENOENT) { ++ hdmi->hclk_vio = NULL; ++ } else if (PTR_ERR(hdmi->hclk_vio) == -EPROBE_DEFER) { ++ return -EPROBE_DEFER; ++ } else if (IS_ERR(hdmi->hclk_vio)) { ++ dev_err(hdmi->dev, "failed to get hclk_vio clock\n"); ++ return PTR_ERR(hdmi->hclk_vio); ++ } ++ ++ hdmi->hclk_vop = devm_clk_get(hdmi->dev, "hclk"); ++ if (PTR_ERR(hdmi->hclk_vop) == -ENOENT) { ++ hdmi->hclk_vop = NULL; ++ } else if (PTR_ERR(hdmi->hclk_vop) == -EPROBE_DEFER) { ++ return -EPROBE_DEFER; ++ } else if (IS_ERR(hdmi->hclk_vop)) { ++ dev_err(hdmi->dev, "failed to get hclk_vop clock\n"); ++ return PTR_ERR(hdmi->hclk_vop); ++ } ++ ++ hdmi->aud_clk = devm_clk_get_optional(hdmi->dev, "aud"); ++ if (IS_ERR(hdmi->aud_clk)) { ++ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->aud_clk), ++ "failed to get aud_clk clock\n"); ++ return PTR_ERR(hdmi->aud_clk); ++ } ++ ++ hdmi->hpd_clk = devm_clk_get_optional(hdmi->dev, "hpd"); ++ if (IS_ERR(hdmi->hpd_clk)) { ++ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hpd_clk), ++ "failed to get hpd_clk clock\n"); ++ return PTR_ERR(hdmi->hpd_clk); ++ } ++ ++ hdmi->hclk_vo1 = devm_clk_get_optional(hdmi->dev, "hclk_vo1"); ++ if (IS_ERR(hdmi->hclk_vo1)) { ++ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hclk_vo1), ++ "failed to get hclk_vo1 clock\n"); ++ return PTR_ERR(hdmi->hclk_vo1); ++ } ++ ++ hdmi->earc_clk = devm_clk_get_optional(hdmi->dev, "earc"); ++ if (IS_ERR(hdmi->earc_clk)) { ++ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->earc_clk), ++ "failed to get earc_clk clock\n"); ++ return PTR_ERR(hdmi->earc_clk); ++ } ++ ++ hdmi->hdmitx_ref = devm_clk_get_optional(hdmi->dev, "hdmitx_ref"); ++ if (IS_ERR(hdmi->hdmitx_ref)) { ++ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hdmitx_ref), ++ "failed to get hdmitx_ref clock\n"); ++ return PTR_ERR(hdmi->hdmitx_ref); ++ } ++ ++ hdmi->pclk = devm_clk_get_optional(hdmi->dev, "pclk"); ++ if (IS_ERR(hdmi->pclk)) { ++ dev_err_probe(hdmi->dev, PTR_ERR(hdmi->pclk), ++ "failed to get pclk clock\n"); ++ return PTR_ERR(hdmi->pclk); ++ } ++ ++ hdmi->enable_gpio = devm_gpiod_get_optional(hdmi->dev, "enable", ++ GPIOD_OUT_HIGH); ++ if (IS_ERR(hdmi->enable_gpio)) { ++ ret = PTR_ERR(hdmi->enable_gpio); ++ dev_err(hdmi->dev, "failed to request enable GPIO: %d\n", ret); ++ return ret; ++ } ++ ++ hdmi->skip_check_420_mode = ++ of_property_read_bool(np, "skip-check-420-mode"); ++ + return 0; + } + +@@ -283,9 +1340,114 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data, + + return MODE_BAD; + } ++/* [CC:] enable downstream mode_valid() */ ++// static enum drm_mode_status ++// dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, void *data, ++// const struct drm_display_info *info, ++// const struct drm_display_mode *mode) ++// { ++// struct drm_encoder *encoder = connector->encoder; ++// enum drm_mode_status status = MODE_OK; ++// struct drm_device *dev = connector->dev; ++// struct rockchip_drm_private *priv = dev->dev_private; ++// struct drm_crtc *crtc; ++// struct rockchip_hdmi *hdmi; ++// ++// /* ++// * Pixel clocks we support are always < 2GHz and so fit in an ++// * int. We should make sure source rate does too so we don't get ++// * overflow when we multiply by 1000. ++// */ ++// if (mode->clock > INT_MAX / 1000) ++// return MODE_BAD; ++// ++// if (!encoder) { ++// const struct drm_connector_helper_funcs *funcs; ++// ++// funcs = connector->helper_private; ++// if (funcs->atomic_best_encoder) ++// encoder = funcs->atomic_best_encoder(connector, ++// connector->state); ++// else ++// encoder = funcs->best_encoder(connector); ++// } ++// ++// if (!encoder || !encoder->possible_crtcs) ++// return MODE_BAD; ++// ++// hdmi = to_rockchip_hdmi(encoder); ++// ++// /* ++// * If sink max TMDS clock < 340MHz, we should check the mode pixel ++// * clock > 340MHz is YCbCr420 or not and whether the platform supports ++// * YCbCr420. ++// */ ++// if (!hdmi->skip_check_420_mode) { ++// if (mode->clock > 340000 && ++// connector->display_info.max_tmds_clock < 340000 && ++// (!drm_mode_is_420(&connector->display_info, mode) || ++// !connector->ycbcr_420_allowed)) ++// return MODE_BAD; ++// ++// if (hdmi->max_tmdsclk <= 340000 && mode->clock > 340000 && ++// !drm_mode_is_420(&connector->display_info, mode)) ++// return MODE_BAD; ++// }; ++// ++// if (hdmi->phy) { ++// if (hdmi->is_hdmi_qp) ++// phy_set_bus_width(hdmi->phy, mode->clock * 10); ++// else ++// phy_set_bus_width(hdmi->phy, 8); ++// } ++// ++// /* ++// * ensure all drm display mode can work, if someone want support more ++// * resolutions, please limit the possible_crtc, only connect to ++// * needed crtc. ++// */ ++// drm_for_each_crtc(crtc, connector->dev) { ++// int pipe = drm_crtc_index(crtc); ++// const struct rockchip_crtc_funcs *funcs = ++// priv->crtc_funcs[pipe]; ++// ++// if (!(encoder->possible_crtcs & drm_crtc_mask(crtc))) ++// continue; ++// if (!funcs || !funcs->mode_valid) ++// continue; ++// ++// status = funcs->mode_valid(crtc, mode, ++// DRM_MODE_CONNECTOR_HDMIA); ++// if (status != MODE_OK) ++// return status; ++// } ++// ++// return status; ++// } ++// + + static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) + { ++ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); ++ // struct drm_crtc *crtc = encoder->crtc; ++ // struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); ++ // ++ // if (crtc->state->active_changed) { ++ // if (hdmi->plat_data->split_mode) { ++ // s->output_if &= ~(VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1); ++ // } else { ++ // if (!hdmi->id) ++ // s->output_if &= ~VOP_OUTPUT_IF_HDMI1; ++ // else ++ // s->output_if &= ~VOP_OUTPUT_IF_HDMI0; ++ // } ++ // } ++ /* ++ * when plug out hdmi it will be switch cvbs and then phy bus width ++ * must be set as 8 ++ */ ++ if (hdmi->phy) ++ phy_set_bus_width(hdmi->phy, 8); + } + + static bool +@@ -301,6 +1463,27 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *adj_mode) + { + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); ++ struct drm_crtc *crtc; ++ struct rockchip_crtc_state *s; ++ ++ if (!encoder->crtc) ++ return; ++ crtc = encoder->crtc; ++ ++ if (!crtc->state) ++ return; ++ s = to_rockchip_crtc_state(crtc->state); ++ ++ if (!s) ++ return; ++ ++ if (hdmi->is_hdmi_qp) { ++ // s->dsc_enable = 0; ++ // if (hdmi->link_cfg.dsc_mode) ++ // dw_hdmi_qp_dsc_configure(hdmi, s, crtc->state); ++ ++ phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width); ++ } + + clk_set_rate(hdmi->ref_clk, adj_mode->clock * 1000); + } +@@ -308,14 +1491,25 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, + static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) + { + struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); ++ struct drm_crtc *crtc = encoder->crtc; + u32 val; ++ int mux; + int ret; + ++ if (WARN_ON(!crtc || !crtc->state)) ++ return; ++ ++ if (hdmi->phy) ++ phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width); ++ ++ clk_set_rate(hdmi->ref_clk, ++ crtc->state->adjusted_mode.crtc_clock * 1000); ++ + if (hdmi->chip_data->lcdsel_grf_reg < 0) + return; + +- ret = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); +- if (ret) ++ mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); ++ if (mux) + val = hdmi->chip_data->lcdsel_lit; + else + val = hdmi->chip_data->lcdsel_big; +@@ -330,24 +1524,992 @@ static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) + if (ret != 0) + DRM_DEV_ERROR(hdmi->dev, "Could not write to GRF: %d\n", ret); + ++ if (hdmi->chip_data->lcdsel_grf_reg == RK3288_GRF_SOC_CON6) { ++ struct rockchip_crtc_state *s = ++ to_rockchip_crtc_state(crtc->state); ++ u32 mode_mask = mux ? RK3288_HDMI_LCDC1_YUV420 : ++ RK3288_HDMI_LCDC0_YUV420; ++ ++ if (s->output_mode == ROCKCHIP_OUT_MODE_YUV420) ++ val = HIWORD_UPDATE(mode_mask, mode_mask); ++ else ++ val = HIWORD_UPDATE(0, mode_mask); ++ ++ regmap_write(hdmi->regmap, RK3288_GRF_SOC_CON16, val); ++ } ++ + clk_disable_unprepare(hdmi->grf_clk); + DRM_DEV_DEBUG(hdmi->dev, "vop %s output to hdmi\n", + ret ? "LIT" : "BIG"); + } + +-static int +-dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, +- struct drm_crtc_state *crtc_state, +- struct drm_connector_state *conn_state) ++static void rk3588_set_link_mode(struct rockchip_hdmi *hdmi) + { +- struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); ++ int val; ++ bool is_hdmi0; + +- s->output_mode = ROCKCHIP_OUT_MODE_AAAA; +- s->output_type = DRM_MODE_CONNECTOR_HDMIA; ++ if (!hdmi->id) ++ is_hdmi0 = true; ++ else ++ is_hdmi0 = false; ++ ++ if (!hdmi->link_cfg.frl_mode) { ++ val = HIWORD_UPDATE(0, RK3588_HDMI21_MASK); ++ if (is_hdmi0) ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON4, val); ++ else ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON7, val); ++ ++ val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK); ++ if (is_hdmi0) ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); ++ else ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); ++ ++ return; ++ } ++ ++ val = HIWORD_UPDATE(RK3588_HDMI21_MASK, RK3588_HDMI21_MASK); ++ if (is_hdmi0) ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON4, val); ++ else ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON7, val); ++ ++ if (hdmi->link_cfg.dsc_mode) { ++ val = HIWORD_UPDATE(RK3588_COMPRESS_MODE_MASK | RK3588_COMPRESSED_DATA, ++ RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK); ++ if (is_hdmi0) ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); ++ else ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); ++ } else { ++ val = HIWORD_UPDATE(0, RK3588_COMPRESS_MODE_MASK | RK3588_COLOR_FORMAT_MASK); ++ if (is_hdmi0) ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); ++ else ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); ++ } ++} ++ ++static void rk3588_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format, ++ u32 depth) ++{ ++ u32 val = 0; ++ ++ switch (bus_format) { ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ case MEDIA_BUS_FMT_RGB101010_1X30: ++ val = HIWORD_UPDATE(0, RK3588_COLOR_FORMAT_MASK); ++ break; ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ val = HIWORD_UPDATE(RK3588_YUV420, RK3588_COLOR_FORMAT_MASK); ++ break; ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ val = HIWORD_UPDATE(RK3588_YUV444, RK3588_COLOR_FORMAT_MASK); ++ break; ++ default: ++ dev_err(hdmi->dev, "can't set correct color format\n"); ++ return; ++ } ++ ++ if (hdmi->link_cfg.dsc_mode) ++ val = HIWORD_UPDATE(RK3588_COMPRESSED_DATA, RK3588_COLOR_FORMAT_MASK); ++ ++ if (depth == 8) ++ val |= HIWORD_UPDATE(RK3588_8BPC, RK3588_COLOR_DEPTH_MASK); ++ else ++ val |= HIWORD_UPDATE(RK3588_10BPC, RK3588_COLOR_DEPTH_MASK); ++ ++ if (!hdmi->id) ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); ++ else ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); ++} ++ ++static void rk3588_set_grf_cfg(void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ int color_depth; ++ ++ rk3588_set_link_mode(hdmi); ++ color_depth = hdmi_bus_fmt_color_depth(hdmi->bus_format); ++ rk3588_set_color_format(hdmi, hdmi->bus_format, color_depth); ++} ++ ++static void ++dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state, ++ struct drm_crtc_state *crtc_state, ++ struct rockchip_hdmi *hdmi, ++ unsigned int *color_format, ++ unsigned int *output_mode, ++ unsigned long *bus_format, ++ unsigned int *bus_width, ++ unsigned long *enc_out_encoding, ++ unsigned int *eotf) ++{ ++ struct drm_display_info *info = &conn_state->connector->display_info; ++ struct drm_display_mode mode; ++ struct hdr_output_metadata *hdr_metadata; ++ u32 vic; ++ unsigned long tmdsclock, pixclock; ++ unsigned int color_depth; ++ bool support_dc = false; ++ bool sink_is_hdmi = true; ++ u32 max_tmds_clock = info->max_tmds_clock; ++ int output_eotf; ++ ++ drm_mode_copy(&mode, &crtc_state->mode); ++ pixclock = mode.crtc_clock; ++ // if (hdmi->plat_data->split_mode) { ++ // drm_mode_convert_to_origin_mode(&mode); ++ // pixclock /= 2; ++ // } ++ ++ vic = drm_match_cea_mode(&mode); ++ ++ if (!hdmi->is_hdmi_qp) ++ sink_is_hdmi = dw_hdmi_get_output_whether_hdmi(hdmi->hdmi); ++ ++ *color_format = RK_IF_FORMAT_RGB; ++ ++ switch (hdmi->hdmi_output) { ++ case RK_IF_FORMAT_YCBCR_HQ: ++ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) ++ *color_format = RK_IF_FORMAT_YCBCR444; ++ else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) ++ *color_format = RK_IF_FORMAT_YCBCR422; ++ else if (conn_state->connector->ycbcr_420_allowed && ++ drm_mode_is_420(info, &mode) && ++ (pixclock >= 594000 && !hdmi->is_hdmi_qp)) ++ *color_format = RK_IF_FORMAT_YCBCR420; ++ break; ++ case RK_IF_FORMAT_YCBCR_LQ: ++ if (conn_state->connector->ycbcr_420_allowed && ++ drm_mode_is_420(info, &mode) && pixclock >= 594000) ++ *color_format = RK_IF_FORMAT_YCBCR420; ++ else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) ++ *color_format = RK_IF_FORMAT_YCBCR422; ++ else if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) ++ *color_format = RK_IF_FORMAT_YCBCR444; ++ break; ++ case RK_IF_FORMAT_YCBCR420: ++ if (conn_state->connector->ycbcr_420_allowed && ++ drm_mode_is_420(info, &mode) && pixclock >= 594000) ++ *color_format = RK_IF_FORMAT_YCBCR420; ++ break; ++ case RK_IF_FORMAT_YCBCR422: ++ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) ++ *color_format = RK_IF_FORMAT_YCBCR422; ++ break; ++ case RK_IF_FORMAT_YCBCR444: ++ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) ++ *color_format = RK_IF_FORMAT_YCBCR444; ++ break; ++ case RK_IF_FORMAT_RGB: ++ default: ++ break; ++ } ++ ++ if (*color_format == RK_IF_FORMAT_RGB && ++ info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) ++ support_dc = true; ++ if (*color_format == RK_IF_FORMAT_YCBCR444 && ++ info->edid_hdmi_rgb444_dc_modes & ++ (DRM_EDID_HDMI_DC_Y444 | DRM_EDID_HDMI_DC_30)) ++ support_dc = true; ++ if (*color_format == RK_IF_FORMAT_YCBCR422) ++ support_dc = true; ++ if (*color_format == RK_IF_FORMAT_YCBCR420 && ++ info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) ++ support_dc = true; ++ ++ if (hdmi->colordepth > 8 && support_dc) ++ color_depth = 10; ++ else ++ color_depth = 8; ++ ++ if (!sink_is_hdmi) { ++ *color_format = RK_IF_FORMAT_RGB; ++ color_depth = 8; ++ } ++ ++ *eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR; ++ if (conn_state->hdr_output_metadata) { ++ hdr_metadata = (struct hdr_output_metadata *) ++ conn_state->hdr_output_metadata->data; ++ output_eotf = hdr_metadata->hdmi_metadata_type1.eotf; ++ if (output_eotf > HDMI_EOTF_TRADITIONAL_GAMMA_SDR && ++ output_eotf <= HDMI_EOTF_BT_2100_HLG) ++ *eotf = output_eotf; ++ } ++ ++ hdmi->colorimetry = conn_state->colorspace; ++ ++ if ((*eotf > HDMI_EOTF_TRADITIONAL_GAMMA_SDR && ++ conn_state->connector->hdr_sink_metadata.hdmi_type1.eotf & ++ BIT(*eotf)) || ((hdmi->colorimetry >= DRM_MODE_COLORIMETRY_BT2020_CYCC) && ++ (hdmi->colorimetry <= DRM_MODE_COLORIMETRY_BT2020_YCC))) ++ *enc_out_encoding = V4L2_YCBCR_ENC_BT2020; ++ else if ((vic == 6) || (vic == 7) || (vic == 21) || (vic == 22) || ++ (vic == 2) || (vic == 3) || (vic == 17) || (vic == 18)) ++ *enc_out_encoding = V4L2_YCBCR_ENC_601; ++ else ++ *enc_out_encoding = V4L2_YCBCR_ENC_709; ++ ++ if (*enc_out_encoding == V4L2_YCBCR_ENC_BT2020) { ++ /* BT2020 require color depth at lest 10bit */ ++ color_depth = 10; ++ /* We prefer use YCbCr422 to send 10bit */ ++ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) ++ *color_format = RK_IF_FORMAT_YCBCR422; ++ if (hdmi->is_hdmi_qp) { ++ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR420) { ++ if (mode.clock >= 340000) ++ *color_format = RK_IF_FORMAT_YCBCR420; ++ else ++ *color_format = RK_IF_FORMAT_RGB; ++ } else { ++ *color_format = RK_IF_FORMAT_RGB; ++ } ++ } ++ } ++ ++ if (mode.flags & DRM_MODE_FLAG_DBLCLK) ++ pixclock *= 2; ++ if ((mode.flags & DRM_MODE_FLAG_3D_MASK) == ++ DRM_MODE_FLAG_3D_FRAME_PACKING) ++ pixclock *= 2; ++ ++ if (*color_format == RK_IF_FORMAT_YCBCR422 || color_depth == 8) ++ tmdsclock = pixclock; ++ else ++ tmdsclock = pixclock * (color_depth) / 8; ++ ++ if (*color_format == RK_IF_FORMAT_YCBCR420) ++ tmdsclock /= 2; ++ ++ /* XXX: max_tmds_clock of some sink is 0, we think it is 340MHz. */ ++ if (!max_tmds_clock) ++ max_tmds_clock = 340000; ++ ++ max_tmds_clock = min(max_tmds_clock, hdmi->max_tmdsclk); ++ ++ if ((tmdsclock > max_tmds_clock) && !hdmi->is_hdmi_qp) { ++ if (max_tmds_clock >= 594000) { ++ color_depth = 8; ++ } else if (max_tmds_clock > 340000) { ++ if (drm_mode_is_420(info, &mode) || tmdsclock >= 594000) ++ *color_format = RK_IF_FORMAT_YCBCR420; ++ } else { ++ color_depth = 8; ++ if (drm_mode_is_420(info, &mode) || tmdsclock >= 594000) ++ *color_format = RK_IF_FORMAT_YCBCR420; ++ } ++ } ++ ++ if (hdmi->is_hdmi_qp) { ++ if (mode.clock >= 340000) { ++ if (drm_mode_is_420(info, &mode)) ++ *color_format = RK_IF_FORMAT_YCBCR420; ++ else ++ *color_format = RK_IF_FORMAT_RGB; ++ } else if (tmdsclock > max_tmds_clock) { ++ color_depth = 8; ++ if (drm_mode_is_420(info, &mode)) ++ *color_format = RK_IF_FORMAT_YCBCR420; ++ } ++ } ++ ++ if (*color_format == RK_IF_FORMAT_YCBCR420) { ++ *output_mode = ROCKCHIP_OUT_MODE_YUV420; ++ if (color_depth > 8) ++ *bus_format = MEDIA_BUS_FMT_UYYVYY10_0_5X30; ++ else ++ *bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24; ++ *bus_width = color_depth / 2; ++ } else { ++ *output_mode = ROCKCHIP_OUT_MODE_AAAA; ++ if (color_depth > 8) { ++ if (*color_format != RK_IF_FORMAT_RGB && ++ !hdmi->unsupported_yuv_input) ++ *bus_format = MEDIA_BUS_FMT_YUV10_1X30; ++ else ++ *bus_format = MEDIA_BUS_FMT_RGB101010_1X30; ++ } else { ++ if (*color_format != RK_IF_FORMAT_RGB && ++ !hdmi->unsupported_yuv_input) ++ *bus_format = MEDIA_BUS_FMT_YUV8_1X24; ++ else ++ *bus_format = MEDIA_BUS_FMT_RGB888_1X24; ++ } ++ if (*color_format == RK_IF_FORMAT_YCBCR422) ++ *bus_width = 8; ++ else ++ *bus_width = color_depth; ++ } ++ ++ hdmi->bus_format = *bus_format; ++ ++ if (*color_format == RK_IF_FORMAT_YCBCR422) { ++ if (color_depth == 12) ++ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY12_1X24; ++ else if (color_depth == 10) ++ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY10_1X20; ++ else ++ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY8_1X16; ++ } else { ++ hdmi->output_bus_format = *bus_format; ++ } ++} ++ ++static bool ++dw_hdmi_rockchip_check_color(struct drm_connector_state *conn_state, ++ struct rockchip_hdmi *hdmi) ++{ ++ struct drm_crtc_state *crtc_state = conn_state->crtc->state; ++ unsigned int colorformat; ++ unsigned long bus_format; ++ unsigned long output_bus_format = hdmi->output_bus_format; ++ unsigned long enc_out_encoding = hdmi->enc_out_encoding; ++ unsigned int eotf, bus_width; ++ unsigned int output_mode; ++ ++ dw_hdmi_rockchip_select_output(conn_state, crtc_state, hdmi, ++ &colorformat, ++ &output_mode, &bus_format, &bus_width, ++ &hdmi->enc_out_encoding, &eotf); ++ ++ if (output_bus_format != hdmi->output_bus_format || ++ enc_out_encoding != hdmi->enc_out_encoding) ++ return true; ++ else ++ return false; ++} ++ ++static int ++dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, ++ struct drm_crtc_state *crtc_state, ++ struct drm_connector_state *conn_state) ++{ ++ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); ++ struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); ++ unsigned int colorformat, bus_width, tmdsclk; ++ struct drm_display_mode mode; ++ unsigned int output_mode; ++ unsigned long bus_format; ++ int color_depth; ++ bool secondary = false; ++ ++ /* ++ * There are two hdmi but only one encoder in split mode, ++ * so we need to check twice. ++ */ ++secondary: ++ drm_mode_copy(&mode, &crtc_state->mode); ++ ++ hdmi->vp_id = 0; ++ // hdmi->vp_id = s->vp_id; ++ // if (hdmi->plat_data->split_mode) ++ // drm_mode_convert_to_origin_mode(&mode); ++ ++ int eotf; ++ dw_hdmi_rockchip_select_output(conn_state, crtc_state, hdmi, ++ &colorformat, ++ &output_mode, &bus_format, &bus_width, ++ // &hdmi->enc_out_encoding, &s->eotf); ++ &hdmi->enc_out_encoding, &eotf); ++ ++ s->bus_format = bus_format; ++ if (hdmi->is_hdmi_qp) { ++ color_depth = hdmi_bus_fmt_color_depth(bus_format); ++ tmdsclk = hdmi_get_tmdsclock(hdmi, crtc_state->mode.clock); ++ if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format)) ++ tmdsclk /= 2; ++ hdmi_select_link_config(hdmi, crtc_state, tmdsclk); ++ ++ if (hdmi->link_cfg.frl_mode) { ++ gpiod_set_value(hdmi->enable_gpio, 0); ++ /* in the current version, support max 40G frl */ ++ if (hdmi->link_cfg.rate_per_lane >= 10) { ++ hdmi->link_cfg.frl_lanes = 4; ++ hdmi->link_cfg.rate_per_lane = 10; ++ } ++ bus_width = hdmi->link_cfg.frl_lanes * ++ hdmi->link_cfg.rate_per_lane * 1000000; ++ /* 10 bit color depth and frl mode */ ++ if (color_depth == 10) ++ bus_width |= ++ COLOR_DEPTH_10BIT | HDMI_FRL_MODE; ++ else ++ bus_width |= HDMI_FRL_MODE; ++ } else { ++ gpiod_set_value(hdmi->enable_gpio, 1); ++ bus_width = hdmi_get_tmdsclock(hdmi, mode.clock * 10); ++ if (hdmi_bus_fmt_is_yuv420(hdmi->output_bus_format)) ++ bus_width /= 2; ++ ++ if (color_depth == 10) ++ bus_width |= COLOR_DEPTH_10BIT; ++ } ++ } ++ ++ hdmi->phy_bus_width = bus_width; ++ ++ if (hdmi->phy) ++ phy_set_bus_width(hdmi->phy, bus_width); ++ ++ s->output_type = DRM_MODE_CONNECTOR_HDMIA; ++ // s->tv_state = &conn_state->tv; ++ // ++ // if (hdmi->plat_data->split_mode) { ++ // s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE; ++ // if (hdmi->plat_data->right && hdmi->id) ++ // s->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP; ++ // s->output_if |= VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1; ++ // } else { ++ // if (!hdmi->id) ++ // s->output_if |= VOP_OUTPUT_IF_HDMI0; ++ // else ++ // s->output_if |= VOP_OUTPUT_IF_HDMI1; ++ // } ++ ++ s->output_mode = output_mode; ++ hdmi->bus_format = s->bus_format; ++ ++ if (hdmi->enc_out_encoding == V4L2_YCBCR_ENC_BT2020) ++ s->color_space = V4L2_COLORSPACE_BT2020; ++ else if (colorformat == RK_IF_FORMAT_RGB) ++ s->color_space = V4L2_COLORSPACE_DEFAULT; ++ else if (hdmi->enc_out_encoding == V4L2_YCBCR_ENC_709) ++ s->color_space = V4L2_COLORSPACE_REC709; ++ else ++ s->color_space = V4L2_COLORSPACE_SMPTE170M; ++ ++ if (hdmi->plat_data->split_mode && !secondary) { ++ hdmi = rockchip_hdmi_find_by_id(hdmi->dev->driver, !hdmi->id); ++ secondary = true; ++ goto secondary; ++ } + + return 0; + } + ++static unsigned long ++dw_hdmi_rockchip_get_input_bus_format(void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ return hdmi->bus_format; ++} ++ ++static unsigned long ++dw_hdmi_rockchip_get_output_bus_format(void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ return hdmi->output_bus_format; ++} ++ ++static unsigned long ++dw_hdmi_rockchip_get_enc_in_encoding(void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ return hdmi->enc_out_encoding; ++} ++ ++static unsigned long ++dw_hdmi_rockchip_get_enc_out_encoding(void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ return hdmi->enc_out_encoding; ++} ++ ++static unsigned long ++dw_hdmi_rockchip_get_quant_range(void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ return hdmi->hdmi_quant_range; ++} ++ ++static struct drm_property * ++dw_hdmi_rockchip_get_hdr_property(void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ return hdmi->hdr_panel_metadata_property; ++} ++ ++static struct drm_property_blob * ++dw_hdmi_rockchip_get_hdr_blob(void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ return hdmi->hdr_panel_blob_ptr; ++} ++ ++static bool ++dw_hdmi_rockchip_get_color_changed(void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ bool ret = false; ++ ++ if (hdmi->color_changed) ++ ret = true; ++ hdmi->color_changed = 0; ++ ++ return ret; ++} ++ ++#if 0 ++static int ++dw_hdmi_rockchip_get_edid_dsc_info(void *data, struct edid *edid) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ if (!edid) ++ return -EINVAL; ++ ++ return rockchip_drm_parse_cea_ext(&hdmi->dsc_cap, ++ &hdmi->max_frl_rate_per_lane, ++ &hdmi->max_lanes, edid); ++} ++ ++static int ++dw_hdmi_rockchip_get_next_hdr_data(void *data, struct edid *edid, ++ struct drm_connector *connector) ++{ ++ int ret; ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ struct next_hdr_sink_data *sink_data = &hdmi->next_hdr_data; ++ size_t size = sizeof(*sink_data); ++ struct drm_property *property = hdmi->next_hdr_sink_data_property; ++ struct drm_property_blob *blob = hdmi->hdr_panel_blob_ptr; ++ ++ if (!edid) ++ return -EINVAL; ++ ++ rockchip_drm_parse_next_hdr(sink_data, edid); ++ ++ ret = drm_property_replace_global_blob(connector->dev, &blob, size, sink_data, ++ &connector->base, property); ++ ++ return ret; ++}; ++#endif ++ ++static ++struct dw_hdmi_link_config *dw_hdmi_rockchip_get_link_cfg(void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ return &hdmi->link_cfg; ++} ++ ++#if 0 ++static const struct drm_prop_enum_list color_depth_enum_list[] = { ++ { 0, "Automatic" }, /* Prefer highest color depth */ ++ { 8, "24bit" }, ++ { 10, "30bit" }, ++}; ++ ++static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = { ++ { RK_IF_FORMAT_RGB, "rgb" }, ++ { RK_IF_FORMAT_YCBCR444, "ycbcr444" }, ++ { RK_IF_FORMAT_YCBCR422, "ycbcr422" }, ++ { RK_IF_FORMAT_YCBCR420, "ycbcr420" }, ++ { RK_IF_FORMAT_YCBCR_HQ, "ycbcr_high_subsampling" }, ++ { RK_IF_FORMAT_YCBCR_LQ, "ycbcr_low_subsampling" }, ++ { RK_IF_FORMAT_MAX, "invalid_output" }, ++}; ++ ++static const struct drm_prop_enum_list quant_range_enum_list[] = { ++ { HDMI_QUANTIZATION_RANGE_DEFAULT, "default" }, ++ { HDMI_QUANTIZATION_RANGE_LIMITED, "limit" }, ++ { HDMI_QUANTIZATION_RANGE_FULL, "full" }, ++}; ++ ++static const struct drm_prop_enum_list output_hdmi_dvi_enum_list[] = { ++ { 0, "auto" }, ++ { 1, "force_hdmi" }, ++ { 2, "force_dvi" }, ++}; ++ ++static const struct drm_prop_enum_list output_type_cap_list[] = { ++ { 0, "DVI" }, ++ { 1, "HDMI" }, ++}; ++#endif ++ ++static void ++dw_hdmi_rockchip_attach_properties(struct drm_connector *connector, ++ unsigned int color, int version, ++ void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ struct drm_property *prop; ++ // struct rockchip_drm_private *private = connector->dev->dev_private; ++ ++ switch (color) { ++ case MEDIA_BUS_FMT_RGB101010_1X30: ++ hdmi->hdmi_output = RK_IF_FORMAT_RGB; ++ hdmi->colordepth = 10; ++ break; ++ case MEDIA_BUS_FMT_YUV8_1X24: ++ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR444; ++ hdmi->colordepth = 8; ++ break; ++ case MEDIA_BUS_FMT_YUV10_1X30: ++ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR444; ++ hdmi->colordepth = 10; ++ break; ++ case MEDIA_BUS_FMT_UYVY10_1X20: ++ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR422; ++ hdmi->colordepth = 10; ++ break; ++ case MEDIA_BUS_FMT_UYVY8_1X16: ++ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR422; ++ hdmi->colordepth = 8; ++ break; ++ case MEDIA_BUS_FMT_UYYVYY8_0_5X24: ++ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR420; ++ hdmi->colordepth = 8; ++ break; ++ case MEDIA_BUS_FMT_UYYVYY10_0_5X30: ++ hdmi->hdmi_output = RK_IF_FORMAT_YCBCR420; ++ hdmi->colordepth = 10; ++ break; ++ default: ++ hdmi->hdmi_output = RK_IF_FORMAT_RGB; ++ hdmi->colordepth = 8; ++ } ++ ++ hdmi->bus_format = color; ++ ++ if (hdmi->hdmi_output == RK_IF_FORMAT_YCBCR422) { ++ if (hdmi->colordepth == 12) ++ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY12_1X24; ++ else if (hdmi->colordepth == 10) ++ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY10_1X20; ++ else ++ hdmi->output_bus_format = MEDIA_BUS_FMT_UYVY8_1X16; ++ } else { ++ hdmi->output_bus_format = hdmi->bus_format; ++ } ++ ++#if 0 ++ /* RK3368 does not support deep color mode */ ++ if (!hdmi->color_depth_property && !hdmi->unsupported_deep_color) { ++ prop = drm_property_create_enum(connector->dev, 0, ++ RK_IF_PROP_COLOR_DEPTH, ++ color_depth_enum_list, ++ ARRAY_SIZE(color_depth_enum_list)); ++ if (prop) { ++ hdmi->color_depth_property = prop; ++ drm_object_attach_property(&connector->base, prop, 0); ++ } ++ } ++ ++ prop = drm_property_create_enum(connector->dev, 0, RK_IF_PROP_COLOR_FORMAT, ++ drm_hdmi_output_enum_list, ++ ARRAY_SIZE(drm_hdmi_output_enum_list)); ++ if (prop) { ++ hdmi->hdmi_output_property = prop; ++ drm_object_attach_property(&connector->base, prop, 0); ++ } ++ ++ prop = drm_property_create_range(connector->dev, 0, ++ RK_IF_PROP_COLOR_DEPTH_CAPS, ++ 0, 0xff); ++ if (prop) { ++ hdmi->colordepth_capacity = prop; ++ drm_object_attach_property(&connector->base, prop, 0); ++ } ++ ++ prop = drm_property_create_range(connector->dev, 0, ++ RK_IF_PROP_COLOR_FORMAT_CAPS, ++ 0, 0xf); ++ if (prop) { ++ hdmi->outputmode_capacity = prop; ++ drm_object_attach_property(&connector->base, prop, 0); ++ } ++ ++ prop = drm_property_create(connector->dev, ++ DRM_MODE_PROP_BLOB | ++ DRM_MODE_PROP_IMMUTABLE, ++ "HDR_PANEL_METADATA", 0); ++ if (prop) { ++ hdmi->hdr_panel_metadata_property = prop; ++ drm_object_attach_property(&connector->base, prop, 0); ++ } ++ ++ prop = drm_property_create(connector->dev, ++ DRM_MODE_PROP_BLOB | ++ DRM_MODE_PROP_IMMUTABLE, ++ "NEXT_HDR_SINK_DATA", 0); ++ if (prop) { ++ hdmi->next_hdr_sink_data_property = prop; ++ drm_object_attach_property(&connector->base, prop, 0); ++ } ++ ++ prop = drm_property_create_bool(connector->dev, DRM_MODE_PROP_IMMUTABLE, ++ "USER_SPLIT_MODE"); ++ if (prop) { ++ hdmi->user_split_mode_prop = prop; ++ drm_object_attach_property(&connector->base, prop, ++ hdmi->user_split_mode ? 1 : 0); ++ } ++ ++ if (!hdmi->is_hdmi_qp) { ++ prop = drm_property_create_enum(connector->dev, 0, ++ "output_hdmi_dvi", ++ output_hdmi_dvi_enum_list, ++ ARRAY_SIZE(output_hdmi_dvi_enum_list)); ++ if (prop) { ++ hdmi->output_hdmi_dvi = prop; ++ drm_object_attach_property(&connector->base, prop, 0); ++ } ++ ++ prop = drm_property_create_enum(connector->dev, 0, ++ "output_type_capacity", ++ output_type_cap_list, ++ ARRAY_SIZE(output_type_cap_list)); ++ if (prop) { ++ hdmi->output_type_capacity = prop; ++ drm_object_attach_property(&connector->base, prop, 0); ++ } ++ ++ prop = drm_property_create_enum(connector->dev, 0, ++ "hdmi_quant_range", ++ quant_range_enum_list, ++ ARRAY_SIZE(quant_range_enum_list)); ++ if (prop) { ++ hdmi->quant_range = prop; ++ drm_object_attach_property(&connector->base, prop, 0); ++ } ++ } ++#endif ++ ++ prop = connector->dev->mode_config.hdr_output_metadata_property; ++ if (version >= 0x211a || hdmi->is_hdmi_qp) ++ drm_object_attach_property(&connector->base, prop, 0); ++ ++ if (!drm_mode_create_hdmi_colorspace_property(connector, 0)) ++ drm_object_attach_property(&connector->base, ++ connector->colorspace_property, 0); ++ ++#if 0 ++ // [CC:] if this is not needed, also drop connector_id_prop ++ if (!private->connector_id_prop) ++ private->connector_id_prop = drm_property_create_range(connector->dev, ++ DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_IMMUTABLE, ++ "CONNECTOR_ID", 0, 0xf); ++ if (private->connector_id_prop) ++ drm_object_attach_property(&connector->base, private->connector_id_prop, hdmi->id); ++#endif ++} ++ ++static void ++dw_hdmi_rockchip_destroy_properties(struct drm_connector *connector, ++ void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ if (hdmi->color_depth_property) { ++ drm_property_destroy(connector->dev, ++ hdmi->color_depth_property); ++ hdmi->color_depth_property = NULL; ++ } ++ ++ if (hdmi->hdmi_output_property) { ++ drm_property_destroy(connector->dev, ++ hdmi->hdmi_output_property); ++ hdmi->hdmi_output_property = NULL; ++ } ++ ++ if (hdmi->colordepth_capacity) { ++ drm_property_destroy(connector->dev, ++ hdmi->colordepth_capacity); ++ hdmi->colordepth_capacity = NULL; ++ } ++ ++ if (hdmi->outputmode_capacity) { ++ drm_property_destroy(connector->dev, ++ hdmi->outputmode_capacity); ++ hdmi->outputmode_capacity = NULL; ++ } ++ ++ if (hdmi->quant_range) { ++ drm_property_destroy(connector->dev, ++ hdmi->quant_range); ++ hdmi->quant_range = NULL; ++ } ++ ++ if (hdmi->hdr_panel_metadata_property) { ++ drm_property_destroy(connector->dev, ++ hdmi->hdr_panel_metadata_property); ++ hdmi->hdr_panel_metadata_property = NULL; ++ } ++ ++ if (hdmi->next_hdr_sink_data_property) { ++ drm_property_destroy(connector->dev, ++ hdmi->next_hdr_sink_data_property); ++ hdmi->next_hdr_sink_data_property = NULL; ++ } ++ ++ if (hdmi->output_hdmi_dvi) { ++ drm_property_destroy(connector->dev, ++ hdmi->output_hdmi_dvi); ++ hdmi->output_hdmi_dvi = NULL; ++ } ++ ++ if (hdmi->output_type_capacity) { ++ drm_property_destroy(connector->dev, ++ hdmi->output_type_capacity); ++ hdmi->output_type_capacity = NULL; ++ } ++ ++ if (hdmi->user_split_mode_prop) { ++ drm_property_destroy(connector->dev, ++ hdmi->user_split_mode_prop); ++ hdmi->user_split_mode_prop = NULL; ++ } ++} ++ ++static int ++dw_hdmi_rockchip_set_property(struct drm_connector *connector, ++ struct drm_connector_state *state, ++ struct drm_property *property, ++ u64 val, ++ void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ struct drm_mode_config *config = &connector->dev->mode_config; ++ ++ if (property == hdmi->color_depth_property) { ++ hdmi->colordepth = val; ++ /* If hdmi is disconnected, state->crtc is null */ ++ if (!state->crtc) ++ return 0; ++ if (dw_hdmi_rockchip_check_color(state, hdmi)) ++ hdmi->color_changed++; ++ return 0; ++ } else if (property == hdmi->hdmi_output_property) { ++ hdmi->hdmi_output = val; ++ if (!state->crtc) ++ return 0; ++ if (dw_hdmi_rockchip_check_color(state, hdmi)) ++ hdmi->color_changed++; ++ return 0; ++ } else if (property == hdmi->quant_range) { ++ u64 quant_range = hdmi->hdmi_quant_range; ++ ++ hdmi->hdmi_quant_range = val; ++ if (quant_range != hdmi->hdmi_quant_range) ++ dw_hdmi_set_quant_range(hdmi->hdmi); ++ return 0; ++ } else if (property == config->hdr_output_metadata_property) { ++ return 0; ++ } else if (property == hdmi->output_hdmi_dvi) { ++ if (hdmi->force_output != val) ++ hdmi->color_changed++; ++ hdmi->force_output = val; ++ dw_hdmi_set_output_type(hdmi->hdmi, val); ++ return 0; ++ } else if (property == hdmi->colordepth_capacity) { ++ return 0; ++ } else if (property == hdmi->outputmode_capacity) { ++ return 0; ++ } else if (property == hdmi->output_type_capacity) { ++ return 0; ++ } ++ ++ DRM_ERROR("Unknown property [PROP:%d:%s]\n", ++ property->base.id, property->name); ++ ++ return -EINVAL; ++} ++ ++static int ++dw_hdmi_rockchip_get_property(struct drm_connector *connector, ++ const struct drm_connector_state *state, ++ struct drm_property *property, ++ u64 *val, ++ void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ struct drm_display_info *info = &connector->display_info; ++ struct drm_mode_config *config = &connector->dev->mode_config; ++ ++ if (property == hdmi->color_depth_property) { ++ *val = hdmi->colordepth; ++ return 0; ++ } else if (property == hdmi->hdmi_output_property) { ++ *val = hdmi->hdmi_output; ++ return 0; ++ } else if (property == hdmi->colordepth_capacity) { ++ *val = BIT(RK_IF_DEPTH_8); ++ /* RK3368 only support 8bit */ ++ if (hdmi->unsupported_deep_color) ++ return 0; ++ if (info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) ++ *val |= BIT(RK_IF_DEPTH_10); ++ if (info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36) ++ *val |= BIT(RK_IF_DEPTH_12); ++ if (info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_48) ++ *val |= BIT(RK_IF_DEPTH_16); ++ if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) ++ *val |= BIT(RK_IF_DEPTH_420_10); ++ if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) ++ *val |= BIT(RK_IF_DEPTH_420_12); ++ if (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48) ++ *val |= BIT(RK_IF_DEPTH_420_16); ++ return 0; ++ } else if (property == hdmi->outputmode_capacity) { ++ *val = BIT(RK_IF_FORMAT_RGB); ++ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) ++ *val |= BIT(RK_IF_FORMAT_YCBCR444); ++ if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) ++ *val |= BIT(RK_IF_FORMAT_YCBCR422); ++ if (connector->ycbcr_420_allowed && ++ info->color_formats & DRM_COLOR_FORMAT_YCBCR420) ++ *val |= BIT(RK_IF_FORMAT_YCBCR420); ++ return 0; ++ } else if (property == hdmi->quant_range) { ++ *val = hdmi->hdmi_quant_range; ++ return 0; ++ } else if (property == config->hdr_output_metadata_property) { ++ *val = state->hdr_output_metadata ? ++ state->hdr_output_metadata->base.id : 0; ++ return 0; ++ } else if (property == hdmi->output_hdmi_dvi) { ++ *val = hdmi->force_output; ++ return 0; ++ } else if (property == hdmi->output_type_capacity) { ++ *val = dw_hdmi_get_output_type_cap(hdmi->hdmi); ++ return 0; ++ } else if (property == hdmi->user_split_mode_prop) { ++ *val = hdmi->user_split_mode; ++ return 0; ++ } ++ ++ DRM_ERROR("Unknown property [PROP:%d:%s]\n", ++ property->base.id, property->name); ++ ++ return -EINVAL; ++} ++ ++static const struct dw_hdmi_property_ops dw_hdmi_rockchip_property_ops = { ++ .attach_properties = dw_hdmi_rockchip_attach_properties, ++ .destroy_properties = dw_hdmi_rockchip_destroy_properties, ++ .set_property = dw_hdmi_rockchip_set_property, ++ .get_property = dw_hdmi_rockchip_get_property, ++}; ++ + static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { + .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, + .mode_set = dw_hdmi_rockchip_encoder_mode_set, +@@ -356,20 +2518,24 @@ static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_fun + .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, + }; + +-static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, +- const struct drm_display_info *display, +- const struct drm_display_mode *mode) ++static void dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data) + { + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; + +- return phy_power_on(hdmi->phy); ++ while (hdmi->phy->power_count > 0) ++ phy_power_off(hdmi->phy); + } + +-static void dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data) ++static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, ++ const struct drm_display_info *display, ++ const struct drm_display_mode *mode) + { + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; + +- phy_power_off(hdmi->phy); ++ dw_hdmi_rockchip_genphy_disable(dw_hdmi, data); ++ dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display); ++ ++ return phy_power_on(hdmi->phy); + } + + static void dw_hdmi_rk3228_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) +@@ -436,6 +2602,90 @@ static void dw_hdmi_rk3328_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) + RK3328_HDMI_HPD_IOE)); + } + ++static void dw_hdmi_qp_rockchip_phy_disable(struct dw_hdmi_qp *dw_hdmi, ++ void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ while (hdmi->phy->power_count > 0) ++ phy_power_off(hdmi->phy); ++} ++ ++static int dw_hdmi_qp_rockchip_genphy_init(struct dw_hdmi_qp *dw_hdmi, void *data, ++ struct drm_display_mode *mode) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ dw_hdmi_qp_rockchip_phy_disable(dw_hdmi, data); ++ ++ return phy_power_on(hdmi->phy); ++} ++ ++static enum drm_connector_status ++dw_hdmi_rk3588_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) ++{ ++ u32 val; ++ int ret; ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &val); ++ ++ if (!hdmi->id) { ++ if (val & RK3588_HDMI0_LEVEL_INT) { ++ hdmi->hpd_stat = true; ++ ret = connector_status_connected; ++ } else { ++ hdmi->hpd_stat = false; ++ ret = connector_status_disconnected; ++ } ++ } else { ++ if (val & RK3588_HDMI1_LEVEL_INT) { ++ hdmi->hpd_stat = true; ++ ret = connector_status_connected; ++ } else { ++ hdmi->hpd_stat = false; ++ ret = connector_status_disconnected; ++ } ++ } ++ ++ return ret; ++} ++ ++static void dw_hdmi_rk3588_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ u32 val; ++ ++ if (!hdmi->id) { ++ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR, ++ RK3588_HDMI0_HPD_INT_CLR) | ++ HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK); ++ } else { ++ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR, ++ RK3588_HDMI1_HPD_INT_CLR) | ++ HIWORD_UPDATE(0, RK3588_HDMI1_HPD_INT_MSK); ++ } ++ ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); ++} ++ ++static void dw_hdmi_rk3588_phy_set_mode(struct dw_hdmi_qp *dw_hdmi, void *data, ++ u32 mode_mask, bool enable) ++{ ++ struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; ++ ++ if (!hdmi->phy) ++ return; ++ ++ /* set phy earc/frl mode */ ++ if (enable) ++ hdmi->phy_bus_width |= mode_mask; ++ else ++ hdmi->phy_bus_width &= ~mode_mask; ++ ++ phy_set_bus_width(hdmi->phy, hdmi->phy_bus_width); ++} ++ + static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { + .init = dw_hdmi_rockchip_genphy_init, + .disable = dw_hdmi_rockchip_genphy_disable, +@@ -525,6 +2775,30 @@ static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = { + .use_drm_infoframe = true, + }; + ++static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = { ++ .init = dw_hdmi_qp_rockchip_genphy_init, ++ .disable = dw_hdmi_qp_rockchip_phy_disable, ++ .read_hpd = dw_hdmi_rk3588_read_hpd, ++ .setup_hpd = dw_hdmi_rk3588_setup_hpd, ++ .set_mode = dw_hdmi_rk3588_phy_set_mode, ++}; ++ ++struct rockchip_hdmi_chip_data rk3588_hdmi_chip_data = { ++ .lcdsel_grf_reg = -1, ++ .ddc_en_reg = RK3588_GRF_VO1_CON3, ++ .split_mode = true, ++}; ++ ++static const struct dw_hdmi_plat_data rk3588_hdmi_drv_data = { ++ .phy_data = &rk3588_hdmi_chip_data, ++ .qp_phy_ops = &rk3588_hdmi_phy_ops, ++ .phy_name = "samsung_hdptx_phy", ++ .phy_force_vendor = true, ++ .ycbcr_420_allowed = true, ++ .is_hdmi_qp = true, ++ .use_drm_infoframe = true, ++}; ++ + static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { + { .compatible = "rockchip,rk3228-dw-hdmi", + .data = &rk3228_hdmi_drv_data +@@ -541,6 +2815,9 @@ static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { + { .compatible = "rockchip,rk3568-dw-hdmi", + .data = &rk3568_hdmi_drv_data + }, ++ { .compatible = "rockchip,rk3588-dw-hdmi", ++ .data = &rk3588_hdmi_drv_data ++ }, + {}, + }; + MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids); +@@ -550,44 +2827,103 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + { + struct platform_device *pdev = to_platform_device(dev); + struct dw_hdmi_plat_data *plat_data; +- const struct of_device_id *match; + struct drm_device *drm = data; + struct drm_encoder *encoder; + struct rockchip_hdmi *hdmi; ++ struct rockchip_hdmi *secondary; + int ret; ++ u32 val; + + if (!pdev->dev.of_node) + return -ENODEV; + +- hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); ++ hdmi = platform_get_drvdata(pdev); + if (!hdmi) + return -ENOMEM; + +- match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); +- plat_data = devm_kmemdup(&pdev->dev, match->data, +- sizeof(*plat_data), GFP_KERNEL); +- if (!plat_data) +- return -ENOMEM; ++ plat_data = hdmi->plat_data; ++ hdmi->drm_dev = drm; + +- hdmi->dev = &pdev->dev; +- hdmi->plat_data = plat_data; +- hdmi->chip_data = plat_data->phy_data; + plat_data->phy_data = hdmi; +- plat_data->priv_data = hdmi; +- encoder = &hdmi->encoder.encoder; ++ plat_data->get_input_bus_format = ++ dw_hdmi_rockchip_get_input_bus_format; ++ plat_data->get_output_bus_format = ++ dw_hdmi_rockchip_get_output_bus_format; ++ plat_data->get_enc_in_encoding = ++ dw_hdmi_rockchip_get_enc_in_encoding; ++ plat_data->get_enc_out_encoding = ++ dw_hdmi_rockchip_get_enc_out_encoding; ++ plat_data->get_quant_range = ++ dw_hdmi_rockchip_get_quant_range; ++ plat_data->get_hdr_property = ++ dw_hdmi_rockchip_get_hdr_property; ++ plat_data->get_hdr_blob = ++ dw_hdmi_rockchip_get_hdr_blob; ++ plat_data->get_color_changed = ++ dw_hdmi_rockchip_get_color_changed; ++ // plat_data->get_edid_dsc_info = ++ // dw_hdmi_rockchip_get_edid_dsc_info; ++ // plat_data->get_next_hdr_data = ++ // dw_hdmi_rockchip_get_next_hdr_data; ++ plat_data->get_link_cfg = dw_hdmi_rockchip_get_link_cfg; ++ plat_data->set_grf_cfg = rk3588_set_grf_cfg; ++ // plat_data->convert_to_split_mode = drm_mode_convert_to_split_mode; ++ // plat_data->convert_to_origin_mode = drm_mode_convert_to_origin_mode; ++ ++ plat_data->property_ops = &dw_hdmi_rockchip_property_ops; ++ ++ secondary = rockchip_hdmi_find_by_id(dev->driver, !hdmi->id); ++ /* If don't enable hdmi0 and hdmi1, we don't enable split mode */ ++ if (hdmi->chip_data->split_mode && secondary) { + +- encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); +- rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder, +- dev->of_node, 0, 0); ++ /* ++ * hdmi can only attach bridge and init encoder/connector in the ++ * last bind hdmi in split mode, or hdmi->hdmi_qp will not be initialized ++ * and plat_data->left/right will be null pointer. we must check if split ++ * mode is on and determine the sequence of hdmi bind. ++ */ ++ if (device_property_read_bool(dev, "split-mode") || ++ device_property_read_bool(secondary->dev, "split-mode")) { ++ plat_data->split_mode = true; ++ secondary->plat_data->split_mode = true; ++ if (!secondary->plat_data->first_screen) ++ plat_data->first_screen = true; ++ } ++ ++ if (device_property_read_bool(dev, "user-split-mode") || ++ device_property_read_bool(secondary->dev, "user-split-mode")) { ++ hdmi->user_split_mode = true; ++ secondary->user_split_mode = true; ++ } ++ } ++ ++ if (!plat_data->first_screen) { ++ encoder = &hdmi->encoder.encoder; ++ encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); ++ rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder, ++ dev->of_node, 0, 0); ++ /* ++ * If we failed to find the CRTC(s) which this encoder is ++ * supposed to be connected to, it's because the CRTC has ++ * not been registered yet. Defer probing, and hope that ++ * the required CRTC is added later. ++ */ ++ if (encoder->possible_crtcs == 0) ++ return -EPROBE_DEFER; ++ ++ drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); ++ // [CC:] consider using drmm_simple_encoder_alloc() ++ drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); ++ } ++ ++ if (!plat_data->max_tmdsclk) ++ hdmi->max_tmdsclk = 594000; ++ else ++ hdmi->max_tmdsclk = plat_data->max_tmdsclk; + +- /* +- * If we failed to find the CRTC(s) which this encoder is +- * supposed to be connected to, it's because the CRTC has +- * not been registered yet. Defer probing, and hope that +- * the required CRTC is added later. +- */ +- if (encoder->possible_crtcs == 0) +- return -EPROBE_DEFER; ++ ++ hdmi->unsupported_yuv_input = plat_data->unsupported_yuv_input; ++ hdmi->unsupported_deep_color = plat_data->unsupported_deep_color; + + ret = rockchip_hdmi_parse_dt(hdmi); + if (ret) { +@@ -596,34 +2932,44 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + return ret; + } + +- hdmi->phy = devm_phy_optional_get(dev, "hdmi"); +- if (IS_ERR(hdmi->phy)) { +- ret = PTR_ERR(hdmi->phy); +- if (ret != -EPROBE_DEFER) +- DRM_DEV_ERROR(hdmi->dev, "failed to get phy\n"); ++ ret = clk_prepare_enable(hdmi->aud_clk); ++ if (ret) { ++ dev_err(hdmi->dev, "Failed to enable HDMI aud_clk: %d\n", ret); + return ret; + } + +- ret = regulator_enable(hdmi->avdd_0v9); ++ ret = clk_prepare_enable(hdmi->hpd_clk); + if (ret) { +- DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret); +- goto err_avdd_0v9; ++ dev_err(hdmi->dev, "Failed to enable HDMI hpd_clk: %d\n", ret); ++ return ret; + } + +- ret = regulator_enable(hdmi->avdd_1v8); ++ ret = clk_prepare_enable(hdmi->hclk_vo1); + if (ret) { +- DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret); +- goto err_avdd_1v8; ++ dev_err(hdmi->dev, "Failed to enable HDMI hclk_vo1: %d\n", ret); ++ return ret; + } + +- ret = clk_prepare_enable(hdmi->ref_clk); ++ ret = clk_prepare_enable(hdmi->earc_clk); + if (ret) { +- DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI reference clock: %d\n", +- ret); +- goto err_clk; ++ dev_err(hdmi->dev, "Failed to enable HDMI earc_clk: %d\n", ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(hdmi->hdmitx_ref); ++ if (ret) { ++ dev_err(hdmi->dev, "Failed to enable HDMI hdmitx_ref: %d\n", ++ ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(hdmi->pclk); ++ if (ret) { ++ dev_err(hdmi->dev, "Failed to enable HDMI pclk: %d\n", ret); ++ return ret; + } + +- if (hdmi->chip_data == &rk3568_chip_data) { ++ if (hdmi->chip_data->ddc_en_reg == RK3568_GRF_VO_CON1) { + regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1, + HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK | + RK3568_HDMI_SCLIN_MSK, +@@ -631,12 +2977,131 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + RK3568_HDMI_SCLIN_MSK)); + } + +- drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); +- drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); ++ if (hdmi->is_hdmi_qp) { ++ if (!hdmi->id) { ++ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | ++ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | ++ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | ++ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); ++ ++ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, ++ RK3588_SET_HPD_PATH_MASK); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); ++ ++ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL, ++ RK3588_HDMI0_GRANT_SEL); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val); ++ } else { ++ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | ++ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | ++ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | ++ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); ++ ++ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, ++ RK3588_SET_HPD_PATH_MASK); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); ++ ++ val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL, ++ RK3588_HDMI1_GRANT_SEL); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val); ++ } ++ } + +- platform_set_drvdata(pdev, hdmi); ++ ret = clk_prepare_enable(hdmi->hclk_vio); ++ if (ret) { ++ dev_err(hdmi->dev, "Failed to enable HDMI hclk_vio: %d\n", ++ ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(hdmi->hclk_vop); ++ if (ret) { ++ dev_err(hdmi->dev, "Failed to enable HDMI hclk_vop: %d\n", ++ ret); ++ return ret; ++ } ++ ++ ret = clk_prepare_enable(hdmi->ref_clk); ++ if (ret) { ++ DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI reference clock: %d\n", ++ ret); ++ goto err_clk; ++ } ++ ++ ret = regulator_enable(hdmi->avdd_0v9); ++ if (ret) { ++ DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret); ++ goto err_avdd_0v9; ++ } ++ ++ ret = regulator_enable(hdmi->avdd_1v8); ++ if (ret) { ++ DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret); ++ goto err_avdd_1v8; ++ } ++ ++ if (!hdmi->id) ++ val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK); ++ else ++ val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK, RK3588_HDMI1_HPD_INT_MSK); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); ++ ++ if (hdmi->is_hdmi_qp) { ++ hdmi->hpd_irq = platform_get_irq(pdev, 4); ++ if (hdmi->hpd_irq < 0) ++ return hdmi->hpd_irq; ++ ++ ret = devm_request_threaded_irq(hdmi->dev, hdmi->hpd_irq, ++ rockchip_hdmi_hardirq, ++ rockchip_hdmi_irq, ++ IRQF_SHARED, "dw-hdmi-qp-hpd", ++ hdmi); ++ if (ret) ++ return ret; ++ } ++ ++ hdmi->phy = devm_phy_optional_get(dev, "hdmi"); ++ if (IS_ERR(hdmi->phy)) { ++ hdmi->phy = devm_phy_optional_get(dev, "hdmi_phy"); ++ if (IS_ERR(hdmi->phy)) { ++ ret = PTR_ERR(hdmi->phy); ++ if (ret != -EPROBE_DEFER) ++ DRM_DEV_ERROR(hdmi->dev, "failed to get phy\n"); ++ return ret; ++ } ++ } ++ ++ if (hdmi->is_hdmi_qp) { ++ // [CC:] do proper error handling, e.g. clk_disable_unprepare ++ hdmi->hdmi_qp = dw_hdmi_qp_bind(pdev, &hdmi->encoder.encoder, plat_data); ++ ++ if (IS_ERR(hdmi->hdmi_qp)) { ++ ret = PTR_ERR(hdmi->hdmi_qp); ++ drm_encoder_cleanup(&hdmi->encoder.encoder); ++ } ++ ++ // if (plat_data->connector) { ++ // hdmi->sub_dev.connector = plat_data->connector; ++ // hdmi->sub_dev.of_node = dev->of_node; ++ // rockchip_drm_register_sub_dev(&hdmi->sub_dev); ++ // } ++ ++ if (plat_data->split_mode && secondary) { ++ if (device_property_read_bool(dev, "split-mode")) { ++ plat_data->right = secondary->hdmi_qp; ++ secondary->plat_data->left = hdmi->hdmi_qp; ++ } else { ++ plat_data->left = secondary->hdmi_qp; ++ secondary->plat_data->right = hdmi->hdmi_qp; ++ } ++ } ++ ++ return ret; ++ } + +- hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); ++ hdmi->hdmi = dw_hdmi_bind(pdev, &hdmi->encoder.encoder, plat_data); + + /* + * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), +@@ -647,11 +3112,24 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, + goto err_bind; + } + ++ // if (plat_data->connector) { ++ // hdmi->sub_dev.connector = plat_data->connector; ++ // hdmi->sub_dev.of_node = dev->of_node; ++ // rockchip_drm_register_sub_dev(&hdmi->sub_dev); ++ // } ++ + return 0; + + err_bind: +- drm_encoder_cleanup(encoder); ++ drm_encoder_cleanup(&hdmi->encoder.encoder); ++ clk_disable_unprepare(hdmi->aud_clk); + clk_disable_unprepare(hdmi->ref_clk); ++ clk_disable_unprepare(hdmi->hclk_vop); ++ clk_disable_unprepare(hdmi->hpd_clk); ++ clk_disable_unprepare(hdmi->hclk_vo1); ++ clk_disable_unprepare(hdmi->earc_clk); ++ clk_disable_unprepare(hdmi->hdmitx_ref); ++ clk_disable_unprepare(hdmi->pclk); + err_clk: + regulator_disable(hdmi->avdd_1v8); + err_avdd_1v8: +@@ -665,9 +3143,29 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, + { + struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); + +- dw_hdmi_unbind(hdmi->hdmi); ++ if (hdmi->is_hdmi_qp) { ++ cancel_delayed_work(&hdmi->work); ++ flush_workqueue(hdmi->workqueue); ++ } ++ ++ // if (hdmi->sub_dev.connector) ++ // rockchip_drm_unregister_sub_dev(&hdmi->sub_dev); ++ // ++ if (hdmi->is_hdmi_qp) ++ dw_hdmi_qp_unbind(hdmi->hdmi_qp); ++ else ++ dw_hdmi_unbind(hdmi->hdmi); ++ + drm_encoder_cleanup(&hdmi->encoder.encoder); ++ ++ clk_disable_unprepare(hdmi->aud_clk); + clk_disable_unprepare(hdmi->ref_clk); ++ clk_disable_unprepare(hdmi->hclk_vop); ++ clk_disable_unprepare(hdmi->hpd_clk); ++ clk_disable_unprepare(hdmi->hclk_vo1); ++ clk_disable_unprepare(hdmi->earc_clk); ++ clk_disable_unprepare(hdmi->hdmitx_ref); ++ clk_disable_unprepare(hdmi->pclk); + + regulator_disable(hdmi->avdd_1v8); + regulator_disable(hdmi->avdd_0v9); +@@ -680,30 +3178,142 @@ static const struct component_ops dw_hdmi_rockchip_ops = { + + static int dw_hdmi_rockchip_probe(struct platform_device *pdev) + { ++ struct rockchip_hdmi *hdmi; ++ const struct of_device_id *match; ++ struct dw_hdmi_plat_data *plat_data; ++ int id; ++ ++ hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); ++ if (!hdmi) ++ return -ENOMEM; ++ ++ id = of_alias_get_id(pdev->dev.of_node, "hdmi"); ++ if (id < 0) ++ id = 0; ++ ++ hdmi->id = id; ++ hdmi->dev = &pdev->dev; ++ ++ match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); ++ plat_data = devm_kmemdup(&pdev->dev, match->data, ++ sizeof(*plat_data), GFP_KERNEL); ++ if (!plat_data) ++ return -ENOMEM; ++ ++ plat_data->id = hdmi->id; ++ hdmi->plat_data = plat_data; ++ hdmi->chip_data = plat_data->phy_data; ++ hdmi->is_hdmi_qp = plat_data->is_hdmi_qp; ++ ++ if (hdmi->is_hdmi_qp) { ++ hdmi->workqueue = create_workqueue("hpd_queue"); ++ INIT_DELAYED_WORK(&hdmi->work, repo_hpd_event); ++ } ++ ++ platform_set_drvdata(pdev, hdmi); ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_get_sync(&pdev->dev); ++ + return component_add(&pdev->dev, &dw_hdmi_rockchip_ops); + } + ++static void dw_hdmi_rockchip_shutdown(struct platform_device *pdev) ++{ ++ struct rockchip_hdmi *hdmi = dev_get_drvdata(&pdev->dev); ++ ++ if (!hdmi) ++ return; ++ ++ if (hdmi->is_hdmi_qp) { ++ cancel_delayed_work(&hdmi->work); ++ flush_workqueue(hdmi->workqueue); ++ dw_hdmi_qp_suspend(hdmi->dev, hdmi->hdmi_qp); ++ } else { ++ dw_hdmi_suspend(hdmi->hdmi); ++ } ++ pm_runtime_put_sync(&pdev->dev); ++} ++ + static void dw_hdmi_rockchip_remove(struct platform_device *pdev) + { ++ struct rockchip_hdmi *hdmi = dev_get_drvdata(&pdev->dev); ++ + component_del(&pdev->dev, &dw_hdmi_rockchip_ops); ++ pm_runtime_disable(&pdev->dev); ++ ++ if (hdmi->is_hdmi_qp) ++ destroy_workqueue(hdmi->workqueue); ++} ++ ++static int __maybe_unused dw_hdmi_rockchip_suspend(struct device *dev) ++{ ++ struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); ++ ++ if (hdmi->is_hdmi_qp) ++ dw_hdmi_qp_suspend(dev, hdmi->hdmi_qp); ++ else ++ dw_hdmi_suspend(hdmi->hdmi); ++ ++ pm_runtime_put_sync(dev); ++ ++ return 0; + } + + static int __maybe_unused dw_hdmi_rockchip_resume(struct device *dev) + { + struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); ++ u32 val; + +- dw_hdmi_resume(hdmi->hdmi); ++ if (hdmi->is_hdmi_qp) { ++ if (!hdmi->id) { ++ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | ++ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | ++ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | ++ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON3, val); ++ ++ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, ++ RK3588_SET_HPD_PATH_MASK); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); ++ ++ val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL, ++ RK3588_HDMI0_GRANT_SEL); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val); ++ } else { ++ val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) | ++ HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) | ++ HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) | ++ HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val); ++ ++ val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, ++ RK3588_SET_HPD_PATH_MASK); ++ regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); ++ ++ val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL, ++ RK3588_HDMI1_GRANT_SEL); ++ regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON9, val); ++ } ++ ++ dw_hdmi_qp_resume(dev, hdmi->hdmi_qp); ++ drm_helper_hpd_irq_event(hdmi->drm_dev); ++ } else { ++ dw_hdmi_resume(hdmi->hdmi); ++ } ++ pm_runtime_get_sync(dev); + + return 0; + } + + static const struct dev_pm_ops dw_hdmi_rockchip_pm = { +- SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_rockchip_resume) ++ SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_rockchip_suspend, ++ dw_hdmi_rockchip_resume) + }; + + struct platform_driver dw_hdmi_rockchip_pltfm_driver = { + .probe = dw_hdmi_rockchip_probe, + .remove_new = dw_hdmi_rockchip_remove, ++ .shutdown = dw_hdmi_rockchip_shutdown, + .driver = { + .name = "dwhdmi-rockchip", + .pm = &dw_hdmi_rockchip_pm, +diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h +index 111111111111..222222222222 100644 +--- a/include/drm/bridge/dw_hdmi.h ++++ b/include/drm/bridge/dw_hdmi.h +@@ -6,12 +6,14 @@ + #ifndef __DW_HDMI__ + #define __DW_HDMI__ + ++#include + #include + + struct drm_display_info; + struct drm_display_mode; + struct drm_encoder; + struct dw_hdmi; ++struct dw_hdmi_qp; + struct platform_device; + + /** +@@ -92,6 +94,13 @@ enum dw_hdmi_phy_type { + DW_HDMI_PHY_VENDOR_PHY = 0xfe, + }; + ++struct dw_hdmi_audio_tmds_n { ++ unsigned long tmds; ++ unsigned int n_32k; ++ unsigned int n_44k1; ++ unsigned int n_48k; ++}; ++ + struct dw_hdmi_mpll_config { + unsigned long mpixelclock; + struct { +@@ -112,6 +121,15 @@ struct dw_hdmi_phy_config { + u16 vlev_ctr; /* voltage level control */ + }; + ++struct dw_hdmi_link_config { ++ bool dsc_mode; ++ bool frl_mode; ++ int frl_lanes; ++ int rate_per_lane; ++ int hcactive; ++ u8 pps_payload[128]; ++}; ++ + struct dw_hdmi_phy_ops { + int (*init)(struct dw_hdmi *hdmi, void *data, + const struct drm_display_info *display, +@@ -123,14 +141,52 @@ struct dw_hdmi_phy_ops { + void (*setup_hpd)(struct dw_hdmi *hdmi, void *data); + }; + ++struct dw_hdmi_qp_phy_ops { ++ int (*init)(struct dw_hdmi_qp *hdmi, void *data, ++ struct drm_display_mode *mode); ++ void (*disable)(struct dw_hdmi_qp *hdmi, void *data); ++ enum drm_connector_status (*read_hpd)(struct dw_hdmi_qp *hdmi, ++ void *data); ++ void (*update_hpd)(struct dw_hdmi_qp *hdmi, void *data, ++ bool force, bool disabled, bool rxsense); ++ void (*setup_hpd)(struct dw_hdmi_qp *hdmi, void *data); ++ void (*set_mode)(struct dw_hdmi_qp *dw_hdmi, void *data, ++ u32 mode_mask, bool enable); ++}; ++ ++struct dw_hdmi_property_ops { ++ void (*attach_properties)(struct drm_connector *connector, ++ unsigned int color, int version, ++ void *data); ++ void (*destroy_properties)(struct drm_connector *connector, ++ void *data); ++ int (*set_property)(struct drm_connector *connector, ++ struct drm_connector_state *state, ++ struct drm_property *property, ++ u64 val, ++ void *data); ++ int (*get_property)(struct drm_connector *connector, ++ const struct drm_connector_state *state, ++ struct drm_property *property, ++ u64 *val, ++ void *data); ++}; ++ + struct dw_hdmi_plat_data { + struct regmap *regm; + ++ //[CC:] not in dowstream + unsigned int output_port; + ++ unsigned long input_bus_format; + unsigned long input_bus_encoding; ++ unsigned int max_tmdsclk; ++ int id; + bool use_drm_infoframe; + bool ycbcr_420_allowed; ++ bool unsupported_yuv_input; ++ bool unsupported_deep_color; ++ bool is_hdmi_qp; + + /* + * Private data passed to all the .mode_valid() and .configure_phy() +@@ -139,6 +195,7 @@ struct dw_hdmi_plat_data { + void *priv_data; + + /* Platform-specific mode validation (optional). */ ++ //[CC:] downstream changed "struct dw_hdmi *hdmi" to "struct drm_connector *connector" + enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data, + const struct drm_display_info *info, + const struct drm_display_mode *mode); +@@ -150,18 +207,50 @@ struct dw_hdmi_plat_data { + + /* Vendor PHY support */ + const struct dw_hdmi_phy_ops *phy_ops; ++ const struct dw_hdmi_qp_phy_ops *qp_phy_ops; + const char *phy_name; + void *phy_data; + unsigned int phy_force_vendor; + ++ /* split mode */ ++ bool split_mode; ++ bool first_screen; ++ struct dw_hdmi_qp *left; ++ struct dw_hdmi_qp *right; ++ + /* Synopsys PHY support */ + const struct dw_hdmi_mpll_config *mpll_cfg; ++ const struct dw_hdmi_mpll_config *mpll_cfg_420; + const struct dw_hdmi_curr_ctrl *cur_ctr; + const struct dw_hdmi_phy_config *phy_config; + int (*configure_phy)(struct dw_hdmi *hdmi, void *data, + unsigned long mpixelclock); + + unsigned int disable_cec : 1; ++ ++ //[CC:] 7b29b5f29585 ("drm/rockchip: dw_hdmi: Support HDMI 2.0 YCbCr 4:2:0") ++ unsigned long (*get_input_bus_format)(void *data); ++ unsigned long (*get_output_bus_format)(void *data); ++ unsigned long (*get_enc_in_encoding)(void *data); ++ unsigned long (*get_enc_out_encoding)(void *data); ++ ++ unsigned long (*get_quant_range)(void *data); ++ struct drm_property *(*get_hdr_property)(void *data); ++ struct drm_property_blob *(*get_hdr_blob)(void *data); ++ bool (*get_color_changed)(void *data); ++ int (*get_yuv422_format)(struct drm_connector *connector, ++ struct edid *edid); ++ int (*get_edid_dsc_info)(void *data, struct edid *edid); ++ int (*get_next_hdr_data)(void *data, struct edid *edid, ++ struct drm_connector *connector); ++ struct dw_hdmi_link_config *(*get_link_cfg)(void *data); ++ void (*set_grf_cfg)(void *data); ++ void (*convert_to_split_mode)(struct drm_display_mode *mode); ++ void (*convert_to_origin_mode)(struct drm_display_mode *mode); ++ ++ /* Vendor Property support */ ++ const struct dw_hdmi_property_ops *property_ops; ++ struct drm_connector *connector; + }; + + struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, +@@ -172,6 +261,7 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, + struct drm_encoder *encoder, + const struct dw_hdmi_plat_data *plat_data); + ++void dw_hdmi_suspend(struct dw_hdmi *hdmi); + void dw_hdmi_resume(struct dw_hdmi *hdmi); + + void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense); +@@ -205,6 +295,17 @@ enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, + void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data, + bool force, bool disabled, bool rxsense); + void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data); ++void dw_hdmi_set_quant_range(struct dw_hdmi *hdmi); ++void dw_hdmi_set_output_type(struct dw_hdmi *hdmi, u64 val); ++bool dw_hdmi_get_output_whether_hdmi(struct dw_hdmi *hdmi); ++int dw_hdmi_get_output_type_cap(struct dw_hdmi *hdmi); ++ ++void dw_hdmi_qp_unbind(struct dw_hdmi_qp *hdmi); ++struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, ++ struct drm_encoder *encoder, ++ struct dw_hdmi_plat_data *plat_data); ++void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi); ++void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi); + + bool dw_hdmi_bus_fmt_is_420(struct dw_hdmi *hdmi); + +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch new file mode 100644 index 000000000000..eafe1a14369d --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch @@ -0,0 +1,81 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Mon, 15 Jan 2024 22:47:41 +0200 +Subject: arm64: dts: rockchip: Add HDMI0 bridge to rk3588 + +Add DT node for the HDMI0 bridge found on RK3588 SoC. + +Signed-off-by: Cristian Ciocaltea +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 55 ++++++++++ + 1 file changed, 55 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -1407,6 +1407,61 @@ i2s9_8ch: i2s@fddfc000 { + status = "disabled"; + }; + ++ hdmi0: hdmi@fde80000 { ++ compatible = "rockchip,rk3588-dw-hdmi"; ++ reg = <0x0 0xfde80000 0x0 0x20000>; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ clocks = <&cru PCLK_HDMITX0>, ++ <&cru CLK_HDMIHDP0>, ++ <&cru CLK_HDMITX0_EARC>, ++ <&cru CLK_HDMITX0_REF>, ++ <&cru MCLK_I2S5_8CH_TX>, ++ <&cru DCLK_VOP0>, ++ <&cru DCLK_VOP1>, ++ <&cru DCLK_VOP2>, ++ <&cru DCLK_VOP3>, ++ <&cru HCLK_VO1>; ++ clock-names = "pclk", ++ "hpd", ++ "earc", ++ "hdmitx_ref", ++ "aud", ++ "dclk_vp0", ++ "dclk_vp1", ++ "dclk_vp2", ++ "dclk_vp3", ++ "hclk_vo1"; ++ resets = <&cru SRST_HDMITX0_REF>, <&cru SRST_HDMIHDP0>; ++ reset-names = "ref", "hdp"; ++ power-domains = <&power RK3588_PD_VO1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmim0_tx0_cec &hdmim0_tx0_hpd ++ &hdmim0_tx0_scl &hdmim0_tx0_sda>; ++ reg-io-width = <4>; ++ rockchip,grf = <&sys_grf>; ++ rockchip,vo1_grf = <&vo1_grf>; ++ phys = <&hdptxphy_hdmi0>; ++ phy-names = "hdmi"; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hdmi0_in: port@0 { ++ reg = <0>; ++ }; ++ ++ hdmi0_out: port@1 { ++ reg = <1>; ++ }; ++ }; ++ }; ++ + qos_gpu_m0: qos@fdf35000 { + compatible = "rockchip,rk3588-qos", "syscon"; + reg = <0x0 0xfdf35000 0x0 0x20>; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch new file mode 100644 index 000000000000..ea5fca05b9ce --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Tue, 16 Jan 2024 03:13:38 +0200 +Subject: arm64: dts: rockchip: Enable HDMI0 PHY clk provider on rk3588 + +The HDMI0 PHY can be used as a clock provider on RK3588, hence add the +missing #clock-cells property. +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -2913,6 +2913,7 @@ hdptxphy_hdmi0: phy@fed60000 { + reg = <0x0 0xfed60000 0x0 0x2000>; + clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>; + clock-names = "ref", "apb"; ++ #clock-cells = <0>; + #phy-cells = <0>; + resets = <&cru SRST_HDPTX0>, <&cru SRST_P_HDPTX0>, + <&cru SRST_HDPTX0_INIT>, <&cru SRST_HDPTX0_CMN>, +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0141-panthor-v6.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0141-panthor-v6.patch new file mode 100644 index 000000000000..bcf969929b99 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0141-panthor-v6.patch @@ -0,0 +1,14855 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:15 +0100 +Subject: drm/panthor: Add uAPI + +Panthor follows the lead of other recently submitted drivers with +ioctls allowing us to support modern Vulkan features, like sparse memory +binding: + +- Pretty standard GEM management ioctls (BO_CREATE and BO_MMAP_OFFSET), + with the 'exclusive-VM' bit to speed-up BO reservation on job submission +- VM management ioctls (VM_CREATE, VM_DESTROY and VM_BIND). The VM_BIND + ioctl is loosely based on the Xe model, and can handle both + asynchronous and synchronous requests +- GPU execution context creation/destruction, tiler heap context creation + and job submission. Those ioctls reflect how the hardware/scheduler + works and are thus driver specific. + +We also have a way to expose IO regions, such that the usermode driver +can directly access specific/well-isolate registers, like the +LATEST_FLUSH register used to implement cache-flush reduction. + +This uAPI intentionally keeps usermode queues out of the scope, which +explains why doorbell registers and command stream ring-buffers are not +directly exposed to userspace. + +v6: +- Add Maxime's and Heiko's acks + +v5: +- Fix typo +- Add Liviu's R-b + +v4: +- Add a VM_GET_STATE ioctl +- Fix doc +- Expose the CORE_FEATURES register so we can deal with variants in the + UMD +- Add Steve's R-b + +v3: +- Add the concept of sync-only VM operation +- Fix support for 32-bit userspace +- Rework drm_panthor_vm_create to pass the user VA size instead of + the kernel VA size (suggested by Robin Murphy) +- Typo fixes +- Explicitly cast enums with top bit set to avoid compiler warnings in + -pedantic mode. +- Drop property core_group_count as it can be easily calculated by the + number of bits set in l2_present. + +Co-developed-by: Steven Price +Signed-off-by: Steven Price +Signed-off-by: Boris Brezillon +Reviewed-by: Steven Price +Reviewed-by: Liviu Dudau +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + Documentation/gpu/driver-uapi.rst | 5 + + include/uapi/drm/panthor_drm.h | 945 ++++++++++ + 2 files changed, 950 insertions(+) + +diff --git a/Documentation/gpu/driver-uapi.rst b/Documentation/gpu/driver-uapi.rst +index 111111111111..222222222222 100644 +--- a/Documentation/gpu/driver-uapi.rst ++++ b/Documentation/gpu/driver-uapi.rst +@@ -18,6 +18,11 @@ VM_BIND / EXEC uAPI + + .. kernel-doc:: include/uapi/drm/nouveau_drm.h + ++drm/panthor uAPI ++================ ++ ++.. kernel-doc:: include/uapi/drm/panthor_drm.h ++ + drm/xe uAPI + =========== + +diff --git a/include/uapi/drm/panthor_drm.h b/include/uapi/drm/panthor_drm.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/include/uapi/drm/panthor_drm.h +@@ -0,0 +1,945 @@ ++/* SPDX-License-Identifier: MIT */ ++/* Copyright (C) 2023 Collabora ltd. */ ++#ifndef _PANTHOR_DRM_H_ ++#define _PANTHOR_DRM_H_ ++ ++#include "drm.h" ++ ++#if defined(__cplusplus) ++extern "C" { ++#endif ++ ++/** ++ * DOC: Introduction ++ * ++ * This documentation describes the Panthor IOCTLs. ++ * ++ * Just a few generic rules about the data passed to the Panthor IOCTLs: ++ * ++ * - Structures must be aligned on 64-bit/8-byte. If the object is not ++ * naturally aligned, a padding field must be added. ++ * - Fields must be explicitly aligned to their natural type alignment with ++ * pad[0..N] fields. ++ * - All padding fields will be checked by the driver to make sure they are ++ * zeroed. ++ * - Flags can be added, but not removed/replaced. ++ * - New fields can be added to the main structures (the structures ++ * directly passed to the ioctl). Those fields can be added at the end of ++ * the structure, or replace existing padding fields. Any new field being ++ * added must preserve the behavior that existed before those fields were ++ * added when a value of zero is passed. ++ * - New fields can be added to indirect objects (objects pointed by the ++ * main structure), iff those objects are passed a size to reflect the ++ * size known by the userspace driver (see drm_panthor_obj_array::stride ++ * or drm_panthor_dev_query::size). ++ * - If the kernel driver is too old to know some fields, those will be ++ * ignored if zero, and otherwise rejected (and so will be zero on output). ++ * - If userspace is too old to know some fields, those will be zeroed ++ * (input) before the structure is parsed by the kernel driver. ++ * - Each new flag/field addition must come with a driver version update so ++ * the userspace driver doesn't have to trial and error to know which ++ * flags are supported. ++ * - Structures should not contain unions, as this would defeat the ++ * extensibility of such structures. ++ * - IOCTLs can't be removed or replaced. New IOCTL IDs should be placed ++ * at the end of the drm_panthor_ioctl_id enum. ++ */ ++ ++/** ++ * DOC: MMIO regions exposed to userspace. ++ * ++ * .. c:macro:: DRM_PANTHOR_USER_MMIO_OFFSET ++ * ++ * File offset for all MMIO regions being exposed to userspace. Don't use ++ * this value directly, use DRM_PANTHOR_USER__OFFSET values instead. ++ * pgoffset passed to mmap2() is an unsigned long, which forces us to use a ++ * different offset on 32-bit and 64-bit systems. ++ * ++ * .. c:macro:: DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET ++ * ++ * File offset for the LATEST_FLUSH_ID register. The Userspace driver controls ++ * GPU cache flushing through CS instructions, but the flush reduction ++ * mechanism requires a flush_id. This flush_id could be queried with an ++ * ioctl, but Arm provides a well-isolated register page containing only this ++ * read-only register, so let's expose this page through a static mmap offset ++ * and allow direct mapping of this MMIO region so we can avoid the ++ * user <-> kernel round-trip. ++ */ ++#define DRM_PANTHOR_USER_MMIO_OFFSET_32BIT (1ull << 43) ++#define DRM_PANTHOR_USER_MMIO_OFFSET_64BIT (1ull << 56) ++#define DRM_PANTHOR_USER_MMIO_OFFSET (sizeof(unsigned long) < 8 ? \ ++ DRM_PANTHOR_USER_MMIO_OFFSET_32BIT : \ ++ DRM_PANTHOR_USER_MMIO_OFFSET_64BIT) ++#define DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET (DRM_PANTHOR_USER_MMIO_OFFSET | 0) ++ ++/** ++ * DOC: IOCTL IDs ++ * ++ * enum drm_panthor_ioctl_id - IOCTL IDs ++ * ++ * Place new ioctls at the end, don't re-order, don't replace or remove entries. ++ * ++ * These IDs are not meant to be used directly. Use the DRM_IOCTL_PANTHOR_xxx ++ * definitions instead. ++ */ ++enum drm_panthor_ioctl_id { ++ /** @DRM_PANTHOR_DEV_QUERY: Query device information. */ ++ DRM_PANTHOR_DEV_QUERY = 0, ++ ++ /** @DRM_PANTHOR_VM_CREATE: Create a VM. */ ++ DRM_PANTHOR_VM_CREATE, ++ ++ /** @DRM_PANTHOR_VM_DESTROY: Destroy a VM. */ ++ DRM_PANTHOR_VM_DESTROY, ++ ++ /** @DRM_PANTHOR_VM_BIND: Bind/unbind memory to a VM. */ ++ DRM_PANTHOR_VM_BIND, ++ ++ /** @DRM_PANTHOR_VM_GET_STATE: Get VM state. */ ++ DRM_PANTHOR_VM_GET_STATE, ++ ++ /** @DRM_PANTHOR_BO_CREATE: Create a buffer object. */ ++ DRM_PANTHOR_BO_CREATE, ++ ++ /** ++ * @DRM_PANTHOR_BO_MMAP_OFFSET: Get the file offset to pass to ++ * mmap to map a GEM object. ++ */ ++ DRM_PANTHOR_BO_MMAP_OFFSET, ++ ++ /** @DRM_PANTHOR_GROUP_CREATE: Create a scheduling group. */ ++ DRM_PANTHOR_GROUP_CREATE, ++ ++ /** @DRM_PANTHOR_GROUP_DESTROY: Destroy a scheduling group. */ ++ DRM_PANTHOR_GROUP_DESTROY, ++ ++ /** ++ * @DRM_PANTHOR_GROUP_SUBMIT: Submit jobs to queues belonging ++ * to a specific scheduling group. ++ */ ++ DRM_PANTHOR_GROUP_SUBMIT, ++ ++ /** @DRM_PANTHOR_GROUP_GET_STATE: Get the state of a scheduling group. */ ++ DRM_PANTHOR_GROUP_GET_STATE, ++ ++ /** @DRM_PANTHOR_TILER_HEAP_CREATE: Create a tiler heap. */ ++ DRM_PANTHOR_TILER_HEAP_CREATE, ++ ++ /** @DRM_PANTHOR_TILER_HEAP_DESTROY: Destroy a tiler heap. */ ++ DRM_PANTHOR_TILER_HEAP_DESTROY, ++}; ++ ++/** ++ * DRM_IOCTL_PANTHOR() - Build a Panthor IOCTL number ++ * @__access: Access type. Must be R, W or RW. ++ * @__id: One of the DRM_PANTHOR_xxx id. ++ * @__type: Suffix of the type being passed to the IOCTL. ++ * ++ * Don't use this macro directly, use the DRM_IOCTL_PANTHOR_xxx ++ * values instead. ++ * ++ * Return: An IOCTL number to be passed to ioctl() from userspace. ++ */ ++#define DRM_IOCTL_PANTHOR(__access, __id, __type) \ ++ DRM_IO ## __access(DRM_COMMAND_BASE + DRM_PANTHOR_ ## __id, \ ++ struct drm_panthor_ ## __type) ++ ++#define DRM_IOCTL_PANTHOR_DEV_QUERY \ ++ DRM_IOCTL_PANTHOR(WR, DEV_QUERY, dev_query) ++#define DRM_IOCTL_PANTHOR_VM_CREATE \ ++ DRM_IOCTL_PANTHOR(WR, VM_CREATE, vm_create) ++#define DRM_IOCTL_PANTHOR_VM_DESTROY \ ++ DRM_IOCTL_PANTHOR(WR, VM_DESTROY, vm_destroy) ++#define DRM_IOCTL_PANTHOR_VM_BIND \ ++ DRM_IOCTL_PANTHOR(WR, VM_BIND, vm_bind) ++#define DRM_IOCTL_PANTHOR_VM_GET_STATE \ ++ DRM_IOCTL_PANTHOR(WR, VM_GET_STATE, vm_get_state) ++#define DRM_IOCTL_PANTHOR_BO_CREATE \ ++ DRM_IOCTL_PANTHOR(WR, BO_CREATE, bo_create) ++#define DRM_IOCTL_PANTHOR_BO_MMAP_OFFSET \ ++ DRM_IOCTL_PANTHOR(WR, BO_MMAP_OFFSET, bo_mmap_offset) ++#define DRM_IOCTL_PANTHOR_GROUP_CREATE \ ++ DRM_IOCTL_PANTHOR(WR, GROUP_CREATE, group_create) ++#define DRM_IOCTL_PANTHOR_GROUP_DESTROY \ ++ DRM_IOCTL_PANTHOR(WR, GROUP_DESTROY, group_destroy) ++#define DRM_IOCTL_PANTHOR_GROUP_SUBMIT \ ++ DRM_IOCTL_PANTHOR(WR, GROUP_SUBMIT, group_submit) ++#define DRM_IOCTL_PANTHOR_GROUP_GET_STATE \ ++ DRM_IOCTL_PANTHOR(WR, GROUP_GET_STATE, group_get_state) ++#define DRM_IOCTL_PANTHOR_TILER_HEAP_CREATE \ ++ DRM_IOCTL_PANTHOR(WR, TILER_HEAP_CREATE, tiler_heap_create) ++#define DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY \ ++ DRM_IOCTL_PANTHOR(WR, TILER_HEAP_DESTROY, tiler_heap_destroy) ++ ++/** ++ * DOC: IOCTL arguments ++ */ ++ ++/** ++ * struct drm_panthor_obj_array - Object array. ++ * ++ * This object is used to pass an array of objects whose size is subject to changes in ++ * future versions of the driver. In order to support this mutability, we pass a stride ++ * describing the size of the object as known by userspace. ++ * ++ * You shouldn't fill drm_panthor_obj_array fields directly. You should instead use ++ * the DRM_PANTHOR_OBJ_ARRAY() macro that takes care of initializing the stride to ++ * the object size. ++ */ ++struct drm_panthor_obj_array { ++ /** @stride: Stride of object struct. Used for versioning. */ ++ __u32 stride; ++ ++ /** @count: Number of objects in the array. */ ++ __u32 count; ++ ++ /** @array: User pointer to an array of objects. */ ++ __u64 array; ++}; ++ ++/** ++ * DRM_PANTHOR_OBJ_ARRAY() - Initialize a drm_panthor_obj_array field. ++ * @cnt: Number of elements in the array. ++ * @ptr: Pointer to the array to pass to the kernel. ++ * ++ * Macro initializing a drm_panthor_obj_array based on the object size as known ++ * by userspace. ++ */ ++#define DRM_PANTHOR_OBJ_ARRAY(cnt, ptr) \ ++ { .stride = sizeof((ptr)[0]), .count = (cnt), .array = (__u64)(uintptr_t)(ptr) } ++ ++/** ++ * enum drm_panthor_sync_op_flags - Synchronization operation flags. ++ */ ++enum drm_panthor_sync_op_flags { ++ /** @DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK: Synchronization handle type mask. */ ++ DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK = 0xff, ++ ++ /** @DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ: Synchronization object type. */ ++ DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ = 0, ++ ++ /** ++ * @DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ: Timeline synchronization ++ * object type. ++ */ ++ DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ = 1, ++ ++ /** @DRM_PANTHOR_SYNC_OP_WAIT: Wait operation. */ ++ DRM_PANTHOR_SYNC_OP_WAIT = 0 << 31, ++ ++ /** @DRM_PANTHOR_SYNC_OP_SIGNAL: Signal operation. */ ++ DRM_PANTHOR_SYNC_OP_SIGNAL = (int)(1u << 31), ++}; ++ ++/** ++ * struct drm_panthor_sync_op - Synchronization operation. ++ */ ++struct drm_panthor_sync_op { ++ /** @flags: Synchronization operation flags. Combination of DRM_PANTHOR_SYNC_OP values. */ ++ __u32 flags; ++ ++ /** @handle: Sync handle. */ ++ __u32 handle; ++ ++ /** ++ * @timeline_value: MBZ if ++ * (flags & DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK) != ++ * DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ. ++ */ ++ __u64 timeline_value; ++}; ++ ++/** ++ * enum drm_panthor_dev_query_type - Query type ++ * ++ * Place new types at the end, don't re-order, don't remove or replace. ++ */ ++enum drm_panthor_dev_query_type { ++ /** @DRM_PANTHOR_DEV_QUERY_GPU_INFO: Query GPU information. */ ++ DRM_PANTHOR_DEV_QUERY_GPU_INFO = 0, ++ ++ /** @DRM_PANTHOR_DEV_QUERY_CSIF_INFO: Query command-stream interface information. */ ++ DRM_PANTHOR_DEV_QUERY_CSIF_INFO, ++}; ++ ++/** ++ * struct drm_panthor_gpu_info - GPU information ++ * ++ * Structure grouping all queryable information relating to the GPU. ++ */ ++struct drm_panthor_gpu_info { ++ /** @gpu_id : GPU ID. */ ++ __u32 gpu_id; ++#define DRM_PANTHOR_ARCH_MAJOR(x) ((x) >> 28) ++#define DRM_PANTHOR_ARCH_MINOR(x) (((x) >> 24) & 0xf) ++#define DRM_PANTHOR_ARCH_REV(x) (((x) >> 20) & 0xf) ++#define DRM_PANTHOR_PRODUCT_MAJOR(x) (((x) >> 16) & 0xf) ++#define DRM_PANTHOR_VERSION_MAJOR(x) (((x) >> 12) & 0xf) ++#define DRM_PANTHOR_VERSION_MINOR(x) (((x) >> 4) & 0xff) ++#define DRM_PANTHOR_VERSION_STATUS(x) ((x) & 0xf) ++ ++ /** @gpu_rev: GPU revision. */ ++ __u32 gpu_rev; ++ ++ /** @csf_id: Command stream frontend ID. */ ++ __u32 csf_id; ++#define DRM_PANTHOR_CSHW_MAJOR(x) (((x) >> 26) & 0x3f) ++#define DRM_PANTHOR_CSHW_MINOR(x) (((x) >> 20) & 0x3f) ++#define DRM_PANTHOR_CSHW_REV(x) (((x) >> 16) & 0xf) ++#define DRM_PANTHOR_MCU_MAJOR(x) (((x) >> 10) & 0x3f) ++#define DRM_PANTHOR_MCU_MINOR(x) (((x) >> 4) & 0x3f) ++#define DRM_PANTHOR_MCU_REV(x) ((x) & 0xf) ++ ++ /** @l2_features: L2-cache features. */ ++ __u32 l2_features; ++ ++ /** @tiler_features: Tiler features. */ ++ __u32 tiler_features; ++ ++ /** @mem_features: Memory features. */ ++ __u32 mem_features; ++ ++ /** @mmu_features: MMU features. */ ++ __u32 mmu_features; ++#define DRM_PANTHOR_MMU_VA_BITS(x) ((x) & 0xff) ++ ++ /** @thread_features: Thread features. */ ++ __u32 thread_features; ++ ++ /** @max_threads: Maximum number of threads. */ ++ __u32 max_threads; ++ ++ /** @thread_max_workgroup_size: Maximum workgroup size. */ ++ __u32 thread_max_workgroup_size; ++ ++ /** ++ * @thread_max_barrier_size: Maximum number of threads that can wait ++ * simultaneously on a barrier. ++ */ ++ __u32 thread_max_barrier_size; ++ ++ /** @coherency_features: Coherency features. */ ++ __u32 coherency_features; ++ ++ /** @texture_features: Texture features. */ ++ __u32 texture_features[4]; ++ ++ /** @as_present: Bitmask encoding the number of address-space exposed by the MMU. */ ++ __u32 as_present; ++ ++ /** @shader_present: Bitmask encoding the shader cores exposed by the GPU. */ ++ __u64 shader_present; ++ ++ /** @l2_present: Bitmask encoding the L2 caches exposed by the GPU. */ ++ __u64 l2_present; ++ ++ /** @tiler_present: Bitmask encoding the tiler units exposed by the GPU. */ ++ __u64 tiler_present; ++ ++ /* @core_features: Used to discriminate core variants when they exist. */ ++ __u32 core_features; ++ ++ /* @pad: MBZ. */ ++ __u32 pad; ++}; ++ ++/** ++ * struct drm_panthor_csif_info - Command stream interface information ++ * ++ * Structure grouping all queryable information relating to the command stream interface. ++ */ ++struct drm_panthor_csif_info { ++ /** @csg_slot_count: Number of command stream group slots exposed by the firmware. */ ++ __u32 csg_slot_count; ++ ++ /** @cs_slot_count: Number of command stream slots per group. */ ++ __u32 cs_slot_count; ++ ++ /** @cs_reg_count: Number of command stream registers. */ ++ __u32 cs_reg_count; ++ ++ /** @scoreboard_slot_count: Number of scoreboard slots. */ ++ __u32 scoreboard_slot_count; ++ ++ /** ++ * @unpreserved_cs_reg_count: Number of command stream registers reserved by ++ * the kernel driver to call a userspace command stream. ++ * ++ * All registers can be used by a userspace command stream, but the ++ * [cs_slot_count - unpreserved_cs_reg_count .. cs_slot_count] registers are ++ * used by the kernel when DRM_PANTHOR_IOCTL_GROUP_SUBMIT is called. ++ */ ++ __u32 unpreserved_cs_reg_count; ++ ++ /** ++ * @pad: Padding field, set to zero. ++ */ ++ __u32 pad; ++}; ++ ++/** ++ * struct drm_panthor_dev_query - Arguments passed to DRM_PANTHOR_IOCTL_DEV_QUERY ++ */ ++struct drm_panthor_dev_query { ++ /** @type: the query type (see drm_panthor_dev_query_type). */ ++ __u32 type; ++ ++ /** ++ * @size: size of the type being queried. ++ * ++ * If pointer is NULL, size is updated by the driver to provide the ++ * output structure size. If pointer is not NULL, the driver will ++ * only copy min(size, actual_structure_size) bytes to the pointer, ++ * and update the size accordingly. This allows us to extend query ++ * types without breaking userspace. ++ */ ++ __u32 size; ++ ++ /** ++ * @pointer: user pointer to a query type struct. ++ * ++ * Pointer can be NULL, in which case, nothing is copied, but the ++ * actual structure size is returned. If not NULL, it must point to ++ * a location that's large enough to hold size bytes. ++ */ ++ __u64 pointer; ++}; ++ ++/** ++ * struct drm_panthor_vm_create - Arguments passed to DRM_PANTHOR_IOCTL_VM_CREATE ++ */ ++struct drm_panthor_vm_create { ++ /** @flags: VM flags, MBZ. */ ++ __u32 flags; ++ ++ /** @id: Returned VM ID. */ ++ __u32 id; ++ ++ /** ++ * @user_va_range: Size of the VA space reserved for user objects. ++ * ++ * The kernel will pick the remaining space to map kernel-only objects to the ++ * VM (heap chunks, heap context, ring buffers, kernel synchronization objects, ++ * ...). If the space left for kernel objects is too small, kernel object ++ * allocation will fail further down the road. One can use ++ * drm_panthor_gpu_info::mmu_features to extract the total virtual address ++ * range, and chose a user_va_range that leaves some space to the kernel. ++ * ++ * If user_va_range is zero, the kernel will pick a sensible value based on ++ * TASK_SIZE and the virtual range supported by the GPU MMU (the kernel/user ++ * split should leave enough VA space for userspace processes to support SVM, ++ * while still allowing the kernel to map some amount of kernel objects in ++ * the kernel VA range). The value chosen by the driver will be returned in ++ * @user_va_range. ++ * ++ * User VA space always starts at 0x0, kernel VA space is always placed after ++ * the user VA range. ++ */ ++ __u64 user_va_range; ++}; ++ ++/** ++ * struct drm_panthor_vm_destroy - Arguments passed to DRM_PANTHOR_IOCTL_VM_DESTROY ++ */ ++struct drm_panthor_vm_destroy { ++ /** @id: ID of the VM to destroy. */ ++ __u32 id; ++ ++ /** @pad: MBZ. */ ++ __u32 pad; ++}; ++ ++/** ++ * enum drm_panthor_vm_bind_op_flags - VM bind operation flags ++ */ ++enum drm_panthor_vm_bind_op_flags { ++ /** ++ * @DRM_PANTHOR_VM_BIND_OP_MAP_READONLY: Map the memory read-only. ++ * ++ * Only valid with DRM_PANTHOR_VM_BIND_OP_TYPE_MAP. ++ */ ++ DRM_PANTHOR_VM_BIND_OP_MAP_READONLY = 1 << 0, ++ ++ /** ++ * @DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC: Map the memory not-executable. ++ * ++ * Only valid with DRM_PANTHOR_VM_BIND_OP_TYPE_MAP. ++ */ ++ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC = 1 << 1, ++ ++ /** ++ * @DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED: Map the memory uncached. ++ * ++ * Only valid with DRM_PANTHOR_VM_BIND_OP_TYPE_MAP. ++ */ ++ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED = 1 << 2, ++ ++ /** ++ * @DRM_PANTHOR_VM_BIND_OP_TYPE_MASK: Mask used to determine the type of operation. ++ */ ++ DRM_PANTHOR_VM_BIND_OP_TYPE_MASK = (int)(0xfu << 28), ++ ++ /** @DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: Map operation. */ ++ DRM_PANTHOR_VM_BIND_OP_TYPE_MAP = 0 << 28, ++ ++ /** @DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP: Unmap operation. */ ++ DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP = 1 << 28, ++ ++ /** ++ * @DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY: No VM operation. ++ * ++ * Just serves as a synchronization point on a VM queue. ++ * ++ * Only valid if %DRM_PANTHOR_VM_BIND_ASYNC is set in drm_panthor_vm_bind::flags, ++ * and drm_panthor_vm_bind_op::syncs contains at least one element. ++ */ ++ DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY = 2 << 28, ++}; ++ ++/** ++ * struct drm_panthor_vm_bind_op - VM bind operation ++ */ ++struct drm_panthor_vm_bind_op { ++ /** @flags: Combination of drm_panthor_vm_bind_op_flags flags. */ ++ __u32 flags; ++ ++ /** ++ * @bo_handle: Handle of the buffer object to map. ++ * MBZ for unmap or sync-only operations. ++ */ ++ __u32 bo_handle; ++ ++ /** ++ * @bo_offset: Buffer object offset. ++ * MBZ for unmap or sync-only operations. ++ */ ++ __u64 bo_offset; ++ ++ /** ++ * @va: Virtual address to map/unmap. ++ * MBZ for sync-only operations. ++ */ ++ __u64 va; ++ ++ /** ++ * @size: Size to map/unmap. ++ * MBZ for sync-only operations. ++ */ ++ __u64 size; ++ ++ /** ++ * @syncs: Array of struct drm_panthor_sync_op synchronization ++ * operations. ++ * ++ * This array must be empty if %DRM_PANTHOR_VM_BIND_ASYNC is not set on ++ * the drm_panthor_vm_bind object containing this VM bind operation. ++ * ++ * This array shall not be empty for sync-only operations. ++ */ ++ struct drm_panthor_obj_array syncs; ++ ++}; ++ ++/** ++ * enum drm_panthor_vm_bind_flags - VM bind flags ++ */ ++enum drm_panthor_vm_bind_flags { ++ /** ++ * @DRM_PANTHOR_VM_BIND_ASYNC: VM bind operations are queued to the VM ++ * queue instead of being executed synchronously. ++ */ ++ DRM_PANTHOR_VM_BIND_ASYNC = 1 << 0, ++}; ++ ++/** ++ * struct drm_panthor_vm_bind - Arguments passed to DRM_IOCTL_PANTHOR_VM_BIND ++ */ ++struct drm_panthor_vm_bind { ++ /** @vm_id: VM targeted by the bind request. */ ++ __u32 vm_id; ++ ++ /** @flags: Combination of drm_panthor_vm_bind_flags flags. */ ++ __u32 flags; ++ ++ /** @ops: Array of struct drm_panthor_vm_bind_op bind operations. */ ++ struct drm_panthor_obj_array ops; ++}; ++ ++/** ++ * enum drm_panthor_vm_state - VM states. ++ */ ++enum drm_panthor_vm_state { ++ /** ++ * @DRM_PANTHOR_VM_STATE_USABLE: VM is usable. ++ * ++ * New VM operations will be accepted on this VM. ++ */ ++ DRM_PANTHOR_VM_STATE_USABLE, ++ ++ /** ++ * @DRM_PANTHOR_VM_STATE_UNUSABLE: VM is unusable. ++ * ++ * Something put the VM in an unusable state (like an asynchronous ++ * VM_BIND request failing for any reason). ++ * ++ * Once the VM is in this state, all new MAP operations will be ++ * rejected, and any GPU job targeting this VM will fail. ++ * UNMAP operations are still accepted. ++ * ++ * The only way to recover from an unusable VM is to create a new ++ * VM, and destroy the old one. ++ */ ++ DRM_PANTHOR_VM_STATE_UNUSABLE, ++}; ++ ++/** ++ * struct drm_panthor_vm_get_state - Get VM state. ++ */ ++struct drm_panthor_vm_get_state { ++ /** @vm_id: VM targeted by the get_state request. */ ++ __u32 vm_id; ++ ++ /** ++ * @state: state returned by the driver. ++ * ++ * Must be one of the enum drm_panthor_vm_state values. ++ */ ++ __u32 state; ++}; ++ ++/** ++ * enum drm_panthor_bo_flags - Buffer object flags, passed at creation time. ++ */ ++enum drm_panthor_bo_flags { ++ /** @DRM_PANTHOR_BO_NO_MMAP: The buffer object will never be CPU-mapped in userspace. */ ++ DRM_PANTHOR_BO_NO_MMAP = (1 << 0), ++}; ++ ++/** ++ * struct drm_panthor_bo_create - Arguments passed to DRM_IOCTL_PANTHOR_BO_CREATE. ++ */ ++struct drm_panthor_bo_create { ++ /** ++ * @size: Requested size for the object ++ * ++ * The (page-aligned) allocated size for the object will be returned. ++ */ ++ __u64 size; ++ ++ /** ++ * @flags: Flags. Must be a combination of drm_panthor_bo_flags flags. ++ */ ++ __u32 flags; ++ ++ /** ++ * @exclusive_vm_id: Exclusive VM this buffer object will be mapped to. ++ * ++ * If not zero, the field must refer to a valid VM ID, and implies that: ++ * - the buffer object will only ever be bound to that VM ++ * - cannot be exported as a PRIME fd ++ */ ++ __u32 exclusive_vm_id; ++ ++ /** ++ * @handle: Returned handle for the object. ++ * ++ * Object handles are nonzero. ++ */ ++ __u32 handle; ++ ++ /** @pad: MBZ. */ ++ __u32 pad; ++}; ++ ++/** ++ * struct drm_panthor_bo_mmap_offset - Arguments passed to DRM_IOCTL_PANTHOR_BO_MMAP_OFFSET. ++ */ ++struct drm_panthor_bo_mmap_offset { ++ /** @handle: Handle of the object we want an mmap offset for. */ ++ __u32 handle; ++ ++ /** @pad: MBZ. */ ++ __u32 pad; ++ ++ /** @offset: The fake offset to use for subsequent mmap calls. */ ++ __u64 offset; ++}; ++ ++/** ++ * struct drm_panthor_queue_create - Queue creation arguments. ++ */ ++struct drm_panthor_queue_create { ++ /** ++ * @priority: Defines the priority of queues inside a group. Goes from 0 to 15, ++ * 15 being the highest priority. ++ */ ++ __u8 priority; ++ ++ /** @pad: Padding fields, MBZ. */ ++ __u8 pad[3]; ++ ++ /** @ringbuf_size: Size of the ring buffer to allocate to this queue. */ ++ __u32 ringbuf_size; ++}; ++ ++/** ++ * enum drm_panthor_group_priority - Scheduling group priority ++ */ ++enum drm_panthor_group_priority { ++ /** @PANTHOR_GROUP_PRIORITY_LOW: Low priority group. */ ++ PANTHOR_GROUP_PRIORITY_LOW = 0, ++ ++ /** @PANTHOR_GROUP_PRIORITY_MEDIUM: Medium priority group. */ ++ PANTHOR_GROUP_PRIORITY_MEDIUM, ++ ++ /** @PANTHOR_GROUP_PRIORITY_HIGH: High priority group. */ ++ PANTHOR_GROUP_PRIORITY_HIGH, ++}; ++ ++/** ++ * struct drm_panthor_group_create - Arguments passed to DRM_IOCTL_PANTHOR_GROUP_CREATE ++ */ ++struct drm_panthor_group_create { ++ /** @queues: Array of drm_panthor_queue_create elements. */ ++ struct drm_panthor_obj_array queues; ++ ++ /** ++ * @max_compute_cores: Maximum number of cores that can be used by compute ++ * jobs across CS queues bound to this group. ++ * ++ * Must be less or equal to the number of bits set in @compute_core_mask. ++ */ ++ __u8 max_compute_cores; ++ ++ /** ++ * @max_fragment_cores: Maximum number of cores that can be used by fragment ++ * jobs across CS queues bound to this group. ++ * ++ * Must be less or equal to the number of bits set in @fragment_core_mask. ++ */ ++ __u8 max_fragment_cores; ++ ++ /** ++ * @max_tiler_cores: Maximum number of tilers that can be used by tiler jobs ++ * across CS queues bound to this group. ++ * ++ * Must be less or equal to the number of bits set in @tiler_core_mask. ++ */ ++ __u8 max_tiler_cores; ++ ++ /** @priority: Group priority (see enum drm_panthor_group_priority). */ ++ __u8 priority; ++ ++ /** @pad: Padding field, MBZ. */ ++ __u32 pad; ++ ++ /** ++ * @compute_core_mask: Mask encoding cores that can be used for compute jobs. ++ * ++ * This field must have at least @max_compute_cores bits set. ++ * ++ * The bits set here should also be set in drm_panthor_gpu_info::shader_present. ++ */ ++ __u64 compute_core_mask; ++ ++ /** ++ * @fragment_core_mask: Mask encoding cores that can be used for fragment jobs. ++ * ++ * This field must have at least @max_fragment_cores bits set. ++ * ++ * The bits set here should also be set in drm_panthor_gpu_info::shader_present. ++ */ ++ __u64 fragment_core_mask; ++ ++ /** ++ * @tiler_core_mask: Mask encoding cores that can be used for tiler jobs. ++ * ++ * This field must have at least @max_tiler_cores bits set. ++ * ++ * The bits set here should also be set in drm_panthor_gpu_info::tiler_present. ++ */ ++ __u64 tiler_core_mask; ++ ++ /** ++ * @vm_id: VM ID to bind this group to. ++ * ++ * All submission to queues bound to this group will use this VM. ++ */ ++ __u32 vm_id; ++ ++ /** ++ * @group_handle: Returned group handle. Passed back when submitting jobs or ++ * destroying a group. ++ */ ++ __u32 group_handle; ++}; ++ ++/** ++ * struct drm_panthor_group_destroy - Arguments passed to DRM_IOCTL_PANTHOR_GROUP_DESTROY ++ */ ++struct drm_panthor_group_destroy { ++ /** @group_handle: Group to destroy */ ++ __u32 group_handle; ++ ++ /** @pad: Padding field, MBZ. */ ++ __u32 pad; ++}; ++ ++/** ++ * struct drm_panthor_queue_submit - Job submission arguments. ++ * ++ * This is describing the userspace command stream to call from the kernel ++ * command stream ring-buffer. Queue submission is always part of a group ++ * submission, taking one or more jobs to submit to the underlying queues. ++ */ ++struct drm_panthor_queue_submit { ++ /** @queue_index: Index of the queue inside a group. */ ++ __u32 queue_index; ++ ++ /** ++ * @stream_size: Size of the command stream to execute. ++ * ++ * Must be 64-bit/8-byte aligned (the size of a CS instruction) ++ * ++ * Can be zero if stream_addr is zero too. ++ */ ++ __u32 stream_size; ++ ++ /** ++ * @stream_addr: GPU address of the command stream to execute. ++ * ++ * Must be aligned on 64-byte. ++ * ++ * Can be zero is stream_size is zero too. ++ */ ++ __u64 stream_addr; ++ ++ /** ++ * @latest_flush: FLUSH_ID read at the time the stream was built. ++ * ++ * This allows cache flush elimination for the automatic ++ * flush+invalidate(all) done at submission time, which is needed to ++ * ensure the GPU doesn't get garbage when reading the indirect command ++ * stream buffers. If you want the cache flush to happen ++ * unconditionally, pass a zero here. ++ */ ++ __u32 latest_flush; ++ ++ /** @pad: MBZ. */ ++ __u32 pad; ++ ++ /** @syncs: Array of struct drm_panthor_sync_op sync operations. */ ++ struct drm_panthor_obj_array syncs; ++}; ++ ++/** ++ * struct drm_panthor_group_submit - Arguments passed to DRM_IOCTL_PANTHOR_GROUP_SUBMIT ++ */ ++struct drm_panthor_group_submit { ++ /** @group_handle: Handle of the group to queue jobs to. */ ++ __u32 group_handle; ++ ++ /** @pad: MBZ. */ ++ __u32 pad; ++ ++ /** @queue_submits: Array of drm_panthor_queue_submit objects. */ ++ struct drm_panthor_obj_array queue_submits; ++}; ++ ++/** ++ * enum drm_panthor_group_state_flags - Group state flags ++ */ ++enum drm_panthor_group_state_flags { ++ /** ++ * @DRM_PANTHOR_GROUP_STATE_TIMEDOUT: Group had unfinished jobs. ++ * ++ * When a group ends up with this flag set, no jobs can be submitted to its queues. ++ */ ++ DRM_PANTHOR_GROUP_STATE_TIMEDOUT = 1 << 0, ++ ++ /** ++ * @DRM_PANTHOR_GROUP_STATE_FATAL_FAULT: Group had fatal faults. ++ * ++ * When a group ends up with this flag set, no jobs can be submitted to its queues. ++ */ ++ DRM_PANTHOR_GROUP_STATE_FATAL_FAULT = 1 << 1, ++}; ++ ++/** ++ * struct drm_panthor_group_get_state - Arguments passed to DRM_IOCTL_PANTHOR_GROUP_GET_STATE ++ * ++ * Used to query the state of a group and decide whether a new group should be created to ++ * replace it. ++ */ ++struct drm_panthor_group_get_state { ++ /** @group_handle: Handle of the group to query state on */ ++ __u32 group_handle; ++ ++ /** ++ * @state: Combination of DRM_PANTHOR_GROUP_STATE_* flags encoding the ++ * group state. ++ */ ++ __u32 state; ++ ++ /** @fatal_queues: Bitmask of queues that faced fatal faults. */ ++ __u32 fatal_queues; ++ ++ /** @pad: MBZ */ ++ __u32 pad; ++}; ++ ++/** ++ * struct drm_panthor_tiler_heap_create - Arguments passed to DRM_IOCTL_PANTHOR_TILER_HEAP_CREATE ++ */ ++struct drm_panthor_tiler_heap_create { ++ /** @vm_id: VM ID the tiler heap should be mapped to */ ++ __u32 vm_id; ++ ++ /** @initial_chunk_count: Initial number of chunks to allocate. */ ++ __u32 initial_chunk_count; ++ ++ /** @chunk_size: Chunk size. Must be a power of two at least 256KB large. */ ++ __u32 chunk_size; ++ ++ /** @max_chunks: Maximum number of chunks that can be allocated. */ ++ __u32 max_chunks; ++ ++ /** ++ * @target_in_flight: Maximum number of in-flight render passes. ++ * ++ * If the heap has more than tiler jobs in-flight, the FW will wait for render ++ * passes to finish before queuing new tiler jobs. ++ */ ++ __u32 target_in_flight; ++ ++ /** @handle: Returned heap handle. Passed back to DESTROY_TILER_HEAP. */ ++ __u32 handle; ++ ++ /** @tiler_heap_ctx_gpu_va: Returned heap GPU virtual address returned */ ++ __u64 tiler_heap_ctx_gpu_va; ++ ++ /** ++ * @first_heap_chunk_gpu_va: First heap chunk. ++ * ++ * The tiler heap is formed of heap chunks forming a single-link list. This ++ * is the first element in the list. ++ */ ++ __u64 first_heap_chunk_gpu_va; ++}; ++ ++/** ++ * struct drm_panthor_tiler_heap_destroy - Arguments passed to DRM_IOCTL_PANTHOR_TILER_HEAP_DESTROY ++ */ ++struct drm_panthor_tiler_heap_destroy { ++ /** @handle: Handle of the tiler heap to destroy */ ++ __u32 handle; ++ ++ /** @pad: Padding field, MBZ. */ ++ __u32 pad; ++}; ++ ++#if defined(__cplusplus) ++} ++#endif ++ ++#endif /* _PANTHOR_DRM_H_ */ +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:16 +0100 +Subject: drm/panthor: Add GPU register definitions + +Those are the registers directly accessible through the MMIO range. + +FW registers are exposed in panthor_fw.h. + +v6: +- Add Maxime's and Heiko's acks + +v4: +- Add the CORE_FEATURES register (needed for GPU variants) +- Add Steve's R-b + +v3: +- Add macros to extract GPU ID info +- Formatting changes +- Remove AS_TRANSCFG_ADRMODE_LEGACY - it doesn't exist post-CSF +- Remove CSF_GPU_LATEST_FLUSH_ID_DEFAULT +- Add GPU_L2_FEATURES_LINE_SIZE for extracting the GPU cache line size + +Co-developed-by: Steven Price +Signed-off-by: Steven Price +Signed-off-by: Boris Brezillon +Acked-by: Steven Price # MIT+GPL2 relicensing,Arm +Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro +Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora +Reviewed-by: Steven Price +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + drivers/gpu/drm/panthor/panthor_regs.h | 239 ++++++++++ + 1 file changed, 239 insertions(+) + +diff --git a/drivers/gpu/drm/panthor/panthor_regs.h b/drivers/gpu/drm/panthor/panthor_regs.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_regs.h +@@ -0,0 +1,239 @@ ++/* SPDX-License-Identifier: GPL-2.0 or MIT */ ++/* Copyright 2018 Marty E. Plummer */ ++/* Copyright 2019 Linaro, Ltd, Rob Herring */ ++/* Copyright 2023 Collabora ltd. */ ++/* ++ * Register definitions based on mali_kbase_gpu_regmap.h and ++ * mali_kbase_gpu_regmap_csf.h ++ * (C) COPYRIGHT 2010-2022 ARM Limited. All rights reserved. ++ */ ++#ifndef __PANTHOR_REGS_H__ ++#define __PANTHOR_REGS_H__ ++ ++#define GPU_ID 0x0 ++#define GPU_ARCH_MAJOR(x) ((x) >> 28) ++#define GPU_ARCH_MINOR(x) (((x) & GENMASK(27, 24)) >> 24) ++#define GPU_ARCH_REV(x) (((x) & GENMASK(23, 20)) >> 20) ++#define GPU_PROD_MAJOR(x) (((x) & GENMASK(19, 16)) >> 16) ++#define GPU_VER_MAJOR(x) (((x) & GENMASK(15, 12)) >> 12) ++#define GPU_VER_MINOR(x) (((x) & GENMASK(11, 4)) >> 4) ++#define GPU_VER_STATUS(x) ((x) & GENMASK(3, 0)) ++ ++#define GPU_L2_FEATURES 0x4 ++#define GPU_L2_FEATURES_LINE_SIZE(x) (1 << ((x) & GENMASK(7, 0))) ++ ++#define GPU_CORE_FEATURES 0x8 ++ ++#define GPU_TILER_FEATURES 0xC ++#define GPU_MEM_FEATURES 0x10 ++#define GROUPS_L2_COHERENT BIT(0) ++ ++#define GPU_MMU_FEATURES 0x14 ++#define GPU_MMU_FEATURES_VA_BITS(x) ((x) & GENMASK(7, 0)) ++#define GPU_MMU_FEATURES_PA_BITS(x) (((x) >> 8) & GENMASK(7, 0)) ++#define GPU_AS_PRESENT 0x18 ++#define GPU_CSF_ID 0x1C ++ ++#define GPU_INT_RAWSTAT 0x20 ++#define GPU_INT_CLEAR 0x24 ++#define GPU_INT_MASK 0x28 ++#define GPU_INT_STAT 0x2c ++#define GPU_IRQ_FAULT BIT(0) ++#define GPU_IRQ_PROTM_FAULT BIT(1) ++#define GPU_IRQ_RESET_COMPLETED BIT(8) ++#define GPU_IRQ_POWER_CHANGED BIT(9) ++#define GPU_IRQ_POWER_CHANGED_ALL BIT(10) ++#define GPU_IRQ_CLEAN_CACHES_COMPLETED BIT(17) ++#define GPU_IRQ_DOORBELL_MIRROR BIT(18) ++#define GPU_IRQ_MCU_STATUS_CHANGED BIT(19) ++#define GPU_CMD 0x30 ++#define GPU_CMD_DEF(type, payload) ((type) | ((payload) << 8)) ++#define GPU_SOFT_RESET GPU_CMD_DEF(1, 1) ++#define GPU_HARD_RESET GPU_CMD_DEF(1, 2) ++#define CACHE_CLEAN BIT(0) ++#define CACHE_INV BIT(1) ++#define GPU_FLUSH_CACHES(l2, lsc, oth) \ ++ GPU_CMD_DEF(4, ((l2) << 0) | ((lsc) << 4) | ((oth) << 8)) ++ ++#define GPU_STATUS 0x34 ++#define GPU_STATUS_ACTIVE BIT(0) ++#define GPU_STATUS_PWR_ACTIVE BIT(1) ++#define GPU_STATUS_PAGE_FAULT BIT(4) ++#define GPU_STATUS_PROTM_ACTIVE BIT(7) ++#define GPU_STATUS_DBG_ENABLED BIT(8) ++ ++#define GPU_FAULT_STATUS 0x3C ++#define GPU_FAULT_ADDR_LO 0x40 ++#define GPU_FAULT_ADDR_HI 0x44 ++ ++#define GPU_PWR_KEY 0x50 ++#define GPU_PWR_KEY_UNLOCK 0x2968A819 ++#define GPU_PWR_OVERRIDE0 0x54 ++#define GPU_PWR_OVERRIDE1 0x58 ++ ++#define GPU_TIMESTAMP_OFFSET_LO 0x88 ++#define GPU_TIMESTAMP_OFFSET_HI 0x8C ++#define GPU_CYCLE_COUNT_LO 0x90 ++#define GPU_CYCLE_COUNT_HI 0x94 ++#define GPU_TIMESTAMP_LO 0x98 ++#define GPU_TIMESTAMP_HI 0x9C ++ ++#define GPU_THREAD_MAX_THREADS 0xA0 ++#define GPU_THREAD_MAX_WORKGROUP_SIZE 0xA4 ++#define GPU_THREAD_MAX_BARRIER_SIZE 0xA8 ++#define GPU_THREAD_FEATURES 0xAC ++ ++#define GPU_TEXTURE_FEATURES(n) (0xB0 + ((n) * 4)) ++ ++#define GPU_SHADER_PRESENT_LO 0x100 ++#define GPU_SHADER_PRESENT_HI 0x104 ++#define GPU_TILER_PRESENT_LO 0x110 ++#define GPU_TILER_PRESENT_HI 0x114 ++#define GPU_L2_PRESENT_LO 0x120 ++#define GPU_L2_PRESENT_HI 0x124 ++ ++#define SHADER_READY_LO 0x140 ++#define SHADER_READY_HI 0x144 ++#define TILER_READY_LO 0x150 ++#define TILER_READY_HI 0x154 ++#define L2_READY_LO 0x160 ++#define L2_READY_HI 0x164 ++ ++#define SHADER_PWRON_LO 0x180 ++#define SHADER_PWRON_HI 0x184 ++#define TILER_PWRON_LO 0x190 ++#define TILER_PWRON_HI 0x194 ++#define L2_PWRON_LO 0x1A0 ++#define L2_PWRON_HI 0x1A4 ++ ++#define SHADER_PWROFF_LO 0x1C0 ++#define SHADER_PWROFF_HI 0x1C4 ++#define TILER_PWROFF_LO 0x1D0 ++#define TILER_PWROFF_HI 0x1D4 ++#define L2_PWROFF_LO 0x1E0 ++#define L2_PWROFF_HI 0x1E4 ++ ++#define SHADER_PWRTRANS_LO 0x200 ++#define SHADER_PWRTRANS_HI 0x204 ++#define TILER_PWRTRANS_LO 0x210 ++#define TILER_PWRTRANS_HI 0x214 ++#define L2_PWRTRANS_LO 0x220 ++#define L2_PWRTRANS_HI 0x224 ++ ++#define SHADER_PWRACTIVE_LO 0x240 ++#define SHADER_PWRACTIVE_HI 0x244 ++#define TILER_PWRACTIVE_LO 0x250 ++#define TILER_PWRACTIVE_HI 0x254 ++#define L2_PWRACTIVE_LO 0x260 ++#define L2_PWRACTIVE_HI 0x264 ++ ++#define GPU_REVID 0x280 ++ ++#define GPU_COHERENCY_FEATURES 0x300 ++#define GPU_COHERENCY_PROT_BIT(name) BIT(GPU_COHERENCY_ ## name) ++ ++#define GPU_COHERENCY_PROTOCOL 0x304 ++#define GPU_COHERENCY_ACE 0 ++#define GPU_COHERENCY_ACE_LITE 1 ++#define GPU_COHERENCY_NONE 31 ++ ++#define MCU_CONTROL 0x700 ++#define MCU_CONTROL_ENABLE 1 ++#define MCU_CONTROL_AUTO 2 ++#define MCU_CONTROL_DISABLE 0 ++ ++#define MCU_STATUS 0x704 ++#define MCU_STATUS_DISABLED 0 ++#define MCU_STATUS_ENABLED 1 ++#define MCU_STATUS_HALT 2 ++#define MCU_STATUS_FATAL 3 ++ ++/* Job Control regs */ ++#define JOB_INT_RAWSTAT 0x1000 ++#define JOB_INT_CLEAR 0x1004 ++#define JOB_INT_MASK 0x1008 ++#define JOB_INT_STAT 0x100c ++#define JOB_INT_GLOBAL_IF BIT(31) ++#define JOB_INT_CSG_IF(x) BIT(x) ++ ++/* MMU regs */ ++#define MMU_INT_RAWSTAT 0x2000 ++#define MMU_INT_CLEAR 0x2004 ++#define MMU_INT_MASK 0x2008 ++#define MMU_INT_STAT 0x200c ++ ++/* AS_COMMAND register commands */ ++ ++#define MMU_BASE 0x2400 ++#define MMU_AS_SHIFT 6 ++#define MMU_AS(as) (MMU_BASE + ((as) << MMU_AS_SHIFT)) ++ ++#define AS_TRANSTAB_LO(as) (MMU_AS(as) + 0x0) ++#define AS_TRANSTAB_HI(as) (MMU_AS(as) + 0x4) ++#define AS_MEMATTR_LO(as) (MMU_AS(as) + 0x8) ++#define AS_MEMATTR_HI(as) (MMU_AS(as) + 0xC) ++#define AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL (2 << 2) ++#define AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r) ((3 << 2) | \ ++ ((w) ? BIT(0) : 0) | \ ++ ((r) ? BIT(1) : 0)) ++#define AS_MEMATTR_AARCH64_SH_MIDGARD_INNER (0 << 4) ++#define AS_MEMATTR_AARCH64_SH_CPU_INNER (1 << 4) ++#define AS_MEMATTR_AARCH64_SH_CPU_INNER_SHADER_COH (2 << 4) ++#define AS_MEMATTR_AARCH64_SHARED (0 << 6) ++#define AS_MEMATTR_AARCH64_INNER_OUTER_NC (1 << 6) ++#define AS_MEMATTR_AARCH64_INNER_OUTER_WB (2 << 6) ++#define AS_MEMATTR_AARCH64_FAULT (3 << 6) ++#define AS_LOCKADDR_LO(as) (MMU_AS(as) + 0x10) ++#define AS_LOCKADDR_HI(as) (MMU_AS(as) + 0x14) ++#define AS_COMMAND(as) (MMU_AS(as) + 0x18) ++#define AS_COMMAND_NOP 0 ++#define AS_COMMAND_UPDATE 1 ++#define AS_COMMAND_LOCK 2 ++#define AS_COMMAND_UNLOCK 3 ++#define AS_COMMAND_FLUSH_PT 4 ++#define AS_COMMAND_FLUSH_MEM 5 ++#define AS_LOCK_REGION_MIN_SIZE (1ULL << 15) ++#define AS_FAULTSTATUS(as) (MMU_AS(as) + 0x1C) ++#define AS_FAULTSTATUS_ACCESS_TYPE_MASK (0x3 << 8) ++#define AS_FAULTSTATUS_ACCESS_TYPE_ATOMIC (0x0 << 8) ++#define AS_FAULTSTATUS_ACCESS_TYPE_EX (0x1 << 8) ++#define AS_FAULTSTATUS_ACCESS_TYPE_READ (0x2 << 8) ++#define AS_FAULTSTATUS_ACCESS_TYPE_WRITE (0x3 << 8) ++#define AS_FAULTADDRESS_LO(as) (MMU_AS(as) + 0x20) ++#define AS_FAULTADDRESS_HI(as) (MMU_AS(as) + 0x24) ++#define AS_STATUS(as) (MMU_AS(as) + 0x28) ++#define AS_STATUS_AS_ACTIVE BIT(0) ++#define AS_TRANSCFG_LO(as) (MMU_AS(as) + 0x30) ++#define AS_TRANSCFG_HI(as) (MMU_AS(as) + 0x34) ++#define AS_TRANSCFG_ADRMODE_UNMAPPED (1 << 0) ++#define AS_TRANSCFG_ADRMODE_IDENTITY (2 << 0) ++#define AS_TRANSCFG_ADRMODE_AARCH64_4K (6 << 0) ++#define AS_TRANSCFG_ADRMODE_AARCH64_64K (8 << 0) ++#define AS_TRANSCFG_INA_BITS(x) ((x) << 6) ++#define AS_TRANSCFG_OUTA_BITS(x) ((x) << 14) ++#define AS_TRANSCFG_SL_CONCAT BIT(22) ++#define AS_TRANSCFG_PTW_MEMATTR_NC (1 << 24) ++#define AS_TRANSCFG_PTW_MEMATTR_WB (2 << 24) ++#define AS_TRANSCFG_PTW_SH_NS (0 << 28) ++#define AS_TRANSCFG_PTW_SH_OS (2 << 28) ++#define AS_TRANSCFG_PTW_SH_IS (3 << 28) ++#define AS_TRANSCFG_PTW_RA BIT(30) ++#define AS_TRANSCFG_DISABLE_HIER_AP BIT(33) ++#define AS_TRANSCFG_DISABLE_AF_FAULT BIT(34) ++#define AS_TRANSCFG_WXN BIT(35) ++#define AS_TRANSCFG_XREADABLE BIT(36) ++#define AS_FAULTEXTRA_LO(as) (MMU_AS(as) + 0x38) ++#define AS_FAULTEXTRA_HI(as) (MMU_AS(as) + 0x3C) ++ ++#define CSF_GPU_LATEST_FLUSH_ID 0x10000 ++ ++#define CSF_DOORBELL(i) (0x80000 + ((i) * 0x10000)) ++#define CSF_GLB_DOORBELL_ID 0 ++ ++#define gpu_write(dev, reg, data) \ ++ writel(data, (dev)->iomem + (reg)) ++ ++#define gpu_read(dev, reg) \ ++ readl((dev)->iomem + (reg)) ++ ++#endif +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:17 +0100 +Subject: drm/panthor: Add the device logical block + +The panthor driver is designed in a modular way, where each logical +block is dealing with a specific HW-block or software feature. In order +for those blocks to communicate with each other, we need a central +panthor_device collecting all the blocks, and exposing some common +features, like interrupt handling, power management, reset, ... + +This what this panthor_device logical block is about. + +v6: +- Add Maxime's and Heiko's acks +- Keep header inclusion alphabetically ordered + +v5: +- Suspend the MMU/GPU blocks if panthor_fw_resume() fails in + panthor_device_resume() +- Move the pm_runtime_use_autosuspend() call before drm_dev_register() +- Add Liviu's R-b + +v4: +- Check drmm_mutex_init() return code +- Fix panthor_device_reset_work() out path +- Fix the race in the unplug logic +- Fix typos +- Unplug blocks when something fails in panthor_device_init() +- Add Steve's R-b + +v3: +- Add acks for the MIT+GPL2 relicensing +- Fix 32-bit support +- Shorten the sections protected by panthor_device::pm::mmio_lock to fix + lock ordering issues. +- Rename panthor_device::pm::lock into panthor_device::pm::mmio_lock to + better reflect what this lock is protecting +- Use dev_err_probe() +- Make sure we call drm_dev_exit() when something fails half-way in + panthor_device_reset_work() +- Replace CSF_GPU_LATEST_FLUSH_ID_DEFAULT with a constant '1' and a + comment to explain. Also remove setting the dummy flush ID on suspend. +- Remove drm_WARN_ON() in panthor_exception_name() +- Check pirq->suspended in panthor_xxx_irq_raw_handler() + +Co-developed-by: Steven Price +Signed-off-by: Steven Price +Signed-off-by: Boris Brezillon +Acked-by: Steven Price # MIT+GPL2 relicensing,Arm +Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro +Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora +Reviewed-by: Steven Price +Reviewed-by: Liviu Dudau +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + drivers/gpu/drm/panthor/panthor_device.c | 549 ++++++++++ + drivers/gpu/drm/panthor/panthor_device.h | 394 +++++++ + 2 files changed, 943 insertions(+) + +diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_device.c +@@ -0,0 +1,549 @@ ++// SPDX-License-Identifier: GPL-2.0 or MIT ++/* Copyright 2018 Marty E. Plummer */ ++/* Copyright 2019 Linaro, Ltd, Rob Herring */ ++/* Copyright 2023 Collabora ltd. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "panthor_devfreq.h" ++#include "panthor_device.h" ++#include "panthor_fw.h" ++#include "panthor_gpu.h" ++#include "panthor_mmu.h" ++#include "panthor_regs.h" ++#include "panthor_sched.h" ++ ++static int panthor_clk_init(struct panthor_device *ptdev) ++{ ++ ptdev->clks.core = devm_clk_get(ptdev->base.dev, NULL); ++ if (IS_ERR(ptdev->clks.core)) ++ return dev_err_probe(ptdev->base.dev, ++ PTR_ERR(ptdev->clks.core), ++ "get 'core' clock failed"); ++ ++ ptdev->clks.stacks = devm_clk_get_optional(ptdev->base.dev, "stacks"); ++ if (IS_ERR(ptdev->clks.stacks)) ++ return dev_err_probe(ptdev->base.dev, ++ PTR_ERR(ptdev->clks.stacks), ++ "get 'stacks' clock failed"); ++ ++ ptdev->clks.coregroup = devm_clk_get_optional(ptdev->base.dev, "coregroup"); ++ if (IS_ERR(ptdev->clks.coregroup)) ++ return dev_err_probe(ptdev->base.dev, ++ PTR_ERR(ptdev->clks.coregroup), ++ "get 'coregroup' clock failed"); ++ ++ drm_info(&ptdev->base, "clock rate = %lu\n", clk_get_rate(ptdev->clks.core)); ++ return 0; ++} ++ ++void panthor_device_unplug(struct panthor_device *ptdev) ++{ ++ /* This function can be called from two different path: the reset work ++ * and the platform device remove callback. drm_dev_unplug() doesn't ++ * deal with concurrent callers, so we have to protect drm_dev_unplug() ++ * calls with our own lock, and bail out if the device is already ++ * unplugged. ++ */ ++ mutex_lock(&ptdev->unplug.lock); ++ if (drm_dev_is_unplugged(&ptdev->base)) { ++ /* Someone beat us, release the lock and wait for the unplug ++ * operation to be reported as done. ++ **/ ++ mutex_unlock(&ptdev->unplug.lock); ++ wait_for_completion(&ptdev->unplug.done); ++ return; ++ } ++ ++ /* Call drm_dev_unplug() so any access to HW blocks happening after ++ * that point get rejected. ++ */ ++ drm_dev_unplug(&ptdev->base); ++ ++ /* We do the rest of the unplug with the unplug lock released, ++ * future callers will wait on ptdev->unplug.done anyway. ++ */ ++ mutex_unlock(&ptdev->unplug.lock); ++ ++ drm_WARN_ON(&ptdev->base, pm_runtime_get_sync(ptdev->base.dev) < 0); ++ ++ /* Now, try to cleanly shutdown the GPU before the device resources ++ * get reclaimed. ++ */ ++ panthor_sched_unplug(ptdev); ++ panthor_fw_unplug(ptdev); ++ panthor_mmu_unplug(ptdev); ++ panthor_gpu_unplug(ptdev); ++ ++ pm_runtime_dont_use_autosuspend(ptdev->base.dev); ++ pm_runtime_put_sync_suspend(ptdev->base.dev); ++ ++ /* Report the unplug operation as done to unblock concurrent ++ * panthor_device_unplug() callers. ++ */ ++ complete_all(&ptdev->unplug.done); ++} ++ ++static void panthor_device_reset_cleanup(struct drm_device *ddev, void *data) ++{ ++ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); ++ ++ cancel_work_sync(&ptdev->reset.work); ++ destroy_workqueue(ptdev->reset.wq); ++} ++ ++static void panthor_device_reset_work(struct work_struct *work) ++{ ++ struct panthor_device *ptdev = container_of(work, struct panthor_device, reset.work); ++ int ret = 0, cookie; ++ ++ if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_ACTIVE) { ++ /* ++ * No need for a reset as the device has been (or will be) ++ * powered down ++ */ ++ atomic_set(&ptdev->reset.pending, 0); ++ return; ++ } ++ ++ if (!drm_dev_enter(&ptdev->base, &cookie)) ++ return; ++ ++ panthor_sched_pre_reset(ptdev); ++ panthor_fw_pre_reset(ptdev, true); ++ panthor_mmu_pre_reset(ptdev); ++ panthor_gpu_soft_reset(ptdev); ++ panthor_gpu_l2_power_on(ptdev); ++ panthor_mmu_post_reset(ptdev); ++ ret = panthor_fw_post_reset(ptdev); ++ if (ret) ++ goto out_dev_exit; ++ ++ atomic_set(&ptdev->reset.pending, 0); ++ panthor_sched_post_reset(ptdev); ++ ++out_dev_exit: ++ drm_dev_exit(cookie); ++ ++ if (ret) { ++ panthor_device_unplug(ptdev); ++ drm_err(&ptdev->base, "Failed to boot MCU after reset, making device unusable."); ++ } ++} ++ ++static bool panthor_device_is_initialized(struct panthor_device *ptdev) ++{ ++ return !!ptdev->scheduler; ++} ++ ++static void panthor_device_free_page(struct drm_device *ddev, void *data) ++{ ++ free_page((unsigned long)data); ++} ++ ++int panthor_device_init(struct panthor_device *ptdev) ++{ ++ struct resource *res; ++ struct page *p; ++ int ret; ++ ++ ptdev->coherent = device_get_dma_attr(ptdev->base.dev) == DEV_DMA_COHERENT; ++ ++ init_completion(&ptdev->unplug.done); ++ ret = drmm_mutex_init(&ptdev->base, &ptdev->unplug.lock); ++ if (ret) ++ return ret; ++ ++ ret = drmm_mutex_init(&ptdev->base, &ptdev->pm.mmio_lock); ++ if (ret) ++ return ret; ++ ++ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDED); ++ p = alloc_page(GFP_KERNEL | __GFP_ZERO); ++ if (!p) ++ return -ENOMEM; ++ ++ ptdev->pm.dummy_latest_flush = page_address(p); ++ ret = drmm_add_action_or_reset(&ptdev->base, panthor_device_free_page, ++ ptdev->pm.dummy_latest_flush); ++ if (ret) ++ return ret; ++ ++ /* ++ * Set the dummy page holding the latest flush to 1. This will cause the ++ * flush to avoided as we know it isn't necessary if the submission ++ * happens while the dummy page is mapped. Zero cannot be used because ++ * that means 'always flush'. ++ */ ++ *ptdev->pm.dummy_latest_flush = 1; ++ ++ INIT_WORK(&ptdev->reset.work, panthor_device_reset_work); ++ ptdev->reset.wq = alloc_ordered_workqueue("panthor-reset-wq", 0); ++ if (!ptdev->reset.wq) ++ return -ENOMEM; ++ ++ ret = drmm_add_action_or_reset(&ptdev->base, panthor_device_reset_cleanup, NULL); ++ if (ret) ++ return ret; ++ ++ ret = panthor_clk_init(ptdev); ++ if (ret) ++ return ret; ++ ++ ret = panthor_devfreq_init(ptdev); ++ if (ret) ++ return ret; ++ ++ ptdev->iomem = devm_platform_get_and_ioremap_resource(to_platform_device(ptdev->base.dev), ++ 0, &res); ++ if (IS_ERR(ptdev->iomem)) ++ return PTR_ERR(ptdev->iomem); ++ ++ ptdev->phys_addr = res->start; ++ ++ ret = devm_pm_runtime_enable(ptdev->base.dev); ++ if (ret) ++ return ret; ++ ++ ret = pm_runtime_resume_and_get(ptdev->base.dev); ++ if (ret) ++ return ret; ++ ++ ret = panthor_gpu_init(ptdev); ++ if (ret) ++ goto err_rpm_put; ++ ++ ret = panthor_mmu_init(ptdev); ++ if (ret) ++ goto err_unplug_gpu; ++ ++ ret = panthor_fw_init(ptdev); ++ if (ret) ++ goto err_unplug_mmu; ++ ++ ret = panthor_sched_init(ptdev); ++ if (ret) ++ goto err_unplug_fw; ++ ++ /* ~3 frames */ ++ pm_runtime_set_autosuspend_delay(ptdev->base.dev, 50); ++ pm_runtime_use_autosuspend(ptdev->base.dev); ++ ++ ret = drm_dev_register(&ptdev->base, 0); ++ if (ret) ++ goto err_disable_autosuspend; ++ ++ pm_runtime_put_autosuspend(ptdev->base.dev); ++ return 0; ++ ++err_disable_autosuspend: ++ pm_runtime_dont_use_autosuspend(ptdev->base.dev); ++ panthor_sched_unplug(ptdev); ++ ++err_unplug_fw: ++ panthor_fw_unplug(ptdev); ++ ++err_unplug_mmu: ++ panthor_mmu_unplug(ptdev); ++ ++err_unplug_gpu: ++ panthor_gpu_unplug(ptdev); ++ ++err_rpm_put: ++ pm_runtime_put_sync_suspend(ptdev->base.dev); ++ return ret; ++} ++ ++#define PANTHOR_EXCEPTION(id) \ ++ [DRM_PANTHOR_EXCEPTION_ ## id] = { \ ++ .name = #id, \ ++ } ++ ++struct panthor_exception_info { ++ const char *name; ++}; ++ ++static const struct panthor_exception_info panthor_exception_infos[] = { ++ PANTHOR_EXCEPTION(OK), ++ PANTHOR_EXCEPTION(TERMINATED), ++ PANTHOR_EXCEPTION(KABOOM), ++ PANTHOR_EXCEPTION(EUREKA), ++ PANTHOR_EXCEPTION(ACTIVE), ++ PANTHOR_EXCEPTION(CS_RES_TERM), ++ PANTHOR_EXCEPTION(CS_CONFIG_FAULT), ++ PANTHOR_EXCEPTION(CS_ENDPOINT_FAULT), ++ PANTHOR_EXCEPTION(CS_BUS_FAULT), ++ PANTHOR_EXCEPTION(CS_INSTR_INVALID), ++ PANTHOR_EXCEPTION(CS_CALL_STACK_OVERFLOW), ++ PANTHOR_EXCEPTION(CS_INHERIT_FAULT), ++ PANTHOR_EXCEPTION(INSTR_INVALID_PC), ++ PANTHOR_EXCEPTION(INSTR_INVALID_ENC), ++ PANTHOR_EXCEPTION(INSTR_BARRIER_FAULT), ++ PANTHOR_EXCEPTION(DATA_INVALID_FAULT), ++ PANTHOR_EXCEPTION(TILE_RANGE_FAULT), ++ PANTHOR_EXCEPTION(ADDR_RANGE_FAULT), ++ PANTHOR_EXCEPTION(IMPRECISE_FAULT), ++ PANTHOR_EXCEPTION(OOM), ++ PANTHOR_EXCEPTION(CSF_FW_INTERNAL_ERROR), ++ PANTHOR_EXCEPTION(CSF_RES_EVICTION_TIMEOUT), ++ PANTHOR_EXCEPTION(GPU_BUS_FAULT), ++ PANTHOR_EXCEPTION(GPU_SHAREABILITY_FAULT), ++ PANTHOR_EXCEPTION(SYS_SHAREABILITY_FAULT), ++ PANTHOR_EXCEPTION(GPU_CACHEABILITY_FAULT), ++ PANTHOR_EXCEPTION(TRANSLATION_FAULT_0), ++ PANTHOR_EXCEPTION(TRANSLATION_FAULT_1), ++ PANTHOR_EXCEPTION(TRANSLATION_FAULT_2), ++ PANTHOR_EXCEPTION(TRANSLATION_FAULT_3), ++ PANTHOR_EXCEPTION(TRANSLATION_FAULT_4), ++ PANTHOR_EXCEPTION(PERM_FAULT_0), ++ PANTHOR_EXCEPTION(PERM_FAULT_1), ++ PANTHOR_EXCEPTION(PERM_FAULT_2), ++ PANTHOR_EXCEPTION(PERM_FAULT_3), ++ PANTHOR_EXCEPTION(ACCESS_FLAG_1), ++ PANTHOR_EXCEPTION(ACCESS_FLAG_2), ++ PANTHOR_EXCEPTION(ACCESS_FLAG_3), ++ PANTHOR_EXCEPTION(ADDR_SIZE_FAULT_IN), ++ PANTHOR_EXCEPTION(ADDR_SIZE_FAULT_OUT0), ++ PANTHOR_EXCEPTION(ADDR_SIZE_FAULT_OUT1), ++ PANTHOR_EXCEPTION(ADDR_SIZE_FAULT_OUT2), ++ PANTHOR_EXCEPTION(ADDR_SIZE_FAULT_OUT3), ++ PANTHOR_EXCEPTION(MEM_ATTR_FAULT_0), ++ PANTHOR_EXCEPTION(MEM_ATTR_FAULT_1), ++ PANTHOR_EXCEPTION(MEM_ATTR_FAULT_2), ++ PANTHOR_EXCEPTION(MEM_ATTR_FAULT_3), ++}; ++ ++const char *panthor_exception_name(struct panthor_device *ptdev, u32 exception_code) ++{ ++ if (exception_code >= ARRAY_SIZE(panthor_exception_infos) || ++ !panthor_exception_infos[exception_code].name) ++ return "Unknown exception type"; ++ ++ return panthor_exception_infos[exception_code].name; ++} ++ ++static vm_fault_t panthor_mmio_vm_fault(struct vm_fault *vmf) ++{ ++ struct vm_area_struct *vma = vmf->vma; ++ struct panthor_device *ptdev = vma->vm_private_data; ++ u64 id = (u64)vma->vm_pgoff << PAGE_SHIFT; ++ unsigned long pfn; ++ pgprot_t pgprot; ++ vm_fault_t ret; ++ bool active; ++ int cookie; ++ ++ if (!drm_dev_enter(&ptdev->base, &cookie)) ++ return VM_FAULT_SIGBUS; ++ ++ mutex_lock(&ptdev->pm.mmio_lock); ++ active = atomic_read(&ptdev->pm.state) == PANTHOR_DEVICE_PM_STATE_ACTIVE; ++ ++ switch (panthor_device_mmio_offset(id)) { ++ case DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET: ++ if (active) ++ pfn = __phys_to_pfn(ptdev->phys_addr + CSF_GPU_LATEST_FLUSH_ID); ++ else ++ pfn = virt_to_pfn(ptdev->pm.dummy_latest_flush); ++ break; ++ ++ default: ++ ret = VM_FAULT_SIGBUS; ++ goto out_unlock; ++ } ++ ++ pgprot = vma->vm_page_prot; ++ if (active) ++ pgprot = pgprot_noncached(pgprot); ++ ++ ret = vmf_insert_pfn_prot(vma, vmf->address, pfn, pgprot); ++ ++out_unlock: ++ mutex_unlock(&ptdev->pm.mmio_lock); ++ drm_dev_exit(cookie); ++ return ret; ++} ++ ++static const struct vm_operations_struct panthor_mmio_vm_ops = { ++ .fault = panthor_mmio_vm_fault, ++}; ++ ++int panthor_device_mmap_io(struct panthor_device *ptdev, struct vm_area_struct *vma) ++{ ++ u64 id = (u64)vma->vm_pgoff << PAGE_SHIFT; ++ ++ switch (panthor_device_mmio_offset(id)) { ++ case DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET: ++ if (vma->vm_end - vma->vm_start != PAGE_SIZE || ++ (vma->vm_flags & (VM_WRITE | VM_EXEC))) ++ return -EINVAL; ++ ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ /* Defer actual mapping to the fault handler. */ ++ vma->vm_private_data = ptdev; ++ vma->vm_ops = &panthor_mmio_vm_ops; ++ vm_flags_set(vma, ++ VM_IO | VM_DONTCOPY | VM_DONTEXPAND | ++ VM_NORESERVE | VM_DONTDUMP | VM_PFNMAP); ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++int panthor_device_resume(struct device *dev) ++{ ++ struct panthor_device *ptdev = dev_get_drvdata(dev); ++ int ret, cookie; ++ ++ if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_SUSPENDED) ++ return -EINVAL; ++ ++ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_RESUMING); ++ ++ ret = clk_prepare_enable(ptdev->clks.core); ++ if (ret) ++ goto err_set_suspended; ++ ++ ret = clk_prepare_enable(ptdev->clks.stacks); ++ if (ret) ++ goto err_disable_core_clk; ++ ++ ret = clk_prepare_enable(ptdev->clks.coregroup); ++ if (ret) ++ goto err_disable_stacks_clk; ++ ++ ret = panthor_devfreq_resume(ptdev); ++ if (ret) ++ goto err_disable_coregroup_clk; ++ ++ if (panthor_device_is_initialized(ptdev) && ++ drm_dev_enter(&ptdev->base, &cookie)) { ++ panthor_gpu_resume(ptdev); ++ panthor_mmu_resume(ptdev); ++ ret = drm_WARN_ON(&ptdev->base, panthor_fw_resume(ptdev)); ++ if (!ret) { ++ panthor_sched_resume(ptdev); ++ } else { ++ panthor_mmu_suspend(ptdev); ++ panthor_gpu_suspend(ptdev); ++ } ++ ++ drm_dev_exit(cookie); ++ ++ if (ret) ++ goto err_suspend_devfreq; ++ } ++ ++ if (atomic_read(&ptdev->reset.pending)) ++ queue_work(ptdev->reset.wq, &ptdev->reset.work); ++ ++ /* Clear all IOMEM mappings pointing to this device after we've ++ * resumed. This way the fake mappings pointing to the dummy pages ++ * are removed and the real iomem mapping will be restored on next ++ * access. ++ */ ++ mutex_lock(&ptdev->pm.mmio_lock); ++ unmap_mapping_range(ptdev->base.anon_inode->i_mapping, ++ DRM_PANTHOR_USER_MMIO_OFFSET, 0, 1); ++ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_ACTIVE); ++ mutex_unlock(&ptdev->pm.mmio_lock); ++ return 0; ++ ++err_suspend_devfreq: ++ panthor_devfreq_suspend(ptdev); ++ ++err_disable_coregroup_clk: ++ clk_disable_unprepare(ptdev->clks.coregroup); ++ ++err_disable_stacks_clk: ++ clk_disable_unprepare(ptdev->clks.stacks); ++ ++err_disable_core_clk: ++ clk_disable_unprepare(ptdev->clks.core); ++ ++err_set_suspended: ++ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDED); ++ return ret; ++} ++ ++int panthor_device_suspend(struct device *dev) ++{ ++ struct panthor_device *ptdev = dev_get_drvdata(dev); ++ int ret, cookie; ++ ++ if (atomic_read(&ptdev->pm.state) != PANTHOR_DEVICE_PM_STATE_ACTIVE) ++ return -EINVAL; ++ ++ /* Clear all IOMEM mappings pointing to this device before we ++ * shutdown the power-domain and clocks. Failing to do that results ++ * in external aborts when the process accesses the iomem region. ++ * We change the state and call unmap_mapping_range() with the ++ * mmio_lock held to make sure the vm_fault handler won't set up ++ * invalid mappings. ++ */ ++ mutex_lock(&ptdev->pm.mmio_lock); ++ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDING); ++ unmap_mapping_range(ptdev->base.anon_inode->i_mapping, ++ DRM_PANTHOR_USER_MMIO_OFFSET, 0, 1); ++ mutex_unlock(&ptdev->pm.mmio_lock); ++ ++ if (panthor_device_is_initialized(ptdev) && ++ drm_dev_enter(&ptdev->base, &cookie)) { ++ cancel_work_sync(&ptdev->reset.work); ++ ++ /* We prepare everything as if we were resetting the GPU. ++ * The end of the reset will happen in the resume path though. ++ */ ++ panthor_sched_suspend(ptdev); ++ panthor_fw_suspend(ptdev); ++ panthor_mmu_suspend(ptdev); ++ panthor_gpu_suspend(ptdev); ++ drm_dev_exit(cookie); ++ } ++ ++ ret = panthor_devfreq_suspend(ptdev); ++ if (ret) { ++ if (panthor_device_is_initialized(ptdev) && ++ drm_dev_enter(&ptdev->base, &cookie)) { ++ panthor_gpu_resume(ptdev); ++ panthor_mmu_resume(ptdev); ++ drm_WARN_ON(&ptdev->base, panthor_fw_resume(ptdev)); ++ panthor_sched_resume(ptdev); ++ drm_dev_exit(cookie); ++ } ++ ++ goto err_set_active; ++ } ++ ++ clk_disable_unprepare(ptdev->clks.coregroup); ++ clk_disable_unprepare(ptdev->clks.stacks); ++ clk_disable_unprepare(ptdev->clks.core); ++ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_SUSPENDED); ++ return 0; ++ ++err_set_active: ++ /* If something failed and we have to revert back to an ++ * active state, we also need to clear the MMIO userspace ++ * mappings, so any dumb pages that were mapped while we ++ * were trying to suspend gets invalidated. ++ */ ++ mutex_lock(&ptdev->pm.mmio_lock); ++ atomic_set(&ptdev->pm.state, PANTHOR_DEVICE_PM_STATE_ACTIVE); ++ unmap_mapping_range(ptdev->base.anon_inode->i_mapping, ++ DRM_PANTHOR_USER_MMIO_OFFSET, 0, 1); ++ mutex_unlock(&ptdev->pm.mmio_lock); ++ return ret; ++} ++#endif +diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_device.h +@@ -0,0 +1,394 @@ ++/* SPDX-License-Identifier: GPL-2.0 or MIT */ ++/* Copyright 2018 Marty E. Plummer */ ++/* Copyright 2019 Linaro, Ltd, Rob Herring */ ++/* Copyright 2023 Collabora ltd. */ ++ ++#ifndef __PANTHOR_DEVICE_H__ ++#define __PANTHOR_DEVICE_H__ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++struct panthor_csf; ++struct panthor_csf_ctx; ++struct panthor_device; ++struct panthor_gpu; ++struct panthor_group_pool; ++struct panthor_heap_pool; ++struct panthor_job; ++struct panthor_mmu; ++struct panthor_fw; ++struct panthor_perfcnt; ++struct panthor_vm; ++struct panthor_vm_pool; ++ ++/** ++ * enum panthor_device_pm_state - PM state ++ */ ++enum panthor_device_pm_state { ++ /** @PANTHOR_DEVICE_PM_STATE_SUSPENDED: Device is suspended. */ ++ PANTHOR_DEVICE_PM_STATE_SUSPENDED = 0, ++ ++ /** @PANTHOR_DEVICE_PM_STATE_RESUMING: Device is being resumed. */ ++ PANTHOR_DEVICE_PM_STATE_RESUMING, ++ ++ /** @PANTHOR_DEVICE_PM_STATE_ACTIVE: Device is active. */ ++ PANTHOR_DEVICE_PM_STATE_ACTIVE, ++ ++ /** @PANTHOR_DEVICE_PM_STATE_SUSPENDING: Device is being suspended. */ ++ PANTHOR_DEVICE_PM_STATE_SUSPENDING, ++}; ++ ++/** ++ * struct panthor_irq - IRQ data ++ * ++ * Used to automate IRQ handling for the 3 different IRQs we have in this driver. ++ */ ++struct panthor_irq { ++ /** @ptdev: Panthor device */ ++ struct panthor_device *ptdev; ++ ++ /** @irq: IRQ number. */ ++ int irq; ++ ++ /** @mask: Current mask being applied to xxx_INT_MASK. */ ++ u32 mask; ++ ++ /** @suspended: Set to true when the IRQ is suspended. */ ++ atomic_t suspended; ++}; ++ ++/** ++ * struct panthor_device - Panthor device ++ */ ++struct panthor_device { ++ /** @base: Base drm_device. */ ++ struct drm_device base; ++ ++ /** @phys_addr: Physical address of the iomem region. */ ++ phys_addr_t phys_addr; ++ ++ /** @iomem: CPU mapping of the IOMEM region. */ ++ void __iomem *iomem; ++ ++ /** @clks: GPU clocks. */ ++ struct { ++ /** @core: Core clock. */ ++ struct clk *core; ++ ++ /** @stacks: Stacks clock. This clock is optional. */ ++ struct clk *stacks; ++ ++ /** @coregroup: Core group clock. This clock is optional. */ ++ struct clk *coregroup; ++ } clks; ++ ++ /** @coherent: True if the CPU/GPU are memory coherent. */ ++ bool coherent; ++ ++ /** @gpu_info: GPU information. */ ++ struct drm_panthor_gpu_info gpu_info; ++ ++ /** @csif_info: Command stream interface information. */ ++ struct drm_panthor_csif_info csif_info; ++ ++ /** @gpu: GPU management data. */ ++ struct panthor_gpu *gpu; ++ ++ /** @fw: FW management data. */ ++ struct panthor_fw *fw; ++ ++ /** @mmu: MMU management data. */ ++ struct panthor_mmu *mmu; ++ ++ /** @scheduler: Scheduler management data. */ ++ struct panthor_scheduler *scheduler; ++ ++ /** @devfreq: Device frequency scaling management data. */ ++ struct panthor_devfreq *devfreq; ++ ++ /** @unplug: Device unplug related fields. */ ++ struct { ++ /** @lock: Lock used to serialize unplug operations. */ ++ struct mutex lock; ++ ++ /** ++ * @done: Completion object signaled when the unplug ++ * operation is done. ++ */ ++ struct completion done; ++ } unplug; ++ ++ /** @reset: Reset related fields. */ ++ struct { ++ /** @wq: Ordered worqueud used to schedule reset operations. */ ++ struct workqueue_struct *wq; ++ ++ /** @work: Reset work. */ ++ struct work_struct work; ++ ++ /** @pending: Set to true if a reset is pending. */ ++ atomic_t pending; ++ } reset; ++ ++ /** @pm: Power management related data. */ ++ struct { ++ /** @state: Power state. */ ++ atomic_t state; ++ ++ /** ++ * @mmio_lock: Lock protecting MMIO userspace CPU mappings. ++ * ++ * This is needed to ensure we map the dummy IO pages when ++ * the device is being suspended, and the real IO pages when ++ * the device is being resumed. We can't just do with the ++ * state atomicity to deal with this race. ++ */ ++ struct mutex mmio_lock; ++ ++ /** ++ * @dummy_latest_flush: Dummy LATEST_FLUSH page. ++ * ++ * Used to replace the real LATEST_FLUSH page when the GPU ++ * is suspended. ++ */ ++ u32 *dummy_latest_flush; ++ } pm; ++}; ++ ++/** ++ * struct panthor_file - Panthor file ++ */ ++struct panthor_file { ++ /** @ptdev: Device attached to this file. */ ++ struct panthor_device *ptdev; ++ ++ /** @vms: VM pool attached to this file. */ ++ struct panthor_vm_pool *vms; ++ ++ /** @groups: Scheduling group pool attached to this file. */ ++ struct panthor_group_pool *groups; ++}; ++ ++int panthor_device_init(struct panthor_device *ptdev); ++void panthor_device_unplug(struct panthor_device *ptdev); ++ ++/** ++ * panthor_device_schedule_reset() - Schedules a reset operation ++ */ ++static inline void panthor_device_schedule_reset(struct panthor_device *ptdev) ++{ ++ if (!atomic_cmpxchg(&ptdev->reset.pending, 0, 1) && ++ atomic_read(&ptdev->pm.state) == PANTHOR_DEVICE_PM_STATE_ACTIVE) ++ queue_work(ptdev->reset.wq, &ptdev->reset.work); ++} ++ ++/** ++ * panthor_device_reset_is_pending() - Checks if a reset is pending. ++ * ++ * Return: true if a reset is pending, false otherwise. ++ */ ++static inline bool panthor_device_reset_is_pending(struct panthor_device *ptdev) ++{ ++ return atomic_read(&ptdev->reset.pending) != 0; ++} ++ ++int panthor_device_mmap_io(struct panthor_device *ptdev, ++ struct vm_area_struct *vma); ++ ++int panthor_device_resume(struct device *dev); ++int panthor_device_suspend(struct device *dev); ++ ++enum drm_panthor_exception_type { ++ DRM_PANTHOR_EXCEPTION_OK = 0x00, ++ DRM_PANTHOR_EXCEPTION_TERMINATED = 0x04, ++ DRM_PANTHOR_EXCEPTION_KABOOM = 0x05, ++ DRM_PANTHOR_EXCEPTION_EUREKA = 0x06, ++ DRM_PANTHOR_EXCEPTION_ACTIVE = 0x08, ++ DRM_PANTHOR_EXCEPTION_CS_RES_TERM = 0x0f, ++ DRM_PANTHOR_EXCEPTION_MAX_NON_FAULT = 0x3f, ++ DRM_PANTHOR_EXCEPTION_CS_CONFIG_FAULT = 0x40, ++ DRM_PANTHOR_EXCEPTION_CS_ENDPOINT_FAULT = 0x44, ++ DRM_PANTHOR_EXCEPTION_CS_BUS_FAULT = 0x48, ++ DRM_PANTHOR_EXCEPTION_CS_INSTR_INVALID = 0x49, ++ DRM_PANTHOR_EXCEPTION_CS_CALL_STACK_OVERFLOW = 0x4a, ++ DRM_PANTHOR_EXCEPTION_CS_INHERIT_FAULT = 0x4b, ++ DRM_PANTHOR_EXCEPTION_INSTR_INVALID_PC = 0x50, ++ DRM_PANTHOR_EXCEPTION_INSTR_INVALID_ENC = 0x51, ++ DRM_PANTHOR_EXCEPTION_INSTR_BARRIER_FAULT = 0x55, ++ DRM_PANTHOR_EXCEPTION_DATA_INVALID_FAULT = 0x58, ++ DRM_PANTHOR_EXCEPTION_TILE_RANGE_FAULT = 0x59, ++ DRM_PANTHOR_EXCEPTION_ADDR_RANGE_FAULT = 0x5a, ++ DRM_PANTHOR_EXCEPTION_IMPRECISE_FAULT = 0x5b, ++ DRM_PANTHOR_EXCEPTION_OOM = 0x60, ++ DRM_PANTHOR_EXCEPTION_CSF_FW_INTERNAL_ERROR = 0x68, ++ DRM_PANTHOR_EXCEPTION_CSF_RES_EVICTION_TIMEOUT = 0x69, ++ DRM_PANTHOR_EXCEPTION_GPU_BUS_FAULT = 0x80, ++ DRM_PANTHOR_EXCEPTION_GPU_SHAREABILITY_FAULT = 0x88, ++ DRM_PANTHOR_EXCEPTION_SYS_SHAREABILITY_FAULT = 0x89, ++ DRM_PANTHOR_EXCEPTION_GPU_CACHEABILITY_FAULT = 0x8a, ++ DRM_PANTHOR_EXCEPTION_TRANSLATION_FAULT_0 = 0xc0, ++ DRM_PANTHOR_EXCEPTION_TRANSLATION_FAULT_1 = 0xc1, ++ DRM_PANTHOR_EXCEPTION_TRANSLATION_FAULT_2 = 0xc2, ++ DRM_PANTHOR_EXCEPTION_TRANSLATION_FAULT_3 = 0xc3, ++ DRM_PANTHOR_EXCEPTION_TRANSLATION_FAULT_4 = 0xc4, ++ DRM_PANTHOR_EXCEPTION_PERM_FAULT_0 = 0xc8, ++ DRM_PANTHOR_EXCEPTION_PERM_FAULT_1 = 0xc9, ++ DRM_PANTHOR_EXCEPTION_PERM_FAULT_2 = 0xca, ++ DRM_PANTHOR_EXCEPTION_PERM_FAULT_3 = 0xcb, ++ DRM_PANTHOR_EXCEPTION_ACCESS_FLAG_1 = 0xd9, ++ DRM_PANTHOR_EXCEPTION_ACCESS_FLAG_2 = 0xda, ++ DRM_PANTHOR_EXCEPTION_ACCESS_FLAG_3 = 0xdb, ++ DRM_PANTHOR_EXCEPTION_ADDR_SIZE_FAULT_IN = 0xe0, ++ DRM_PANTHOR_EXCEPTION_ADDR_SIZE_FAULT_OUT0 = 0xe4, ++ DRM_PANTHOR_EXCEPTION_ADDR_SIZE_FAULT_OUT1 = 0xe5, ++ DRM_PANTHOR_EXCEPTION_ADDR_SIZE_FAULT_OUT2 = 0xe6, ++ DRM_PANTHOR_EXCEPTION_ADDR_SIZE_FAULT_OUT3 = 0xe7, ++ DRM_PANTHOR_EXCEPTION_MEM_ATTR_FAULT_0 = 0xe8, ++ DRM_PANTHOR_EXCEPTION_MEM_ATTR_FAULT_1 = 0xe9, ++ DRM_PANTHOR_EXCEPTION_MEM_ATTR_FAULT_2 = 0xea, ++ DRM_PANTHOR_EXCEPTION_MEM_ATTR_FAULT_3 = 0xeb, ++}; ++ ++/** ++ * panthor_exception_is_fault() - Checks if an exception is a fault. ++ * ++ * Return: true if the exception is a fault, false otherwise. ++ */ ++static inline bool ++panthor_exception_is_fault(u32 exception_code) ++{ ++ return exception_code > DRM_PANTHOR_EXCEPTION_MAX_NON_FAULT; ++} ++ ++const char *panthor_exception_name(struct panthor_device *ptdev, ++ u32 exception_code); ++ ++/** ++ * PANTHOR_IRQ_HANDLER() - Define interrupt handlers and the interrupt ++ * registration function. ++ * ++ * The boiler-plate to gracefully deal with shared interrupts is ++ * auto-generated. All you have to do is call PANTHOR_IRQ_HANDLER() ++ * just after the actual handler. The handler prototype is: ++ * ++ * void (*handler)(struct panthor_device *, u32 status); ++ */ ++#define PANTHOR_IRQ_HANDLER(__name, __reg_prefix, __handler) \ ++static irqreturn_t panthor_ ## __name ## _irq_raw_handler(int irq, void *data) \ ++{ \ ++ struct panthor_irq *pirq = data; \ ++ struct panthor_device *ptdev = pirq->ptdev; \ ++ \ ++ if (atomic_read(&pirq->suspended)) \ ++ return IRQ_NONE; \ ++ if (!gpu_read(ptdev, __reg_prefix ## _INT_STAT)) \ ++ return IRQ_NONE; \ ++ \ ++ gpu_write(ptdev, __reg_prefix ## _INT_MASK, 0); \ ++ return IRQ_WAKE_THREAD; \ ++} \ ++ \ ++static irqreturn_t panthor_ ## __name ## _irq_threaded_handler(int irq, void *data) \ ++{ \ ++ struct panthor_irq *pirq = data; \ ++ struct panthor_device *ptdev = pirq->ptdev; \ ++ irqreturn_t ret = IRQ_NONE; \ ++ \ ++ while (true) { \ ++ u32 status = gpu_read(ptdev, __reg_prefix ## _INT_RAWSTAT) & pirq->mask; \ ++ \ ++ if (!status) \ ++ break; \ ++ \ ++ gpu_write(ptdev, __reg_prefix ## _INT_CLEAR, status); \ ++ \ ++ __handler(ptdev, status); \ ++ ret = IRQ_HANDLED; \ ++ } \ ++ \ ++ if (!atomic_read(&pirq->suspended)) \ ++ gpu_write(ptdev, __reg_prefix ## _INT_MASK, pirq->mask); \ ++ \ ++ return ret; \ ++} \ ++ \ ++static inline void panthor_ ## __name ## _irq_suspend(struct panthor_irq *pirq) \ ++{ \ ++ int cookie; \ ++ \ ++ atomic_set(&pirq->suspended, true); \ ++ \ ++ if (drm_dev_enter(&pirq->ptdev->base, &cookie)) { \ ++ gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, 0); \ ++ synchronize_irq(pirq->irq); \ ++ drm_dev_exit(cookie); \ ++ } \ ++ \ ++ pirq->mask = 0; \ ++} \ ++ \ ++static inline void panthor_ ## __name ## _irq_resume(struct panthor_irq *pirq, u32 mask) \ ++{ \ ++ int cookie; \ ++ \ ++ atomic_set(&pirq->suspended, false); \ ++ pirq->mask = mask; \ ++ \ ++ if (drm_dev_enter(&pirq->ptdev->base, &cookie)) { \ ++ gpu_write(pirq->ptdev, __reg_prefix ## _INT_CLEAR, mask); \ ++ gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, mask); \ ++ drm_dev_exit(cookie); \ ++ } \ ++} \ ++ \ ++static int panthor_request_ ## __name ## _irq(struct panthor_device *ptdev, \ ++ struct panthor_irq *pirq, \ ++ int irq, u32 mask) \ ++{ \ ++ pirq->ptdev = ptdev; \ ++ pirq->irq = irq; \ ++ panthor_ ## __name ## _irq_resume(pirq, mask); \ ++ \ ++ return devm_request_threaded_irq(ptdev->base.dev, irq, \ ++ panthor_ ## __name ## _irq_raw_handler, \ ++ panthor_ ## __name ## _irq_threaded_handler, \ ++ IRQF_SHARED, KBUILD_MODNAME "-" # __name, \ ++ pirq); \ ++} ++ ++/** ++ * panthor_device_mmio_offset() - Turn a user MMIO offset into a kernel one ++ * @offset: Offset to convert. ++ * ++ * With 32-bit systems being limited by the 32-bit representation of mmap2's ++ * pgoffset field, we need to make the MMIO offset arch specific. This function ++ * converts a user MMIO offset into something the kernel driver understands. ++ * ++ * If the kernel and userspace architecture match, the offset is unchanged. If ++ * the kernel is 64-bit and userspace is 32-bit, the offset is adjusted to match ++ * 64-bit offsets. 32-bit kernel with 64-bit userspace is impossible. ++ * ++ * Return: Adjusted offset. ++ */ ++static inline u64 panthor_device_mmio_offset(u64 offset) ++{ ++#ifdef CONFIG_ARM64 ++ if (test_tsk_thread_flag(current, TIF_32BIT)) ++ offset += DRM_PANTHOR_USER_MMIO_OFFSET_64BIT - DRM_PANTHOR_USER_MMIO_OFFSET_32BIT; ++#endif ++ ++ return offset; ++} ++ ++extern struct workqueue_struct *panthor_cleanup_wq; ++ ++#endif +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:18 +0100 +Subject: drm/panthor: Add the GPU logical block + +Handles everything that's not related to the FW, the MMU or the +scheduler. This is the block dealing with the GPU property retrieval, +the GPU block power on/off logic, and some global operations, like +global cache flushing. + +v6: +- Add Maxime's and Heiko's acks + +v5: +- Fix GPU_MODEL() kernel doc +- Fix test in panthor_gpu_block_power_off() +- Add Steve's R-b + +v4: +- Expose CORE_FEATURES through DEV_QUERY + +v3: +- Add acks for the MIT/GPL2 relicensing +- Use macros to extract GPU ID info +- Make sure we reset clear pending_reqs bits when wait_event_timeout() + times out but the corresponding bit is cleared in GPU_INT_RAWSTAT + (can happen if the IRQ is masked or HW takes to long to call the IRQ + handler) +- GPU_MODEL now takes separate arch and product majors to be more + readable. +- Drop GPU_IRQ_MCU_STATUS_CHANGED from interrupt mask. +- Handle GPU_IRQ_PROTM_FAULT correctly (don't output registers that are + not updated for protected interrupts). +- Minor code tidy ups + +Cc: Alexey Sheplyakov # MIT+GPL2 relicensing +Co-developed-by: Steven Price +Signed-off-by: Steven Price +Signed-off-by: Boris Brezillon +Acked-by: Steven Price # MIT+GPL2 relicensing,Arm +Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro +Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora +Reviewed-by: Steven Price +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + drivers/gpu/drm/panthor/panthor_gpu.c | 482 ++++++++++ + drivers/gpu/drm/panthor/panthor_gpu.h | 52 + + 2 files changed, 534 insertions(+) + +diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/panthor/panthor_gpu.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_gpu.c +@@ -0,0 +1,482 @@ ++// SPDX-License-Identifier: GPL-2.0 or MIT ++/* Copyright 2018 Marty E. Plummer */ ++/* Copyright 2019 Linaro, Ltd., Rob Herring */ ++/* Copyright 2019 Collabora ltd. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "panthor_device.h" ++#include "panthor_gpu.h" ++#include "panthor_regs.h" ++ ++/** ++ * struct panthor_gpu - GPU block management data. ++ */ ++struct panthor_gpu { ++ /** @irq: GPU irq. */ ++ struct panthor_irq irq; ++ ++ /** @reqs_lock: Lock protecting access to pending_reqs. */ ++ spinlock_t reqs_lock; ++ ++ /** @pending_reqs: Pending GPU requests. */ ++ u32 pending_reqs; ++ ++ /** @reqs_acked: GPU request wait queue. */ ++ wait_queue_head_t reqs_acked; ++}; ++ ++/** ++ * struct panthor_model - GPU model description ++ */ ++struct panthor_model { ++ /** @name: Model name. */ ++ const char *name; ++ ++ /** @arch_major: Major version number of architecture. */ ++ u8 arch_major; ++ ++ /** @product_major: Major version number of product. */ ++ u8 product_major; ++}; ++ ++/** ++ * GPU_MODEL() - Define a GPU model. A GPU product can be uniquely identified ++ * by a combination of the major architecture version and the major product ++ * version. ++ * @_name: Name for the GPU model. ++ * @_arch_major: Architecture major. ++ * @_product_major: Product major. ++ */ ++#define GPU_MODEL(_name, _arch_major, _product_major) \ ++{\ ++ .name = __stringify(_name), \ ++ .arch_major = _arch_major, \ ++ .product_major = _product_major, \ ++} ++ ++static const struct panthor_model gpu_models[] = { ++ GPU_MODEL(g610, 10, 7), ++ {}, ++}; ++ ++#define GPU_INTERRUPTS_MASK \ ++ (GPU_IRQ_FAULT | \ ++ GPU_IRQ_PROTM_FAULT | \ ++ GPU_IRQ_RESET_COMPLETED | \ ++ GPU_IRQ_CLEAN_CACHES_COMPLETED) ++ ++static void panthor_gpu_init_info(struct panthor_device *ptdev) ++{ ++ const struct panthor_model *model; ++ u32 arch_major, product_major; ++ u32 major, minor, status; ++ unsigned int i; ++ ++ ptdev->gpu_info.gpu_id = gpu_read(ptdev, GPU_ID); ++ ptdev->gpu_info.csf_id = gpu_read(ptdev, GPU_CSF_ID); ++ ptdev->gpu_info.gpu_rev = gpu_read(ptdev, GPU_REVID); ++ ptdev->gpu_info.core_features = gpu_read(ptdev, GPU_CORE_FEATURES); ++ ptdev->gpu_info.l2_features = gpu_read(ptdev, GPU_L2_FEATURES); ++ ptdev->gpu_info.tiler_features = gpu_read(ptdev, GPU_TILER_FEATURES); ++ ptdev->gpu_info.mem_features = gpu_read(ptdev, GPU_MEM_FEATURES); ++ ptdev->gpu_info.mmu_features = gpu_read(ptdev, GPU_MMU_FEATURES); ++ ptdev->gpu_info.thread_features = gpu_read(ptdev, GPU_THREAD_FEATURES); ++ ptdev->gpu_info.max_threads = gpu_read(ptdev, GPU_THREAD_MAX_THREADS); ++ ptdev->gpu_info.thread_max_workgroup_size = gpu_read(ptdev, GPU_THREAD_MAX_WORKGROUP_SIZE); ++ ptdev->gpu_info.thread_max_barrier_size = gpu_read(ptdev, GPU_THREAD_MAX_BARRIER_SIZE); ++ ptdev->gpu_info.coherency_features = gpu_read(ptdev, GPU_COHERENCY_FEATURES); ++ for (i = 0; i < 4; i++) ++ ptdev->gpu_info.texture_features[i] = gpu_read(ptdev, GPU_TEXTURE_FEATURES(i)); ++ ++ ptdev->gpu_info.as_present = gpu_read(ptdev, GPU_AS_PRESENT); ++ ++ ptdev->gpu_info.shader_present = gpu_read(ptdev, GPU_SHADER_PRESENT_LO); ++ ptdev->gpu_info.shader_present |= (u64)gpu_read(ptdev, GPU_SHADER_PRESENT_HI) << 32; ++ ++ ptdev->gpu_info.tiler_present = gpu_read(ptdev, GPU_TILER_PRESENT_LO); ++ ptdev->gpu_info.tiler_present |= (u64)gpu_read(ptdev, GPU_TILER_PRESENT_HI) << 32; ++ ++ ptdev->gpu_info.l2_present = gpu_read(ptdev, GPU_L2_PRESENT_LO); ++ ptdev->gpu_info.l2_present |= (u64)gpu_read(ptdev, GPU_L2_PRESENT_HI) << 32; ++ ++ arch_major = GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id); ++ product_major = GPU_PROD_MAJOR(ptdev->gpu_info.gpu_id); ++ major = GPU_VER_MAJOR(ptdev->gpu_info.gpu_id); ++ minor = GPU_VER_MINOR(ptdev->gpu_info.gpu_id); ++ status = GPU_VER_STATUS(ptdev->gpu_info.gpu_id); ++ ++ for (model = gpu_models; model->name; model++) { ++ if (model->arch_major == arch_major && ++ model->product_major == product_major) ++ break; ++ } ++ ++ drm_info(&ptdev->base, ++ "mali-%s id 0x%x major 0x%x minor 0x%x status 0x%x", ++ model->name ?: "unknown", ptdev->gpu_info.gpu_id >> 16, ++ major, minor, status); ++ ++ drm_info(&ptdev->base, ++ "Features: L2:%#x Tiler:%#x Mem:%#x MMU:%#x AS:%#x", ++ ptdev->gpu_info.l2_features, ++ ptdev->gpu_info.tiler_features, ++ ptdev->gpu_info.mem_features, ++ ptdev->gpu_info.mmu_features, ++ ptdev->gpu_info.as_present); ++ ++ drm_info(&ptdev->base, ++ "shader_present=0x%0llx l2_present=0x%0llx tiler_present=0x%0llx", ++ ptdev->gpu_info.shader_present, ptdev->gpu_info.l2_present, ++ ptdev->gpu_info.tiler_present); ++} ++ ++static void panthor_gpu_irq_handler(struct panthor_device *ptdev, u32 status) ++{ ++ if (status & GPU_IRQ_FAULT) { ++ u32 fault_status = gpu_read(ptdev, GPU_FAULT_STATUS); ++ u64 address = ((u64)gpu_read(ptdev, GPU_FAULT_ADDR_HI) << 32) | ++ gpu_read(ptdev, GPU_FAULT_ADDR_LO); ++ ++ drm_warn(&ptdev->base, "GPU Fault 0x%08x (%s) at 0x%016llx\n", ++ fault_status, panthor_exception_name(ptdev, fault_status & 0xFF), ++ address); ++ } ++ if (status & GPU_IRQ_PROTM_FAULT) ++ drm_warn(&ptdev->base, "GPU Fault in protected mode\n"); ++ ++ spin_lock(&ptdev->gpu->reqs_lock); ++ if (status & ptdev->gpu->pending_reqs) { ++ ptdev->gpu->pending_reqs &= ~status; ++ wake_up_all(&ptdev->gpu->reqs_acked); ++ } ++ spin_unlock(&ptdev->gpu->reqs_lock); ++} ++PANTHOR_IRQ_HANDLER(gpu, GPU, panthor_gpu_irq_handler); ++ ++/** ++ * panthor_gpu_unplug() - Called when the GPU is unplugged. ++ * @ptdev: Device to unplug. ++ */ ++void panthor_gpu_unplug(struct panthor_device *ptdev) ++{ ++ unsigned long flags; ++ ++ /* Make sure the IRQ handler is not running after that point. */ ++ panthor_gpu_irq_suspend(&ptdev->gpu->irq); ++ ++ /* Wake-up all waiters. */ ++ spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); ++ ptdev->gpu->pending_reqs = 0; ++ wake_up_all(&ptdev->gpu->reqs_acked); ++ spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags); ++} ++ ++/** ++ * panthor_gpu_init() - Initialize the GPU block ++ * @ptdev: Device. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_gpu_init(struct panthor_device *ptdev) ++{ ++ struct panthor_gpu *gpu; ++ u32 pa_bits; ++ int ret, irq; ++ ++ gpu = drmm_kzalloc(&ptdev->base, sizeof(*gpu), GFP_KERNEL); ++ if (!gpu) ++ return -ENOMEM; ++ ++ spin_lock_init(&gpu->reqs_lock); ++ init_waitqueue_head(&gpu->reqs_acked); ++ ptdev->gpu = gpu; ++ panthor_gpu_init_info(ptdev); ++ ++ dma_set_max_seg_size(ptdev->base.dev, UINT_MAX); ++ pa_bits = GPU_MMU_FEATURES_PA_BITS(ptdev->gpu_info.mmu_features); ++ ret = dma_set_mask_and_coherent(ptdev->base.dev, DMA_BIT_MASK(pa_bits)); ++ if (ret) ++ return ret; ++ ++ irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "gpu"); ++ if (irq <= 0) ++ return ret; ++ ++ ret = panthor_request_gpu_irq(ptdev, &ptdev->gpu->irq, irq, GPU_INTERRUPTS_MASK); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++/** ++ * panthor_gpu_block_power_off() - Power-off a specific block of the GPU ++ * @ptdev: Device. ++ * @blk_name: Block name. ++ * @pwroff_reg: Power-off register for this block. ++ * @pwrtrans_reg: Power transition register for this block. ++ * @mask: Sub-elements to power-off. ++ * @timeout_us: Timeout in microseconds. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_gpu_block_power_off(struct panthor_device *ptdev, ++ const char *blk_name, ++ u32 pwroff_reg, u32 pwrtrans_reg, ++ u64 mask, u32 timeout_us) ++{ ++ u32 val, i; ++ int ret; ++ ++ for (i = 0; i < 2; i++) { ++ u32 mask32 = mask >> (i * 32); ++ ++ if (!mask32) ++ continue; ++ ++ ret = readl_relaxed_poll_timeout(ptdev->iomem + pwrtrans_reg + (i * 4), ++ val, !(mask32 & val), ++ 100, timeout_us); ++ if (ret) { ++ drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition", ++ blk_name, mask); ++ return ret; ++ } ++ } ++ ++ if (mask & GENMASK(31, 0)) ++ gpu_write(ptdev, pwroff_reg, mask); ++ ++ if (mask >> 32) ++ gpu_write(ptdev, pwroff_reg + 4, mask >> 32); ++ ++ for (i = 0; i < 2; i++) { ++ u32 mask32 = mask >> (i * 32); ++ ++ if (!mask32) ++ continue; ++ ++ ret = readl_relaxed_poll_timeout(ptdev->iomem + pwrtrans_reg + (i * 4), ++ val, !(mask32 & val), ++ 100, timeout_us); ++ if (ret) { ++ drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition", ++ blk_name, mask); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * panthor_gpu_block_power_on() - Power-on a specific block of the GPU ++ * @ptdev: Device. ++ * @blk_name: Block name. ++ * @pwron_reg: Power-on register for this block. ++ * @pwrtrans_reg: Power transition register for this block. ++ * @rdy_reg: Power transition ready register. ++ * @mask: Sub-elements to power-on. ++ * @timeout_us: Timeout in microseconds. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_gpu_block_power_on(struct panthor_device *ptdev, ++ const char *blk_name, ++ u32 pwron_reg, u32 pwrtrans_reg, ++ u32 rdy_reg, u64 mask, u32 timeout_us) ++{ ++ u32 val, i; ++ int ret; ++ ++ for (i = 0; i < 2; i++) { ++ u32 mask32 = mask >> (i * 32); ++ ++ if (!mask32) ++ continue; ++ ++ ret = readl_relaxed_poll_timeout(ptdev->iomem + pwrtrans_reg + (i * 4), ++ val, !(mask32 & val), ++ 100, timeout_us); ++ if (ret) { ++ drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition", ++ blk_name, mask); ++ return ret; ++ } ++ } ++ ++ if (mask & GENMASK(31, 0)) ++ gpu_write(ptdev, pwron_reg, mask); ++ ++ if (mask >> 32) ++ gpu_write(ptdev, pwron_reg + 4, mask >> 32); ++ ++ for (i = 0; i < 2; i++) { ++ u32 mask32 = mask >> (i * 32); ++ ++ if (!mask32) ++ continue; ++ ++ ret = readl_relaxed_poll_timeout(ptdev->iomem + rdy_reg + (i * 4), ++ val, (mask32 & val) == mask32, ++ 100, timeout_us); ++ if (ret) { ++ drm_err(&ptdev->base, "timeout waiting on %s:%llx readyness", ++ blk_name, mask); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * panthor_gpu_l2_power_on() - Power-on the L2-cache ++ * @ptdev: Device. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_gpu_l2_power_on(struct panthor_device *ptdev) ++{ ++ if (ptdev->gpu_info.l2_present != 1) { ++ /* ++ * Only support one core group now. ++ * ~(l2_present - 1) unsets all bits in l2_present except ++ * the bottom bit. (l2_present - 2) has all the bits in ++ * the first core group set. AND them together to generate ++ * a mask of cores in the first core group. ++ */ ++ u64 core_mask = ~(ptdev->gpu_info.l2_present - 1) & ++ (ptdev->gpu_info.l2_present - 2); ++ drm_info_once(&ptdev->base, "using only 1st core group (%lu cores from %lu)\n", ++ hweight64(core_mask), ++ hweight64(ptdev->gpu_info.shader_present)); ++ } ++ ++ return panthor_gpu_power_on(ptdev, L2, 1, 20000); ++} ++ ++/** ++ * panthor_gpu_flush_caches() - Flush caches ++ * @ptdev: Device. ++ * @l2: L2 flush type. ++ * @lsc: LSC flush type. ++ * @other: Other flush type. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_gpu_flush_caches(struct panthor_device *ptdev, ++ u32 l2, u32 lsc, u32 other) ++{ ++ bool timedout = false; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); ++ if (!drm_WARN_ON(&ptdev->base, ++ ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED)) { ++ ptdev->gpu->pending_reqs |= GPU_IRQ_CLEAN_CACHES_COMPLETED; ++ gpu_write(ptdev, GPU_CMD, GPU_FLUSH_CACHES(l2, lsc, other)); ++ } ++ spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags); ++ ++ if (!wait_event_timeout(ptdev->gpu->reqs_acked, ++ !(ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED), ++ msecs_to_jiffies(100))) { ++ spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); ++ if ((ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED) != 0 && ++ !(gpu_read(ptdev, GPU_INT_RAWSTAT) & GPU_IRQ_CLEAN_CACHES_COMPLETED)) ++ timedout = true; ++ else ++ ptdev->gpu->pending_reqs &= ~GPU_IRQ_CLEAN_CACHES_COMPLETED; ++ spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags); ++ } ++ ++ if (timedout) { ++ drm_err(&ptdev->base, "Flush caches timeout"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++/** ++ * panthor_gpu_soft_reset() - Issue a soft-reset ++ * @ptdev: Device. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_gpu_soft_reset(struct panthor_device *ptdev) ++{ ++ bool timedout = false; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); ++ if (!drm_WARN_ON(&ptdev->base, ++ ptdev->gpu->pending_reqs & GPU_IRQ_RESET_COMPLETED)) { ++ ptdev->gpu->pending_reqs |= GPU_IRQ_RESET_COMPLETED; ++ gpu_write(ptdev, GPU_INT_CLEAR, GPU_IRQ_RESET_COMPLETED); ++ gpu_write(ptdev, GPU_CMD, GPU_SOFT_RESET); ++ } ++ spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags); ++ ++ if (!wait_event_timeout(ptdev->gpu->reqs_acked, ++ !(ptdev->gpu->pending_reqs & GPU_IRQ_RESET_COMPLETED), ++ msecs_to_jiffies(100))) { ++ spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags); ++ if ((ptdev->gpu->pending_reqs & GPU_IRQ_RESET_COMPLETED) != 0 && ++ !(gpu_read(ptdev, GPU_INT_RAWSTAT) & GPU_IRQ_RESET_COMPLETED)) ++ timedout = true; ++ else ++ ptdev->gpu->pending_reqs &= ~GPU_IRQ_RESET_COMPLETED; ++ spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags); ++ } ++ ++ if (timedout) { ++ drm_err(&ptdev->base, "Soft reset timeout"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++/** ++ * panthor_gpu_suspend() - Suspend the GPU block. ++ * @ptdev: Device. ++ * ++ * Suspend the GPU irq. This should be called last in the suspend procedure, ++ * after all other blocks have been suspented. ++ */ ++void panthor_gpu_suspend(struct panthor_device *ptdev) ++{ ++ /* ++ * It may be preferable to simply power down the L2, but for now just ++ * soft-reset which will leave the L2 powered down. ++ */ ++ panthor_gpu_soft_reset(ptdev); ++ panthor_gpu_irq_suspend(&ptdev->gpu->irq); ++} ++ ++/** ++ * panthor_gpu_resume() - Resume the GPU block. ++ * @ptdev: Device. ++ * ++ * Resume the IRQ handler and power-on the L2-cache. ++ * The FW takes care of powering the other blocks. ++ */ ++void panthor_gpu_resume(struct panthor_device *ptdev) ++{ ++ panthor_gpu_irq_resume(&ptdev->gpu->irq, GPU_INTERRUPTS_MASK); ++ panthor_gpu_l2_power_on(ptdev); ++} +diff --git a/drivers/gpu/drm/panthor/panthor_gpu.h b/drivers/gpu/drm/panthor/panthor_gpu.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_gpu.h +@@ -0,0 +1,52 @@ ++/* SPDX-License-Identifier: GPL-2.0 or MIT */ ++/* Copyright 2018 Marty E. Plummer */ ++/* Copyright 2019 Collabora ltd. */ ++ ++#ifndef __PANTHOR_GPU_H__ ++#define __PANTHOR_GPU_H__ ++ ++struct panthor_device; ++ ++int panthor_gpu_init(struct panthor_device *ptdev); ++void panthor_gpu_unplug(struct panthor_device *ptdev); ++void panthor_gpu_suspend(struct panthor_device *ptdev); ++void panthor_gpu_resume(struct panthor_device *ptdev); ++ ++int panthor_gpu_block_power_on(struct panthor_device *ptdev, ++ const char *blk_name, ++ u32 pwron_reg, u32 pwrtrans_reg, ++ u32 rdy_reg, u64 mask, u32 timeout_us); ++int panthor_gpu_block_power_off(struct panthor_device *ptdev, ++ const char *blk_name, ++ u32 pwroff_reg, u32 pwrtrans_reg, ++ u64 mask, u32 timeout_us); ++ ++/** ++ * panthor_gpu_power_on() - Power on the GPU block. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++#define panthor_gpu_power_on(ptdev, type, mask, timeout_us) \ ++ panthor_gpu_block_power_on(ptdev, #type, \ ++ type ## _PWRON_LO, \ ++ type ## _PWRTRANS_LO, \ ++ type ## _READY_LO, \ ++ mask, timeout_us) ++ ++/** ++ * panthor_gpu_power_off() - Power off the GPU block. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++#define panthor_gpu_power_off(ptdev, type, mask, timeout_us) \ ++ panthor_gpu_block_power_off(ptdev, #type, \ ++ type ## _PWROFF_LO, \ ++ type ## _PWRTRANS_LO, \ ++ mask, timeout_us) ++ ++int panthor_gpu_l2_power_on(struct panthor_device *ptdev); ++int panthor_gpu_flush_caches(struct panthor_device *ptdev, ++ u32 l2, u32 lsc, u32 other); ++int panthor_gpu_soft_reset(struct panthor_device *ptdev); ++ ++#endif +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:19 +0100 +Subject: drm/panthor: Add GEM logical block + +Anything relating to GEM object management is placed here. Nothing +particularly interesting here, given the implementation is based on +drm_gem_shmem_object, which is doing most of the work. + +v6: +- Add Maxime's and Heiko's acks +- Return a page-aligned BO size to userspace when creating a BO +- Keep header inclusion alphabetically ordered + +v5: +- Add Liviu's and Steve's R-b + +v4: +- Force kernel BOs to be GPU mapped +- Make panthor_kernel_bo_destroy() robust against ERR/NULL BO pointers + to simplify the call sites + +v3: +- Add acks for the MIT/GPL2 relicensing +- Provide a panthor_kernel_bo abstraction for buffer objects managed by + the kernel (will replace panthor_fw_mem and be used everywhere we were + using panthor_gem_create_and_map() before) +- Adjust things to match drm_gpuvm changes +- Change return of panthor_gem_create_with_handle() to int + +Co-developed-by: Steven Price +Signed-off-by: Steven Price +Signed-off-by: Boris Brezillon +Acked-by: Steven Price # MIT+GPL2 relicensing,Arm +Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro +Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora +Reviewed-by: Liviu Dudau +Reviewed-by: Steven Price +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + drivers/gpu/drm/panthor/panthor_gem.c | 230 ++++++++++ + drivers/gpu/drm/panthor/panthor_gem.h | 142 ++++++ + 2 files changed, 372 insertions(+) + +diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_gem.c +@@ -0,0 +1,230 @@ ++// SPDX-License-Identifier: GPL-2.0 or MIT ++/* Copyright 2019 Linaro, Ltd, Rob Herring */ ++/* Copyright 2023 Collabora ltd. */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "panthor_device.h" ++#include "panthor_gem.h" ++#include "panthor_mmu.h" ++ ++static void panthor_gem_free_object(struct drm_gem_object *obj) ++{ ++ struct panthor_gem_object *bo = to_panthor_bo(obj); ++ struct drm_gem_object *vm_root_gem = bo->exclusive_vm_root_gem; ++ ++ drm_gem_free_mmap_offset(&bo->base.base); ++ mutex_destroy(&bo->gpuva_list_lock); ++ drm_gem_shmem_free(&bo->base); ++ drm_gem_object_put(vm_root_gem); ++} ++ ++/** ++ * panthor_kernel_bo_destroy() - Destroy a kernel buffer object ++ * @vm: The VM this BO was mapped to. ++ * @bo: Kernel buffer object to destroy. If NULL or an ERR_PTR(), the destruction ++ * is skipped. ++ */ ++void panthor_kernel_bo_destroy(struct panthor_vm *vm, ++ struct panthor_kernel_bo *bo) ++{ ++ int ret; ++ ++ if (IS_ERR_OR_NULL(bo)) ++ return; ++ ++ panthor_kernel_bo_vunmap(bo); ++ ++ if (drm_WARN_ON(bo->obj->dev, ++ to_panthor_bo(bo->obj)->exclusive_vm_root_gem != panthor_vm_root_gem(vm))) ++ goto out_free_bo; ++ ++ ret = panthor_vm_unmap_range(vm, bo->va_node.start, ++ panthor_kernel_bo_size(bo)); ++ if (ret) ++ goto out_free_bo; ++ ++ panthor_vm_free_va(vm, &bo->va_node); ++ drm_gem_object_put(bo->obj); ++ ++out_free_bo: ++ kfree(bo); ++} ++ ++/** ++ * panthor_kernel_bo_create() - Create and map a GEM object to a VM ++ * @ptdev: Device. ++ * @vm: VM to map the GEM to. If NULL, the kernel object is not GPU mapped. ++ * @size: Size of the buffer object. ++ * @bo_flags: Combination of drm_panthor_bo_flags flags. ++ * @vm_map_flags: Combination of drm_panthor_vm_bind_op_flags (only those ++ * that are related to map operations). ++ * @gpu_va: GPU address assigned when mapping to the VM. ++ * If gpu_va == PANTHOR_VM_KERNEL_AUTO_VA, the virtual address will be ++ * automatically allocated. ++ * ++ * Return: A valid pointer in case of success, an ERR_PTR() otherwise. ++ */ ++struct panthor_kernel_bo * ++panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm, ++ size_t size, u32 bo_flags, u32 vm_map_flags, ++ u64 gpu_va) ++{ ++ struct drm_gem_shmem_object *obj; ++ struct panthor_kernel_bo *kbo; ++ struct panthor_gem_object *bo; ++ int ret; ++ ++ if (drm_WARN_ON(&ptdev->base, !vm)) ++ return ERR_PTR(-EINVAL); ++ ++ kbo = kzalloc(sizeof(*kbo), GFP_KERNEL); ++ if (!kbo) ++ return ERR_PTR(-ENOMEM); ++ ++ obj = drm_gem_shmem_create(&ptdev->base, size); ++ if (IS_ERR(obj)) { ++ ret = PTR_ERR(obj); ++ goto err_free_bo; ++ } ++ ++ bo = to_panthor_bo(&obj->base); ++ size = obj->base.size; ++ kbo->obj = &obj->base; ++ bo->flags = bo_flags; ++ ++ ret = panthor_vm_alloc_va(vm, gpu_va, size, &kbo->va_node); ++ if (ret) ++ goto err_put_obj; ++ ++ ret = panthor_vm_map_bo_range(vm, bo, 0, size, kbo->va_node.start, vm_map_flags); ++ if (ret) ++ goto err_free_va; ++ ++ bo->exclusive_vm_root_gem = panthor_vm_root_gem(vm); ++ drm_gem_object_get(bo->exclusive_vm_root_gem); ++ bo->base.base.resv = bo->exclusive_vm_root_gem->resv; ++ return kbo; ++ ++err_free_va: ++ panthor_vm_free_va(vm, &kbo->va_node); ++ ++err_put_obj: ++ drm_gem_object_put(&obj->base); ++ ++err_free_bo: ++ kfree(kbo); ++ return ERR_PTR(ret); ++} ++ ++static int panthor_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) ++{ ++ struct panthor_gem_object *bo = to_panthor_bo(obj); ++ ++ /* Don't allow mmap on objects that have the NO_MMAP flag set. */ ++ if (bo->flags & DRM_PANTHOR_BO_NO_MMAP) ++ return -EINVAL; ++ ++ return drm_gem_shmem_object_mmap(obj, vma); ++} ++ ++static struct dma_buf * ++panthor_gem_prime_export(struct drm_gem_object *obj, int flags) ++{ ++ /* We can't export GEMs that have an exclusive VM. */ ++ if (to_panthor_bo(obj)->exclusive_vm_root_gem) ++ return ERR_PTR(-EINVAL); ++ ++ return drm_gem_prime_export(obj, flags); ++} ++ ++static const struct drm_gem_object_funcs panthor_gem_funcs = { ++ .free = panthor_gem_free_object, ++ .print_info = drm_gem_shmem_object_print_info, ++ .pin = drm_gem_shmem_object_pin, ++ .unpin = drm_gem_shmem_object_unpin, ++ .get_sg_table = drm_gem_shmem_object_get_sg_table, ++ .vmap = drm_gem_shmem_object_vmap, ++ .vunmap = drm_gem_shmem_object_vunmap, ++ .mmap = panthor_gem_mmap, ++ .export = panthor_gem_prime_export, ++ .vm_ops = &drm_gem_shmem_vm_ops, ++}; ++ ++/** ++ * panthor_gem_create_object - Implementation of driver->gem_create_object. ++ * @ddev: DRM device ++ * @size: Size in bytes of the memory the object will reference ++ * ++ * This lets the GEM helpers allocate object structs for us, and keep ++ * our BO stats correct. ++ */ ++struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size) ++{ ++ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); ++ struct panthor_gem_object *obj; ++ ++ obj = kzalloc(sizeof(*obj), GFP_KERNEL); ++ if (!obj) ++ return ERR_PTR(-ENOMEM); ++ ++ obj->base.base.funcs = &panthor_gem_funcs; ++ obj->base.map_wc = !ptdev->coherent; ++ mutex_init(&obj->gpuva_list_lock); ++ drm_gem_gpuva_set_lock(&obj->base.base, &obj->gpuva_list_lock); ++ ++ return &obj->base.base; ++} ++ ++/** ++ * panthor_gem_create_with_handle() - Create a GEM object and attach it to a handle. ++ * @file: DRM file. ++ * @ddev: DRM device. ++ * @exclusive_vm: Exclusive VM. Not NULL if the GEM object can't be shared. ++ * @size: Size of the GEM object to allocate. ++ * @flags: Combination of drm_panthor_bo_flags flags. ++ * @handle: Pointer holding the handle pointing to the new GEM object. ++ * ++ * Return: Zero on success ++ */ ++int ++panthor_gem_create_with_handle(struct drm_file *file, ++ struct drm_device *ddev, ++ struct panthor_vm *exclusive_vm, ++ u64 *size, u32 flags, u32 *handle) ++{ ++ int ret; ++ struct drm_gem_shmem_object *shmem; ++ struct panthor_gem_object *bo; ++ ++ shmem = drm_gem_shmem_create(ddev, *size); ++ if (IS_ERR(shmem)) ++ return PTR_ERR(shmem); ++ ++ bo = to_panthor_bo(&shmem->base); ++ bo->flags = flags; ++ ++ if (exclusive_vm) { ++ bo->exclusive_vm_root_gem = panthor_vm_root_gem(exclusive_vm); ++ drm_gem_object_get(bo->exclusive_vm_root_gem); ++ bo->base.base.resv = bo->exclusive_vm_root_gem->resv; ++ } ++ ++ /* ++ * Allocate an id of idr table where the obj is registered ++ * and handle has the id what user can see. ++ */ ++ ret = drm_gem_handle_create(file, &shmem->base, handle); ++ if (!ret) ++ *size = bo->base.base.size; ++ ++ /* drop reference from allocate - handle holds it now. */ ++ drm_gem_object_put(&shmem->base); ++ ++ return ret; ++} +diff --git a/drivers/gpu/drm/panthor/panthor_gem.h b/drivers/gpu/drm/panthor/panthor_gem.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_gem.h +@@ -0,0 +1,142 @@ ++/* SPDX-License-Identifier: GPL-2.0 or MIT */ ++/* Copyright 2019 Linaro, Ltd, Rob Herring */ ++/* Copyright 2023 Collabora ltd. */ ++ ++#ifndef __PANTHOR_GEM_H__ ++#define __PANTHOR_GEM_H__ ++ ++#include ++#include ++ ++#include ++#include ++ ++struct panthor_vm; ++ ++/** ++ * struct panthor_gem_object - Driver specific GEM object. ++ */ ++struct panthor_gem_object { ++ /** @base: Inherit from drm_gem_shmem_object. */ ++ struct drm_gem_shmem_object base; ++ ++ /** ++ * @exclusive_vm_root_gem: Root GEM of the exclusive VM this GEM object ++ * is attached to. ++ * ++ * If @exclusive_vm_root_gem != NULL, any attempt to bind the GEM to a ++ * different VM will fail. ++ * ++ * All FW memory objects have this field set to the root GEM of the MCU ++ * VM. ++ */ ++ struct drm_gem_object *exclusive_vm_root_gem; ++ ++ /** ++ * @gpuva_list_lock: Custom GPUVA lock. ++ * ++ * Used to protect insertion of drm_gpuva elements to the ++ * drm_gem_object.gpuva.list list. ++ * ++ * We can't use the GEM resv for that, because drm_gpuva_link() is ++ * called in a dma-signaling path, where we're not allowed to take ++ * resv locks. ++ */ ++ struct mutex gpuva_list_lock; ++ ++ /** @flags: Combination of drm_panthor_bo_flags flags. */ ++ u32 flags; ++}; ++ ++/** ++ * struct panthor_kernel_bo - Kernel buffer object. ++ * ++ * These objects are only manipulated by the kernel driver and not ++ * directly exposed to the userspace. The GPU address of a kernel ++ * BO might be passed to userspace though. ++ */ ++struct panthor_kernel_bo { ++ /** ++ * @obj: The GEM object backing this kernel buffer object. ++ */ ++ struct drm_gem_object *obj; ++ ++ /** ++ * @va_node: VA space allocated to this GEM. ++ */ ++ struct drm_mm_node va_node; ++ ++ /** ++ * @kmap: Kernel CPU mapping of @gem. ++ */ ++ void *kmap; ++}; ++ ++static inline ++struct panthor_gem_object *to_panthor_bo(struct drm_gem_object *obj) ++{ ++ return container_of(to_drm_gem_shmem_obj(obj), struct panthor_gem_object, base); ++} ++ ++struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size); ++ ++struct drm_gem_object * ++panthor_gem_prime_import_sg_table(struct drm_device *ddev, ++ struct dma_buf_attachment *attach, ++ struct sg_table *sgt); ++ ++int ++panthor_gem_create_with_handle(struct drm_file *file, ++ struct drm_device *ddev, ++ struct panthor_vm *exclusive_vm, ++ u64 *size, u32 flags, uint32_t *handle); ++ ++static inline u64 ++panthor_kernel_bo_gpuva(struct panthor_kernel_bo *bo) ++{ ++ return bo->va_node.start; ++} ++ ++static inline size_t ++panthor_kernel_bo_size(struct panthor_kernel_bo *bo) ++{ ++ return bo->obj->size; ++} ++ ++static inline int ++panthor_kernel_bo_vmap(struct panthor_kernel_bo *bo) ++{ ++ struct iosys_map map; ++ int ret; ++ ++ if (bo->kmap) ++ return 0; ++ ++ ret = drm_gem_vmap_unlocked(bo->obj, &map); ++ if (ret) ++ return ret; ++ ++ bo->kmap = map.vaddr; ++ return 0; ++} ++ ++static inline void ++panthor_kernel_bo_vunmap(struct panthor_kernel_bo *bo) ++{ ++ if (bo->kmap) { ++ struct iosys_map map = IOSYS_MAP_INIT_VADDR(bo->kmap); ++ ++ drm_gem_vunmap_unlocked(bo->obj, &map); ++ bo->kmap = NULL; ++ } ++} ++ ++struct panthor_kernel_bo * ++panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm, ++ size_t size, u32 bo_flags, u32 vm_map_flags, ++ u64 gpu_va); ++ ++void panthor_kernel_bo_destroy(struct panthor_vm *vm, ++ struct panthor_kernel_bo *bo); ++ ++#endif /* __PANTHOR_GEM_H__ */ +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:20 +0100 +Subject: drm/panthor: Add the devfreq logical block + +Every thing related to devfreq in placed in panthor_devfreq.c, and +helpers that can be called by other logical blocks are exposed through +panthor_devfreq.h. + +This implementation is loosely based on the panfrost implementation, +the only difference being that we don't count device users, because +the idle/active state will be managed by the scheduler logic. + +v6: +- Add Maxime's and Heiko's acks +- Keep header inclusion alphabetically ordered + +v4: +- Add Clement's A-b for the relicensing + +v3: +- Add acks for the MIT/GPL2 relicensing + +v2: +- Added in v2 + +Cc: Clement Peron # MIT+GPL2 relicensing +Reviewed-by: Steven Price +Signed-off-by: Boris Brezillon +Acked-by: Steven Price # MIT+GPL2 relicensing,Arm +Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro +Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora +Acked-by: Clement Peron # MIT+GPL2 relicensing +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + drivers/gpu/drm/panthor/panthor_devfreq.c | 283 ++++++++++ + drivers/gpu/drm/panthor/panthor_devfreq.h | 21 + + 2 files changed, 304 insertions(+) + +diff --git a/drivers/gpu/drm/panthor/panthor_devfreq.c b/drivers/gpu/drm/panthor/panthor_devfreq.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_devfreq.c +@@ -0,0 +1,283 @@ ++// SPDX-License-Identifier: GPL-2.0 or MIT ++/* Copyright 2019 Collabora ltd. */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "panthor_devfreq.h" ++#include "panthor_device.h" ++ ++/** ++ * struct panthor_devfreq - Device frequency management ++ */ ++struct panthor_devfreq { ++ /** @devfreq: devfreq device. */ ++ struct devfreq *devfreq; ++ ++ /** @gov_data: Governor data. */ ++ struct devfreq_simple_ondemand_data gov_data; ++ ++ /** @busy_time: Busy time. */ ++ ktime_t busy_time; ++ ++ /** @idle_time: Idle time. */ ++ ktime_t idle_time; ++ ++ /** @time_last_update: Last update time. */ ++ ktime_t time_last_update; ++ ++ /** @last_busy_state: True if the GPU was busy last time we updated the state. */ ++ bool last_busy_state; ++ ++ /* ++ * @lock: Lock used to protect busy_time, idle_time, time_last_update and ++ * last_busy_state. ++ * ++ * These fields can be accessed concurrently by panthor_devfreq_get_dev_status() ++ * and panthor_devfreq_record_{busy,idle}(). ++ */ ++ spinlock_t lock; ++}; ++ ++static void panthor_devfreq_update_utilization(struct panthor_devfreq *pdevfreq) ++{ ++ ktime_t now, last; ++ ++ now = ktime_get(); ++ last = pdevfreq->time_last_update; ++ ++ if (pdevfreq->last_busy_state) ++ pdevfreq->busy_time += ktime_sub(now, last); ++ else ++ pdevfreq->idle_time += ktime_sub(now, last); ++ ++ pdevfreq->time_last_update = now; ++} ++ ++static int panthor_devfreq_target(struct device *dev, unsigned long *freq, ++ u32 flags) ++{ ++ struct dev_pm_opp *opp; ++ ++ opp = devfreq_recommended_opp(dev, freq, flags); ++ if (IS_ERR(opp)) ++ return PTR_ERR(opp); ++ dev_pm_opp_put(opp); ++ ++ return dev_pm_opp_set_rate(dev, *freq); ++} ++ ++static void panthor_devfreq_reset(struct panthor_devfreq *pdevfreq) ++{ ++ pdevfreq->busy_time = 0; ++ pdevfreq->idle_time = 0; ++ pdevfreq->time_last_update = ktime_get(); ++} ++ ++static int panthor_devfreq_get_dev_status(struct device *dev, ++ struct devfreq_dev_status *status) ++{ ++ struct panthor_device *ptdev = dev_get_drvdata(dev); ++ struct panthor_devfreq *pdevfreq = ptdev->devfreq; ++ unsigned long irqflags; ++ ++ status->current_frequency = clk_get_rate(ptdev->clks.core); ++ ++ spin_lock_irqsave(&pdevfreq->lock, irqflags); ++ ++ panthor_devfreq_update_utilization(pdevfreq); ++ ++ status->total_time = ktime_to_ns(ktime_add(pdevfreq->busy_time, ++ pdevfreq->idle_time)); ++ ++ status->busy_time = ktime_to_ns(pdevfreq->busy_time); ++ ++ panthor_devfreq_reset(pdevfreq); ++ ++ spin_unlock_irqrestore(&pdevfreq->lock, irqflags); ++ ++ drm_dbg(&ptdev->base, "busy %lu total %lu %lu %% freq %lu MHz\n", ++ status->busy_time, status->total_time, ++ status->busy_time / (status->total_time / 100), ++ status->current_frequency / 1000 / 1000); ++ ++ return 0; ++} ++ ++static struct devfreq_dev_profile panthor_devfreq_profile = { ++ .timer = DEVFREQ_TIMER_DELAYED, ++ .polling_ms = 50, /* ~3 frames */ ++ .target = panthor_devfreq_target, ++ .get_dev_status = panthor_devfreq_get_dev_status, ++}; ++ ++int panthor_devfreq_init(struct panthor_device *ptdev) ++{ ++ /* There's actually 2 regulators (mali and sram), but the OPP core only ++ * supports one. ++ * ++ * We assume the sram regulator is coupled with the mali one and let ++ * the coupling logic deal with voltage updates. ++ */ ++ static const char * const reg_names[] = { "mali", NULL }; ++ struct thermal_cooling_device *cooling; ++ struct device *dev = ptdev->base.dev; ++ struct panthor_devfreq *pdevfreq; ++ struct dev_pm_opp *opp; ++ unsigned long cur_freq; ++ int ret; ++ ++ pdevfreq = drmm_kzalloc(&ptdev->base, sizeof(*ptdev->devfreq), GFP_KERNEL); ++ if (!pdevfreq) ++ return -ENOMEM; ++ ++ ptdev->devfreq = pdevfreq; ++ ++ ret = devm_pm_opp_set_regulators(dev, reg_names); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n"); ++ ++ return ret; ++ } ++ ++ ret = devm_pm_opp_of_add_table(dev); ++ if (ret) ++ return ret; ++ ++ spin_lock_init(&pdevfreq->lock); ++ ++ panthor_devfreq_reset(pdevfreq); ++ ++ cur_freq = clk_get_rate(ptdev->clks.core); ++ ++ opp = devfreq_recommended_opp(dev, &cur_freq, 0); ++ if (IS_ERR(opp)) ++ return PTR_ERR(opp); ++ ++ panthor_devfreq_profile.initial_freq = cur_freq; ++ ++ /* Regulator coupling only takes care of synchronizing/balancing voltage ++ * updates, but the coupled regulator needs to be enabled manually. ++ * ++ * We use devm_regulator_get_enable_optional() and keep the sram supply ++ * enabled until the device is removed, just like we do for the mali ++ * supply, which is enabled when dev_pm_opp_set_opp(dev, opp) is called, ++ * and disabled when the opp_table is torn down, using the devm action. ++ * ++ * If we really care about disabling regulators on suspend, we should: ++ * - use devm_regulator_get_optional() here ++ * - call dev_pm_opp_set_opp(dev, NULL) before leaving this function ++ * (this disables the regulator passed to the OPP layer) ++ * - call dev_pm_opp_set_opp(dev, NULL) and ++ * regulator_disable(ptdev->regulators.sram) in ++ * panthor_devfreq_suspend() ++ * - call dev_pm_opp_set_opp(dev, default_opp) and ++ * regulator_enable(ptdev->regulators.sram) in ++ * panthor_devfreq_resume() ++ * ++ * But without knowing if it's beneficial or not (in term of power ++ * consumption), or how much it slows down the suspend/resume steps, ++ * let's just keep regulators enabled for the device lifetime. ++ */ ++ ret = devm_regulator_get_enable_optional(dev, "sram"); ++ if (ret && ret != -ENODEV) { ++ if (ret != -EPROBE_DEFER) ++ DRM_DEV_ERROR(dev, "Couldn't retrieve/enable sram supply\n"); ++ return ret; ++ } ++ ++ /* ++ * Set the recommend OPP this will enable and configure the regulator ++ * if any and will avoid a switch off by regulator_late_cleanup() ++ */ ++ ret = dev_pm_opp_set_opp(dev, opp); ++ if (ret) { ++ DRM_DEV_ERROR(dev, "Couldn't set recommended OPP\n"); ++ return ret; ++ } ++ ++ dev_pm_opp_put(opp); ++ ++ /* ++ * Setup default thresholds for the simple_ondemand governor. ++ * The values are chosen based on experiments. ++ */ ++ pdevfreq->gov_data.upthreshold = 45; ++ pdevfreq->gov_data.downdifferential = 5; ++ ++ pdevfreq->devfreq = devm_devfreq_add_device(dev, &panthor_devfreq_profile, ++ DEVFREQ_GOV_SIMPLE_ONDEMAND, ++ &pdevfreq->gov_data); ++ if (IS_ERR(pdevfreq->devfreq)) { ++ DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n"); ++ ret = PTR_ERR(pdevfreq->devfreq); ++ pdevfreq->devfreq = NULL; ++ return ret; ++ } ++ ++ cooling = devfreq_cooling_em_register(pdevfreq->devfreq, NULL); ++ if (IS_ERR(cooling)) ++ DRM_DEV_INFO(dev, "Failed to register cooling device\n"); ++ ++ return 0; ++} ++ ++int panthor_devfreq_resume(struct panthor_device *ptdev) ++{ ++ struct panthor_devfreq *pdevfreq = ptdev->devfreq; ++ ++ if (!pdevfreq->devfreq) ++ return 0; ++ ++ panthor_devfreq_reset(pdevfreq); ++ ++ return devfreq_resume_device(pdevfreq->devfreq); ++} ++ ++int panthor_devfreq_suspend(struct panthor_device *ptdev) ++{ ++ struct panthor_devfreq *pdevfreq = ptdev->devfreq; ++ ++ if (!pdevfreq->devfreq) ++ return 0; ++ ++ return devfreq_suspend_device(pdevfreq->devfreq); ++} ++ ++void panthor_devfreq_record_busy(struct panthor_device *ptdev) ++{ ++ struct panthor_devfreq *pdevfreq = ptdev->devfreq; ++ unsigned long irqflags; ++ ++ if (!pdevfreq->devfreq) ++ return; ++ ++ spin_lock_irqsave(&pdevfreq->lock, irqflags); ++ ++ panthor_devfreq_update_utilization(pdevfreq); ++ pdevfreq->last_busy_state = true; ++ ++ spin_unlock_irqrestore(&pdevfreq->lock, irqflags); ++} ++ ++void panthor_devfreq_record_idle(struct panthor_device *ptdev) ++{ ++ struct panthor_devfreq *pdevfreq = ptdev->devfreq; ++ unsigned long irqflags; ++ ++ if (!pdevfreq->devfreq) ++ return; ++ ++ spin_lock_irqsave(&pdevfreq->lock, irqflags); ++ ++ panthor_devfreq_update_utilization(pdevfreq); ++ pdevfreq->last_busy_state = false; ++ ++ spin_unlock_irqrestore(&pdevfreq->lock, irqflags); ++} +diff --git a/drivers/gpu/drm/panthor/panthor_devfreq.h b/drivers/gpu/drm/panthor/panthor_devfreq.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_devfreq.h +@@ -0,0 +1,21 @@ ++/* SPDX-License-Identifier: GPL-2.0 or MIT */ ++/* Copyright 2019 Collabora ltd. */ ++ ++#ifndef __PANTHOR_DEVFREQ_H__ ++#define __PANTHOR_DEVFREQ_H__ ++ ++struct devfreq; ++struct thermal_cooling_device; ++ ++struct panthor_device; ++struct panthor_devfreq; ++ ++int panthor_devfreq_init(struct panthor_device *ptdev); ++ ++int panthor_devfreq_resume(struct panthor_device *ptdev); ++int panthor_devfreq_suspend(struct panthor_device *ptdev); ++ ++void panthor_devfreq_record_busy(struct panthor_device *ptdev); ++void panthor_devfreq_record_idle(struct panthor_device *ptdev); ++ ++#endif /* __PANTHOR_DEVFREQ_H__ */ +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:21 +0100 +Subject: drm/panthor: Add the MMU/VM logical block + +MMU and VM management is related and placed in the same source file. + +Page table updates are delegated to the io-pgtable-arm driver that's in +the iommu subsystem. + +The VM management logic is based on drm_gpuva_mgr, and is assuming the +VA space is mostly managed by the usermode driver, except for a reserved +portion of this VA-space that's used for kernel objects (like the heap +contexts/chunks). + +Both asynchronous and synchronous VM operations are supported, and +internal helpers are exposed to allow other logical blocks to map their +buffers in the GPU VA space. + +There's one VM_BIND queue per-VM (meaning the Vulkan driver can only +expose one sparse-binding queue), and this bind queue is managed with +a 1:1 drm_sched_entity:drm_gpu_scheduler, such that each VM gets its own +independent execution queue, avoiding VM operation serialization at the +device level (things are still serialized at the VM level). + +The rest is just implementation details that are hopefully well explained +in the documentation. + +v6: +- Add Maxime's and Heiko's acks +- Add Steve's R-b +- Adjust the TRANSCFG value to account for SW VA space limitation on + 32-bit systems +- Keep header inclusion alphabetically ordered + +v5: +- Fix a double panthor_vm_cleanup_op_ctx() call +- Fix a race between panthor_vm_prepare_map_op_ctx() and + panthor_vm_bo_put() +- Fix panthor_vm_pool_destroy_vm() kernel doc +- Fix paddr adjustment in panthor_vm_map_pages() +- Fix bo_offset calculation in panthor_vm_get_bo_for_va() + +v4: +- Add an helper to return the VM state +- Check drmm_mutex_init() return code +- Remove the VM from the AS reclaim list when panthor_vm_active() is + called +- Count the number of active VM users instead of considering there's + at most one user (several scheduling groups can point to the same + vM) +- Pre-allocate a VMA object for unmap operations (unmaps can trigger + a sm_step_remap() call) +- Check vm->root_page_table instead of vm->pgtbl_ops to detect if + the io-pgtable is trying to allocate the root page table +- Don't memset() the va_node in panthor_vm_alloc_va(), make it a + caller requirement +- Fix the kernel doc in a few places +- Drop the panthor_vm::base offset constraint and modify + panthor_vm_put() to explicitly check for a NULL value +- Fix unbalanced vm_bo refcount in panthor_gpuva_sm_step_remap() +- Drop stale comments about the shared_bos list +- Patch mmu_features::va_bits on 32-bit builds to reflect the + io_pgtable limitation and let the UMD know about it + +v3: +- Add acks for the MIT/GPL2 relicensing +- Propagate MMU faults to the scheduler +- Move pages pinning/unpinning out of the dma_signalling path +- Fix 32-bit support +- Rework the user/kernel VA range calculation +- Make the auto-VA range explicit (auto-VA range doesn't cover the full + kernel-VA range on the MCU VM) +- Let callers of panthor_vm_alloc_va() allocate the drm_mm_node + (embedded in panthor_kernel_bo now) +- Adjust things to match the latest drm_gpuvm changes (extobj tracking, + resv prep and more) +- Drop the per-AS lock and use slots_lock (fixes a race on vm->as.id) +- Set as.id to -1 when reusing an address space from the LRU list +- Drop misleading comment about page faults +- Remove check for irq being assigned in panthor_mmu_unplug() + +Co-developed-by: Steven Price +Signed-off-by: Steven Price +Signed-off-by: Boris Brezillon +Acked-by: Steven Price # MIT+GPL2 relicensing,Arm +Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro +Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora +Reviewed-by: Steven Price +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + drivers/gpu/drm/panthor/panthor_mmu.c | 2768 ++++++++++ + drivers/gpu/drm/panthor/panthor_mmu.h | 102 + + 2 files changed, 2870 insertions(+) + +diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_mmu.c +@@ -0,0 +1,2768 @@ ++// SPDX-License-Identifier: GPL-2.0 or MIT ++/* Copyright 2019 Linaro, Ltd, Rob Herring */ ++/* Copyright 2023 Collabora ltd. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "panthor_device.h" ++#include "panthor_gem.h" ++#include "panthor_heap.h" ++#include "panthor_mmu.h" ++#include "panthor_regs.h" ++#include "panthor_sched.h" ++ ++#define MAX_AS_SLOTS 32 ++ ++struct panthor_vm; ++ ++/** ++ * struct panthor_as_slot - Address space slot ++ */ ++struct panthor_as_slot { ++ /** @vm: VM bound to this slot. NULL is no VM is bound. */ ++ struct panthor_vm *vm; ++}; ++ ++/** ++ * struct panthor_mmu - MMU related data ++ */ ++struct panthor_mmu { ++ /** @irq: The MMU irq. */ ++ struct panthor_irq irq; ++ ++ /** @as: Address space related fields. ++ * ++ * The GPU has a limited number of address spaces (AS) slots, forcing ++ * us to re-assign them to re-assign slots on-demand. ++ */ ++ struct { ++ /** @slots_lock: Lock protecting access to all other AS fields. */ ++ struct mutex slots_lock; ++ ++ /** @alloc_mask: Bitmask encoding the allocated slots. */ ++ unsigned long alloc_mask; ++ ++ /** @faulty_mask: Bitmask encoding the faulty slots. */ ++ unsigned long faulty_mask; ++ ++ /** @slots: VMs currently bound to the AS slots. */ ++ struct panthor_as_slot slots[MAX_AS_SLOTS]; ++ ++ /** ++ * @lru_list: List of least recently used VMs. ++ * ++ * We use this list to pick a VM to evict when all slots are ++ * used. ++ * ++ * There should be no more active VMs than there are AS slots, ++ * so this LRU is just here to keep VMs bound until there's ++ * a need to release a slot, thus avoid unnecessary TLB/cache ++ * flushes. ++ */ ++ struct list_head lru_list; ++ } as; ++ ++ /** @vm: VMs management fields */ ++ struct { ++ /** @lock: Lock protecting access to list. */ ++ struct mutex lock; ++ ++ /** @list: List containing all VMs. */ ++ struct list_head list; ++ ++ /** @reset_in_progress: True if a reset is in progress. */ ++ bool reset_in_progress; ++ ++ /** @wq: Workqueue used for the VM_BIND queues. */ ++ struct workqueue_struct *wq; ++ } vm; ++}; ++ ++/** ++ * struct panthor_vm_pool - VM pool object ++ */ ++struct panthor_vm_pool { ++ /** @xa: Array used for VM handle tracking. */ ++ struct xarray xa; ++}; ++ ++/** ++ * struct panthor_vma - GPU mapping object ++ * ++ * This is used to track GEM mappings in GPU space. ++ */ ++struct panthor_vma { ++ /** @base: Inherits from drm_gpuva. */ ++ struct drm_gpuva base; ++ ++ /** @node: Used to implement deferred release of VMAs. */ ++ struct list_head node; ++ ++ /** ++ * @flags: Combination of drm_panthor_vm_bind_op_flags. ++ * ++ * Only map related flags are accepted. ++ */ ++ u32 flags; ++}; ++ ++/** ++ * struct panthor_vm_op_ctx - VM operation context ++ * ++ * With VM operations potentially taking place in a dma-signaling path, we ++ * need to make sure everything that might require resource allocation is ++ * pre-allocated upfront. This is what this operation context is far. ++ * ++ * We also collect resources that have been freed, so we can release them ++ * asynchronously, and let the VM_BIND scheduler process the next VM_BIND ++ * request. ++ */ ++struct panthor_vm_op_ctx { ++ /** @rsvd_page_tables: Pages reserved for the MMU page table update. */ ++ struct { ++ /** @count: Number of pages reserved. */ ++ u32 count; ++ ++ /** @ptr: Point to the first unused page in the @pages table. */ ++ u32 ptr; ++ ++ /** ++ * @page: Array of pages that can be used for an MMU page table update. ++ * ++ * After an VM operation, there might be free pages left in this array. ++ * They should be returned to the pt_cache as part of the op_ctx cleanup. ++ */ ++ void **pages; ++ } rsvd_page_tables; ++ ++ /** ++ * @preallocated_vmas: Pre-allocated VMAs to handle the remap case. ++ * ++ * Partial unmap requests or map requests overlapping existing mappings will ++ * trigger a remap call, which need to register up to three panthor_vma objects ++ * (one for the new mapping, and two for the previous and next mappings). ++ */ ++ struct panthor_vma *preallocated_vmas[3]; ++ ++ /** @flags: Combination of drm_panthor_vm_bind_op_flags. */ ++ u32 flags; ++ ++ /** @va: Virtual range targeted by the VM operation. */ ++ struct { ++ /** @addr: Start address. */ ++ u64 addr; ++ ++ /** @range: Range size. */ ++ u64 range; ++ } va; ++ ++ /** ++ * @returned_vmas: List of panthor_vma objects returned after a VM operation. ++ * ++ * For unmap operations, this will contain all VMAs that were covered by the ++ * specified VA range. ++ * ++ * For map operations, this will contain all VMAs that previously mapped to ++ * the specified VA range. ++ * ++ * Those VMAs, and the resources they point to will be released as part of ++ * the op_ctx cleanup operation. ++ */ ++ struct list_head returned_vmas; ++ ++ /** @map: Fields specific to a map operation. */ ++ struct { ++ /** @vm_bo: Buffer object to map. */ ++ struct drm_gpuvm_bo *vm_bo; ++ ++ /** @bo_offset: Offset in the buffer object. */ ++ u64 bo_offset; ++ ++ /** ++ * @sgt: sg-table pointing to pages backing the GEM object. ++ * ++ * This is gathered at job creation time, such that we don't have ++ * to allocate in ::run_job(). ++ */ ++ struct sg_table *sgt; ++ ++ /** ++ * @new_vma: The new VMA object that will be inserted to the VA tree. ++ */ ++ struct panthor_vma *new_vma; ++ } map; ++}; ++ ++/** ++ * struct panthor_vm - VM object ++ * ++ * A VM is an object representing a GPU (or MCU) virtual address space. ++ * It embeds the MMU page table for this address space, a tree containing ++ * all the virtual mappings of GEM objects, and other things needed to manage ++ * the VM. ++ * ++ * Except for the MCU VM, which is managed by the kernel, all other VMs are ++ * created by userspace and mostly managed by userspace, using the ++ * %DRM_IOCTL_PANTHOR_VM_BIND ioctl. ++ * ++ * A portion of the virtual address space is reserved for kernel objects, ++ * like heap chunks, and userspace gets to decide how much of the virtual ++ * address space is left to the kernel (half of the virtual address space ++ * by default). ++ */ ++struct panthor_vm { ++ /** ++ * @base: Inherit from drm_gpuvm. ++ * ++ * We delegate all the VA management to the common drm_gpuvm framework ++ * and only implement hooks to update the MMU page table. ++ */ ++ struct drm_gpuvm base; ++ ++ /** ++ * @sched: Scheduler used for asynchronous VM_BIND request. ++ * ++ * We use a 1:1 scheduler here. ++ */ ++ struct drm_gpu_scheduler sched; ++ ++ /** ++ * @entity: Scheduling entity representing the VM_BIND queue. ++ * ++ * There's currently one bind queue per VM. It doesn't make sense to ++ * allow more given the VM operations are serialized anyway. ++ */ ++ struct drm_sched_entity entity; ++ ++ /** @ptdev: Device. */ ++ struct panthor_device *ptdev; ++ ++ /** @memattr: Value to program to the AS_MEMATTR register. */ ++ u64 memattr; ++ ++ /** @pgtbl_ops: Page table operations. */ ++ struct io_pgtable_ops *pgtbl_ops; ++ ++ /** @root_page_table: Stores the root page table pointer. */ ++ void *root_page_table; ++ ++ /** ++ * @op_lock: Lock used to serialize operations on a VM. ++ * ++ * The serialization of jobs queued to the VM_BIND queue is already ++ * taken care of by drm_sched, but we need to serialize synchronous ++ * and asynchronous VM_BIND request. This is what this lock is for. ++ */ ++ struct mutex op_lock; ++ ++ /** ++ * @op_ctx: The context attached to the currently executing VM operation. ++ * ++ * NULL when no operation is in progress. ++ */ ++ struct panthor_vm_op_ctx *op_ctx; ++ ++ /** ++ * @mm: Memory management object representing the auto-VA/kernel-VA. ++ * ++ * Used to auto-allocate VA space for kernel-managed objects (tiler ++ * heaps, ...). ++ * ++ * For the MCU VM, this is managing the VA range that's used to map ++ * all shared interfaces. ++ * ++ * For user VMs, the range is specified by userspace, and must not ++ * exceed half of the VA space addressable. ++ */ ++ struct drm_mm mm; ++ ++ /** @mm_lock: Lock protecting the @mm field. */ ++ struct mutex mm_lock; ++ ++ /** @kernel_auto_va: Automatic VA-range for kernel BOs. */ ++ struct { ++ /** @start: Start of the automatic VA-range for kernel BOs. */ ++ u64 start; ++ ++ /** @size: Size of the automatic VA-range for kernel BOs. */ ++ u64 end; ++ } kernel_auto_va; ++ ++ /** @as: Address space related fields. */ ++ struct { ++ /** ++ * @id: ID of the address space this VM is bound to. ++ * ++ * A value of -1 means the VM is inactive/not bound. ++ */ ++ int id; ++ ++ /** @active_cnt: Number of active users of this VM. */ ++ refcount_t active_cnt; ++ ++ /** ++ * @lru_node: Used to instead the VM in the panthor_mmu::as::lru_list. ++ * ++ * Active VMs should not be inserted in the LRU list. ++ */ ++ struct list_head lru_node; ++ } as; ++ ++ /** ++ * @heaps: Tiler heap related fields. ++ */ ++ struct { ++ /** ++ * @pool: The heap pool attached to this VM. ++ * ++ * Will stay NULL until someone creates a heap context on this VM. ++ */ ++ struct panthor_heap_pool *pool; ++ ++ /** @lock: Lock used to protect access to @pool. */ ++ struct mutex lock; ++ } heaps; ++ ++ /** @node: Used to insert the VM in the panthor_mmu::vm::list. */ ++ struct list_head node; ++ ++ /** @for_mcu: True if this is the MCU VM. */ ++ bool for_mcu; ++ ++ /** ++ * @destroyed: True if the VM was destroyed. ++ * ++ * No further bind requests should be queued to a destroyed VM. ++ */ ++ bool destroyed; ++ ++ /** ++ * @unusable: True if the VM has turned unusable because something ++ * bad happened during an asynchronous request. ++ * ++ * We don't try to recover from such failures, because this implies ++ * informing userspace about the specific operation that failed, and ++ * hoping the userspace driver can replay things from there. This all ++ * sounds very complicated for little gain. ++ * ++ * Instead, we should just flag the VM as unusable, and fail any ++ * further request targeting this VM. ++ * ++ * We also provide a way to query a VM state, so userspace can destroy ++ * it and create a new one. ++ * ++ * As an analogy, this would be mapped to a VK_ERROR_DEVICE_LOST ++ * situation, where the logical device needs to be re-created. ++ */ ++ bool unusable; ++ ++ /** ++ * @unhandled_fault: Unhandled fault happened. ++ * ++ * This should be reported to the scheduler, and the queue/group be ++ * flagged as faulty as a result. ++ */ ++ bool unhandled_fault; ++}; ++ ++/** ++ * struct panthor_vm_bind_job - VM bind job ++ */ ++struct panthor_vm_bind_job { ++ /** @base: Inherit from drm_sched_job. */ ++ struct drm_sched_job base; ++ ++ /** @refcount: Reference count. */ ++ struct kref refcount; ++ ++ /** @cleanup_op_ctx_work: Work used to cleanup the VM operation context. */ ++ struct work_struct cleanup_op_ctx_work; ++ ++ /** @vm: VM targeted by the VM operation. */ ++ struct panthor_vm *vm; ++ ++ /** @ctx: Operation context. */ ++ struct panthor_vm_op_ctx ctx; ++}; ++ ++/** ++ * @pt_cache: Cache used to allocate MMU page tables. ++ * ++ * The pre-allocation pattern forces us to over-allocate to plan for ++ * the worst case scenario, and return the pages we didn't use. ++ * ++ * Having a kmem_cache allows us to speed allocations. ++ */ ++static struct kmem_cache *pt_cache; ++ ++/** ++ * alloc_pt() - Custom page table allocator ++ * @cookie: Cookie passed at page table allocation time. ++ * @size: Size of the page table. This size should be fixed, ++ * and determined at creation time based on the granule size. ++ * @gfp: GFP flags. ++ * ++ * We want a custom allocator so we can use a cache for page table ++ * allocations and amortize the cost of the over-reservation that's ++ * done to allow asynchronous VM operations. ++ * ++ * Return: non-NULL on success, NULL if the allocation failed for any ++ * reason. ++ */ ++static void *alloc_pt(void *cookie, size_t size, gfp_t gfp) ++{ ++ struct panthor_vm *vm = cookie; ++ void *page; ++ ++ /* Allocation of the root page table happening during init. */ ++ if (unlikely(!vm->root_page_table)) { ++ struct page *p; ++ ++ drm_WARN_ON(&vm->ptdev->base, vm->op_ctx); ++ p = alloc_pages_node(dev_to_node(vm->ptdev->base.dev), ++ gfp | __GFP_ZERO, get_order(size)); ++ page = p ? page_address(p) : NULL; ++ vm->root_page_table = page; ++ return page; ++ } ++ ++ /* We're not supposed to have anything bigger than 4k here, because we picked a ++ * 4k granule size at init time. ++ */ ++ if (drm_WARN_ON(&vm->ptdev->base, size != SZ_4K)) ++ return NULL; ++ ++ /* We must have some op_ctx attached to the VM and it must have at least one ++ * free page. ++ */ ++ if (drm_WARN_ON(&vm->ptdev->base, !vm->op_ctx) || ++ drm_WARN_ON(&vm->ptdev->base, ++ vm->op_ctx->rsvd_page_tables.ptr >= vm->op_ctx->rsvd_page_tables.count)) ++ return NULL; ++ ++ page = vm->op_ctx->rsvd_page_tables.pages[vm->op_ctx->rsvd_page_tables.ptr++]; ++ memset(page, 0, SZ_4K); ++ ++ /* Page table entries don't use virtual addresses, which trips out ++ * kmemleak. kmemleak_alloc_phys() might work, but physical addresses ++ * are mixed with other fields, and I fear kmemleak won't detect that ++ * either. ++ * ++ * Let's just ignore memory passed to the page-table driver for now. ++ */ ++ kmemleak_ignore(page); ++ return page; ++} ++ ++/** ++ * @free_pt() - Custom page table free function ++ * @cookie: Cookie passed at page table allocation time. ++ * @data: Page table to free. ++ * @size: Size of the page table. This size should be fixed, ++ * and determined at creation time based on the granule size. ++ */ ++static void free_pt(void *cookie, void *data, size_t size) ++{ ++ struct panthor_vm *vm = cookie; ++ ++ if (unlikely(vm->root_page_table == data)) { ++ free_pages((unsigned long)data, get_order(size)); ++ vm->root_page_table = NULL; ++ return; ++ } ++ ++ if (drm_WARN_ON(&vm->ptdev->base, size != SZ_4K)) ++ return; ++ ++ /* Return the page to the pt_cache. */ ++ kmem_cache_free(pt_cache, data); ++} ++ ++static int wait_ready(struct panthor_device *ptdev, u32 as_nr) ++{ ++ int ret; ++ u32 val; ++ ++ /* Wait for the MMU status to indicate there is no active command, in ++ * case one is pending. ++ */ ++ ret = readl_relaxed_poll_timeout_atomic(ptdev->iomem + AS_STATUS(as_nr), ++ val, !(val & AS_STATUS_AS_ACTIVE), ++ 10, 100000); ++ ++ if (ret) { ++ panthor_device_schedule_reset(ptdev); ++ drm_err(&ptdev->base, "AS_ACTIVE bit stuck\n"); ++ } ++ ++ return ret; ++} ++ ++static int write_cmd(struct panthor_device *ptdev, u32 as_nr, u32 cmd) ++{ ++ int status; ++ ++ /* write AS_COMMAND when MMU is ready to accept another command */ ++ status = wait_ready(ptdev, as_nr); ++ if (!status) ++ gpu_write(ptdev, AS_COMMAND(as_nr), cmd); ++ ++ return status; ++} ++ ++static void lock_region(struct panthor_device *ptdev, u32 as_nr, ++ u64 region_start, u64 size) ++{ ++ u8 region_width; ++ u64 region; ++ u64 region_end = region_start + size; ++ ++ if (!size) ++ return; ++ ++ /* ++ * The locked region is a naturally aligned power of 2 block encoded as ++ * log2 minus(1). ++ * Calculate the desired start/end and look for the highest bit which ++ * differs. The smallest naturally aligned block must include this bit ++ * change, the desired region starts with this bit (and subsequent bits) ++ * zeroed and ends with the bit (and subsequent bits) set to one. ++ */ ++ region_width = max(fls64(region_start ^ (region_end - 1)), ++ const_ilog2(AS_LOCK_REGION_MIN_SIZE)) - 1; ++ ++ /* ++ * Mask off the low bits of region_start (which would be ignored by ++ * the hardware anyway) ++ */ ++ region_start &= GENMASK_ULL(63, region_width); ++ ++ region = region_width | region_start; ++ ++ /* Lock the region that needs to be updated */ ++ gpu_write(ptdev, AS_LOCKADDR_LO(as_nr), lower_32_bits(region)); ++ gpu_write(ptdev, AS_LOCKADDR_HI(as_nr), upper_32_bits(region)); ++ write_cmd(ptdev, as_nr, AS_COMMAND_LOCK); ++} ++ ++static int mmu_hw_do_operation_locked(struct panthor_device *ptdev, int as_nr, ++ u64 iova, u64 size, u32 op) ++{ ++ lockdep_assert_held(&ptdev->mmu->as.slots_lock); ++ ++ if (as_nr < 0) ++ return 0; ++ ++ if (op != AS_COMMAND_UNLOCK) ++ lock_region(ptdev, as_nr, iova, size); ++ ++ /* Run the MMU operation */ ++ write_cmd(ptdev, as_nr, op); ++ ++ /* Wait for the flush to complete */ ++ return wait_ready(ptdev, as_nr); ++} ++ ++static int mmu_hw_do_operation(struct panthor_vm *vm, ++ u64 iova, u64 size, u32 op) ++{ ++ struct panthor_device *ptdev = vm->ptdev; ++ int ret; ++ ++ mutex_lock(&ptdev->mmu->as.slots_lock); ++ ret = mmu_hw_do_operation_locked(ptdev, vm->as.id, iova, size, op); ++ mutex_unlock(&ptdev->mmu->as.slots_lock); ++ ++ return ret; ++} ++ ++static int panthor_mmu_as_enable(struct panthor_device *ptdev, u32 as_nr, ++ u64 transtab, u64 transcfg, u64 memattr) ++{ ++ int ret; ++ ++ ret = mmu_hw_do_operation_locked(ptdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM); ++ if (ret) ++ return ret; ++ ++ gpu_write(ptdev, AS_TRANSTAB_LO(as_nr), lower_32_bits(transtab)); ++ gpu_write(ptdev, AS_TRANSTAB_HI(as_nr), upper_32_bits(transtab)); ++ ++ gpu_write(ptdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr)); ++ gpu_write(ptdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr)); ++ ++ gpu_write(ptdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg)); ++ gpu_write(ptdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg)); ++ ++ return write_cmd(ptdev, as_nr, AS_COMMAND_UPDATE); ++} ++ ++static int panthor_mmu_as_disable(struct panthor_device *ptdev, u32 as_nr) ++{ ++ int ret; ++ ++ ret = mmu_hw_do_operation_locked(ptdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM); ++ if (ret) ++ return ret; ++ ++ gpu_write(ptdev, AS_TRANSTAB_LO(as_nr), 0); ++ gpu_write(ptdev, AS_TRANSTAB_HI(as_nr), 0); ++ ++ gpu_write(ptdev, AS_MEMATTR_LO(as_nr), 0); ++ gpu_write(ptdev, AS_MEMATTR_HI(as_nr), 0); ++ ++ gpu_write(ptdev, AS_TRANSCFG_LO(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED); ++ gpu_write(ptdev, AS_TRANSCFG_HI(as_nr), 0); ++ ++ return write_cmd(ptdev, as_nr, AS_COMMAND_UPDATE); ++} ++ ++static u32 panthor_mmu_fault_mask(struct panthor_device *ptdev, u32 value) ++{ ++ /* Bits 16 to 31 mean REQ_COMPLETE. */ ++ return value & GENMASK(15, 0); ++} ++ ++static u32 panthor_mmu_as_fault_mask(struct panthor_device *ptdev, u32 as) ++{ ++ return BIT(as); ++} ++ ++/** ++ * panthor_vm_has_unhandled_faults() - Check if a VM has unhandled faults ++ * @vm: VM to check. ++ * ++ * Return: true if the VM has unhandled faults, false otherwise. ++ */ ++bool panthor_vm_has_unhandled_faults(struct panthor_vm *vm) ++{ ++ return vm->unhandled_fault; ++} ++ ++/** ++ * panthor_vm_is_unusable() - Check if the VM is still usable ++ * @vm: VM to check. ++ * ++ * Return: true if the VM is unusable, false otherwise. ++ */ ++bool panthor_vm_is_unusable(struct panthor_vm *vm) ++{ ++ return vm->unusable; ++} ++ ++static void panthor_vm_release_as_locked(struct panthor_vm *vm) ++{ ++ struct panthor_device *ptdev = vm->ptdev; ++ ++ lockdep_assert_held(&ptdev->mmu->as.slots_lock); ++ ++ if (drm_WARN_ON(&ptdev->base, vm->as.id < 0)) ++ return; ++ ++ ptdev->mmu->as.slots[vm->as.id].vm = NULL; ++ clear_bit(vm->as.id, &ptdev->mmu->as.alloc_mask); ++ refcount_set(&vm->as.active_cnt, 0); ++ list_del_init(&vm->as.lru_node); ++ vm->as.id = -1; ++} ++ ++/** ++ * panthor_vm_active() - Flag a VM as active ++ * @VM: VM to flag as active. ++ * ++ * Assigns an address space to a VM so it can be used by the GPU/MCU. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_vm_active(struct panthor_vm *vm) ++{ ++ struct panthor_device *ptdev = vm->ptdev; ++ u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features); ++ struct io_pgtable_cfg *cfg = &io_pgtable_ops_to_pgtable(vm->pgtbl_ops)->cfg; ++ int ret = 0, as, cookie; ++ u64 transtab, transcfg; ++ ++ if (!drm_dev_enter(&ptdev->base, &cookie)) ++ return -ENODEV; ++ ++ if (refcount_inc_not_zero(&vm->as.active_cnt)) ++ goto out_dev_exit; ++ ++ mutex_lock(&ptdev->mmu->as.slots_lock); ++ ++ if (refcount_inc_not_zero(&vm->as.active_cnt)) ++ goto out_unlock; ++ ++ as = vm->as.id; ++ if (as >= 0) { ++ /* Unhandled pagefault on this AS, the MMU was disabled. We need to ++ * re-enable the MMU after clearing+unmasking the AS interrupts. ++ */ ++ if (ptdev->mmu->as.faulty_mask & panthor_mmu_as_fault_mask(ptdev, as)) ++ goto out_enable_as; ++ ++ goto out_make_active; ++ } ++ ++ /* Check for a free AS */ ++ if (vm->for_mcu) { ++ drm_WARN_ON(&ptdev->base, ptdev->mmu->as.alloc_mask & BIT(0)); ++ as = 0; ++ } else { ++ as = ffz(ptdev->mmu->as.alloc_mask | BIT(0)); ++ } ++ ++ if (!(BIT(as) & ptdev->gpu_info.as_present)) { ++ struct panthor_vm *lru_vm; ++ ++ lru_vm = list_first_entry_or_null(&ptdev->mmu->as.lru_list, ++ struct panthor_vm, ++ as.lru_node); ++ if (drm_WARN_ON(&ptdev->base, !lru_vm)) { ++ ret = -EBUSY; ++ goto out_unlock; ++ } ++ ++ drm_WARN_ON(&ptdev->base, refcount_read(&lru_vm->as.active_cnt)); ++ as = lru_vm->as.id; ++ panthor_vm_release_as_locked(lru_vm); ++ } ++ ++ /* Assign the free or reclaimed AS to the FD */ ++ vm->as.id = as; ++ set_bit(as, &ptdev->mmu->as.alloc_mask); ++ ptdev->mmu->as.slots[as].vm = vm; ++ ++out_enable_as: ++ transtab = cfg->arm_lpae_s1_cfg.ttbr; ++ transcfg = AS_TRANSCFG_PTW_MEMATTR_WB | ++ AS_TRANSCFG_PTW_RA | ++ AS_TRANSCFG_ADRMODE_AARCH64_4K | ++ AS_TRANSCFG_INA_BITS(55 - va_bits); ++ if (ptdev->coherent) ++ transcfg |= AS_TRANSCFG_PTW_SH_OS; ++ ++ /* If the VM is re-activated, we clear the fault. */ ++ vm->unhandled_fault = false; ++ ++ /* Unhandled pagefault on this AS, clear the fault and re-enable interrupts ++ * before enabling the AS. ++ */ ++ if (ptdev->mmu->as.faulty_mask & panthor_mmu_as_fault_mask(ptdev, as)) { ++ gpu_write(ptdev, MMU_INT_CLEAR, panthor_mmu_as_fault_mask(ptdev, as)); ++ ptdev->mmu->as.faulty_mask &= ~panthor_mmu_as_fault_mask(ptdev, as); ++ gpu_write(ptdev, MMU_INT_MASK, ~ptdev->mmu->as.faulty_mask); ++ } ++ ++ ret = panthor_mmu_as_enable(vm->ptdev, vm->as.id, transtab, transcfg, vm->memattr); ++ ++out_make_active: ++ if (!ret) { ++ refcount_set(&vm->as.active_cnt, 1); ++ list_del_init(&vm->as.lru_node); ++ } ++ ++out_unlock: ++ mutex_unlock(&ptdev->mmu->as.slots_lock); ++ ++out_dev_exit: ++ drm_dev_exit(cookie); ++ return ret; ++} ++ ++/** ++ * panthor_vm_idle() - Flag a VM idle ++ * @VM: VM to flag as idle. ++ * ++ * When we know the GPU is done with the VM (no more jobs to process), ++ * we can relinquish the AS slot attached to this VM, if any. ++ * ++ * We don't release the slot immediately, but instead place the VM in ++ * the LRU list, so it can be evicted if another VM needs an AS slot. ++ * This way, VMs keep attached to the AS they were given until we run ++ * out of free slot, limiting the number of MMU operations (TLB flush ++ * and other AS updates). ++ */ ++void panthor_vm_idle(struct panthor_vm *vm) ++{ ++ struct panthor_device *ptdev = vm->ptdev; ++ ++ if (!refcount_dec_and_mutex_lock(&vm->as.active_cnt, &ptdev->mmu->as.slots_lock)) ++ return; ++ ++ if (!drm_WARN_ON(&ptdev->base, vm->as.id == -1 || !list_empty(&vm->as.lru_node))) ++ list_add_tail(&vm->as.lru_node, &ptdev->mmu->as.lru_list); ++ ++ refcount_set(&vm->as.active_cnt, 0); ++ mutex_unlock(&ptdev->mmu->as.slots_lock); ++} ++ ++static void panthor_vm_stop(struct panthor_vm *vm) ++{ ++ drm_sched_stop(&vm->sched, NULL); ++} ++ ++static void panthor_vm_start(struct panthor_vm *vm) ++{ ++ drm_sched_start(&vm->sched, true); ++} ++ ++/** ++ * panthor_vm_as() - Get the AS slot attached to a VM ++ * @vm: VM to get the AS slot of. ++ * ++ * Return: -1 if the VM is not assigned an AS slot yet, >= 0 otherwise. ++ */ ++int panthor_vm_as(struct panthor_vm *vm) ++{ ++ return vm->as.id; ++} ++ ++static size_t get_pgsize(u64 addr, size_t size, size_t *count) ++{ ++ /* ++ * io-pgtable only operates on multiple pages within a single table ++ * entry, so we need to split at boundaries of the table size, i.e. ++ * the next block size up. The distance from address A to the next ++ * boundary of block size B is logically B - A % B, but in unsigned ++ * two's complement where B is a power of two we get the equivalence ++ * B - A % B == (B - A) % B == (n * B - A) % B, and choose n = 0 :) ++ */ ++ size_t blk_offset = -addr % SZ_2M; ++ ++ if (blk_offset || size < SZ_2M) { ++ *count = min_not_zero(blk_offset, size) / SZ_4K; ++ return SZ_4K; ++ } ++ blk_offset = -addr % SZ_1G ?: SZ_1G; ++ *count = min(blk_offset, size) / SZ_2M; ++ return SZ_2M; ++} ++ ++static int panthor_vm_flush_range(struct panthor_vm *vm, u64 iova, u64 size) ++{ ++ struct panthor_device *ptdev = vm->ptdev; ++ int ret = 0, cookie; ++ ++ if (vm->as.id < 0) ++ return 0; ++ ++ /* If the device is unplugged, we just silently skip the flush. */ ++ if (!drm_dev_enter(&ptdev->base, &cookie)) ++ return 0; ++ ++ /* Flush the PTs only if we're already awake */ ++ if (pm_runtime_active(ptdev->base.dev)) ++ ret = mmu_hw_do_operation(vm, iova, size, AS_COMMAND_FLUSH_PT); ++ ++ drm_dev_exit(cookie); ++ return ret; ++} ++ ++static int panthor_vm_unmap_pages(struct panthor_vm *vm, u64 iova, u64 size) ++{ ++ struct panthor_device *ptdev = vm->ptdev; ++ struct io_pgtable_ops *ops = vm->pgtbl_ops; ++ u64 offset = 0; ++ ++ drm_dbg(&ptdev->base, "unmap: as=%d, iova=%llx, len=%llx", vm->as.id, iova, size); ++ ++ while (offset < size) { ++ size_t unmapped_sz = 0, pgcount; ++ size_t pgsize = get_pgsize(iova + offset, size - offset, &pgcount); ++ ++ unmapped_sz = ops->unmap_pages(ops, iova + offset, pgsize, pgcount, NULL); ++ ++ if (drm_WARN_ON(&ptdev->base, unmapped_sz != pgsize * pgcount)) { ++ drm_err(&ptdev->base, "failed to unmap range %llx-%llx (requested range %llx-%llx)\n", ++ iova + offset + unmapped_sz, ++ iova + offset + pgsize * pgcount, ++ iova, iova + size); ++ panthor_vm_flush_range(vm, iova, offset + unmapped_sz); ++ return -EINVAL; ++ } ++ offset += unmapped_sz; ++ } ++ ++ return panthor_vm_flush_range(vm, iova, size); ++} ++ ++static int ++panthor_vm_map_pages(struct panthor_vm *vm, u64 iova, int prot, ++ struct sg_table *sgt, u64 offset, u64 size) ++{ ++ struct panthor_device *ptdev = vm->ptdev; ++ unsigned int count; ++ struct scatterlist *sgl; ++ struct io_pgtable_ops *ops = vm->pgtbl_ops; ++ u64 start_iova = iova; ++ int ret; ++ ++ if (!size) ++ return 0; ++ ++ for_each_sgtable_dma_sg(sgt, sgl, count) { ++ dma_addr_t paddr = sg_dma_address(sgl); ++ size_t len = sg_dma_len(sgl); ++ ++ if (len <= offset) { ++ offset -= len; ++ continue; ++ } ++ ++ paddr += offset; ++ len -= offset; ++ len = min_t(size_t, len, size); ++ size -= len; ++ ++ drm_dbg(&ptdev->base, "map: as=%d, iova=%llx, paddr=%pad, len=%zx", ++ vm->as.id, iova, &paddr, len); ++ ++ while (len) { ++ size_t pgcount, mapped = 0; ++ size_t pgsize = get_pgsize(iova | paddr, len, &pgcount); ++ ++ ret = ops->map_pages(ops, iova, paddr, pgsize, pgcount, prot, ++ GFP_KERNEL, &mapped); ++ iova += mapped; ++ paddr += mapped; ++ len -= mapped; ++ ++ if (drm_WARN_ON(&ptdev->base, !ret && !mapped)) ++ ret = -ENOMEM; ++ ++ if (ret) { ++ /* If something failed, unmap what we've already mapped before ++ * returning. The unmap call is not supposed to fail. ++ */ ++ drm_WARN_ON(&ptdev->base, ++ panthor_vm_unmap_pages(vm, start_iova, ++ iova - start_iova)); ++ return ret; ++ } ++ } ++ ++ if (!size) ++ break; ++ } ++ ++ return panthor_vm_flush_range(vm, start_iova, iova - start_iova); ++} ++ ++static int flags_to_prot(u32 flags) ++{ ++ int prot = 0; ++ ++ if (flags & DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC) ++ prot |= IOMMU_NOEXEC; ++ ++ if (!(flags & DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED)) ++ prot |= IOMMU_CACHE; ++ ++ if (flags & DRM_PANTHOR_VM_BIND_OP_MAP_READONLY) ++ prot |= IOMMU_READ; ++ else ++ prot |= IOMMU_READ | IOMMU_WRITE; ++ ++ return prot; ++} ++ ++/** ++ * panthor_vm_alloc_va() - Allocate a region in the auto-va space ++ * @VM: VM to allocate a region on. ++ * @va: start of the VA range. Can be PANTHOR_VM_KERNEL_AUTO_VA if the user ++ * wants the VA to be automatically allocated from the auto-VA range. ++ * @size: size of the VA range. ++ * @va_node: drm_mm_node to initialize. Must be zero-initialized. ++ * ++ * Some GPU objects, like heap chunks, are fully managed by the kernel and ++ * need to be mapped to the userspace VM, in the region reserved for kernel ++ * objects. ++ * ++ * This function takes care of allocating a region in the kernel auto-VA space. ++ * ++ * Return: 0 on success, an error code otherwise. ++ */ ++int ++panthor_vm_alloc_va(struct panthor_vm *vm, u64 va, u64 size, ++ struct drm_mm_node *va_node) ++{ ++ int ret; ++ ++ if (!size || (size & ~PAGE_MASK)) ++ return -EINVAL; ++ ++ if (va != PANTHOR_VM_KERNEL_AUTO_VA && (va & ~PAGE_MASK)) ++ return -EINVAL; ++ ++ mutex_lock(&vm->mm_lock); ++ if (va != PANTHOR_VM_KERNEL_AUTO_VA) { ++ va_node->start = va; ++ va_node->size = size; ++ ret = drm_mm_reserve_node(&vm->mm, va_node); ++ } else { ++ ret = drm_mm_insert_node_in_range(&vm->mm, va_node, size, ++ size >= SZ_2M ? SZ_2M : SZ_4K, ++ 0, vm->kernel_auto_va.start, ++ vm->kernel_auto_va.end, ++ DRM_MM_INSERT_BEST); ++ } ++ mutex_unlock(&vm->mm_lock); ++ ++ return ret; ++} ++ ++/** ++ * panthor_vm_free_va() - Free a region allocated with panthor_vm_alloc_va() ++ * @VM: VM to free the region on. ++ * @va_node: Memory node representing the region to free. ++ */ ++void panthor_vm_free_va(struct panthor_vm *vm, struct drm_mm_node *va_node) ++{ ++ mutex_lock(&vm->mm_lock); ++ drm_mm_remove_node(va_node); ++ mutex_unlock(&vm->mm_lock); ++} ++ ++static void panthor_vm_bo_put(struct drm_gpuvm_bo *vm_bo) ++{ ++ struct panthor_gem_object *bo = to_panthor_bo(vm_bo->obj); ++ struct drm_gpuvm *vm = vm_bo->vm; ++ bool unpin; ++ ++ /* We must retain the GEM before calling drm_gpuvm_bo_put(), ++ * otherwise the mutex might be destroyed while we hold it. ++ * Same goes for the VM, since we take the VM resv lock. ++ */ ++ drm_gem_object_get(&bo->base.base); ++ drm_gpuvm_get(vm); ++ ++ /* We take the resv lock to protect against concurrent accesses to the ++ * gpuvm evicted/extobj lists that are modified in ++ * drm_gpuvm_bo_destroy(), which is called if drm_gpuvm_bo_put() ++ * releases sthe last vm_bo reference. ++ * We take the BO GPUVA list lock to protect the vm_bo removal from the ++ * GEM vm_bo list. ++ */ ++ dma_resv_lock(drm_gpuvm_resv(vm), NULL); ++ mutex_lock(&bo->gpuva_list_lock); ++ unpin = drm_gpuvm_bo_put(vm_bo); ++ mutex_unlock(&bo->gpuva_list_lock); ++ dma_resv_unlock(drm_gpuvm_resv(vm)); ++ ++ /* If the vm_bo object was destroyed, release the pin reference that ++ * was hold by this object. ++ */ ++ if (unpin && !bo->base.base.import_attach) ++ drm_gem_shmem_unpin(&bo->base); ++ ++ drm_gpuvm_put(vm); ++ drm_gem_object_put(&bo->base.base); ++} ++ ++static void panthor_vm_cleanup_op_ctx(struct panthor_vm_op_ctx *op_ctx, ++ struct panthor_vm *vm) ++{ ++ struct panthor_vma *vma, *tmp_vma; ++ ++ u32 remaining_pt_count = op_ctx->rsvd_page_tables.count - ++ op_ctx->rsvd_page_tables.ptr; ++ ++ if (remaining_pt_count) { ++ kmem_cache_free_bulk(pt_cache, remaining_pt_count, ++ op_ctx->rsvd_page_tables.pages + ++ op_ctx->rsvd_page_tables.ptr); ++ } ++ ++ kfree(op_ctx->rsvd_page_tables.pages); ++ ++ if (op_ctx->map.vm_bo) ++ panthor_vm_bo_put(op_ctx->map.vm_bo); ++ ++ for (u32 i = 0; i < ARRAY_SIZE(op_ctx->preallocated_vmas); i++) ++ kfree(op_ctx->preallocated_vmas[i]); ++ ++ list_for_each_entry_safe(vma, tmp_vma, &op_ctx->returned_vmas, node) { ++ list_del(&vma->node); ++ panthor_vm_bo_put(vma->base.vm_bo); ++ kfree(vma); ++ } ++} ++ ++static struct panthor_vma * ++panthor_vm_op_ctx_get_vma(struct panthor_vm_op_ctx *op_ctx) ++{ ++ for (u32 i = 0; i < ARRAY_SIZE(op_ctx->preallocated_vmas); i++) { ++ struct panthor_vma *vma = op_ctx->preallocated_vmas[i]; ++ ++ if (vma) { ++ op_ctx->preallocated_vmas[i] = NULL; ++ return vma; ++ } ++ } ++ ++ return NULL; ++} ++ ++static int ++panthor_vm_op_ctx_prealloc_vmas(struct panthor_vm_op_ctx *op_ctx) ++{ ++ u32 vma_count; ++ ++ switch (op_ctx->flags & DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) { ++ case DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: ++ /* One VMA for the new mapping, and two more VMAs for the remap case ++ * which might contain both a prev and next VA. ++ */ ++ vma_count = 3; ++ break; ++ ++ case DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP: ++ /* Partial unmaps might trigger a remap with either a prev or a next VA, ++ * but not both. ++ */ ++ vma_count = 1; ++ break; ++ ++ default: ++ return 0; ++ } ++ ++ for (u32 i = 0; i < vma_count; i++) { ++ struct panthor_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL); ++ ++ if (!vma) ++ return -ENOMEM; ++ ++ op_ctx->preallocated_vmas[i] = vma; ++ } ++ ++ return 0; ++} ++ ++#define PANTHOR_VM_BIND_OP_MAP_FLAGS \ ++ (DRM_PANTHOR_VM_BIND_OP_MAP_READONLY | \ ++ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | \ ++ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED | \ ++ DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) ++ ++static int panthor_vm_prepare_map_op_ctx(struct panthor_vm_op_ctx *op_ctx, ++ struct panthor_vm *vm, ++ struct panthor_gem_object *bo, ++ u64 offset, ++ u64 size, u64 va, ++ u32 flags) ++{ ++ struct drm_gpuvm_bo *preallocated_vm_bo; ++ struct sg_table *sgt = NULL; ++ u64 pt_count; ++ int ret; ++ ++ if (!bo) ++ return -EINVAL; ++ ++ if ((flags & ~PANTHOR_VM_BIND_OP_MAP_FLAGS) || ++ (flags & DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) != DRM_PANTHOR_VM_BIND_OP_TYPE_MAP) ++ return -EINVAL; ++ ++ /* Make sure the VA and size are aligned and in-bounds. */ ++ if (size > bo->base.base.size || offset > bo->base.base.size - size) ++ return -EINVAL; ++ ++ /* If the BO has an exclusive VM attached, it can't be mapped to other VMs. */ ++ if (bo->exclusive_vm_root_gem && ++ bo->exclusive_vm_root_gem != panthor_vm_root_gem(vm)) ++ return -EINVAL; ++ ++ memset(op_ctx, 0, sizeof(*op_ctx)); ++ INIT_LIST_HEAD(&op_ctx->returned_vmas); ++ op_ctx->flags = flags; ++ op_ctx->va.range = size; ++ op_ctx->va.addr = va; ++ ++ ret = panthor_vm_op_ctx_prealloc_vmas(op_ctx); ++ if (ret) ++ goto err_cleanup; ++ ++ if (!bo->base.base.import_attach) { ++ /* Pre-reserve the BO pages, so the map operation doesn't have to ++ * allocate. ++ */ ++ ret = drm_gem_shmem_pin(&bo->base); ++ if (ret) ++ goto err_cleanup; ++ } ++ ++ sgt = drm_gem_shmem_get_pages_sgt(&bo->base); ++ if (IS_ERR(sgt)) { ++ if (!bo->base.base.import_attach) ++ drm_gem_shmem_unpin(&bo->base); ++ ++ ret = PTR_ERR(sgt); ++ goto err_cleanup; ++ } ++ ++ op_ctx->map.sgt = sgt; ++ ++ preallocated_vm_bo = drm_gpuvm_bo_create(&vm->base, &bo->base.base); ++ if (!preallocated_vm_bo) { ++ if (!bo->base.base.import_attach) ++ drm_gem_shmem_unpin(&bo->base); ++ ++ ret = -ENOMEM; ++ goto err_cleanup; ++ } ++ ++ mutex_lock(&bo->gpuva_list_lock); ++ op_ctx->map.vm_bo = drm_gpuvm_bo_obtain_prealloc(preallocated_vm_bo); ++ mutex_unlock(&bo->gpuva_list_lock); ++ ++ /* If the a vm_bo for this combination exists, it already ++ * retains a pin ref, and we can release the one we took earlier. ++ * ++ * If our pre-allocated vm_bo is picked, it now retains the pin ref, ++ * which will be released in panthor_vm_bo_put(). ++ */ ++ if (preallocated_vm_bo != op_ctx->map.vm_bo && ++ !bo->base.base.import_attach) ++ drm_gem_shmem_unpin(&bo->base); ++ ++ op_ctx->map.bo_offset = offset; ++ ++ /* L1, L2 and L3 page tables. ++ * We could optimize L3 allocation by iterating over the sgt and merging ++ * 2M contiguous blocks, but it's simpler to over-provision and return ++ * the pages if they're not used. ++ */ ++ pt_count = ((ALIGN(va + size, 1ull << 39) - ALIGN_DOWN(va, 1ull << 39)) >> 39) + ++ ((ALIGN(va + size, 1ull << 30) - ALIGN_DOWN(va, 1ull << 30)) >> 30) + ++ ((ALIGN(va + size, 1ull << 21) - ALIGN_DOWN(va, 1ull << 21)) >> 21); ++ ++ op_ctx->rsvd_page_tables.pages = kcalloc(pt_count, ++ sizeof(*op_ctx->rsvd_page_tables.pages), ++ GFP_KERNEL); ++ if (!op_ctx->rsvd_page_tables.pages) ++ goto err_cleanup; ++ ++ ret = kmem_cache_alloc_bulk(pt_cache, GFP_KERNEL, pt_count, ++ op_ctx->rsvd_page_tables.pages); ++ op_ctx->rsvd_page_tables.count = ret; ++ if (ret != pt_count) { ++ ret = -ENOMEM; ++ goto err_cleanup; ++ } ++ ++ /* Insert BO into the extobj list last, when we know nothing can fail. */ ++ dma_resv_lock(panthor_vm_resv(vm), NULL); ++ drm_gpuvm_bo_extobj_add(op_ctx->map.vm_bo); ++ dma_resv_unlock(panthor_vm_resv(vm)); ++ ++ return 0; ++ ++err_cleanup: ++ panthor_vm_cleanup_op_ctx(op_ctx, vm); ++ return ret; ++} ++ ++static int panthor_vm_prepare_unmap_op_ctx(struct panthor_vm_op_ctx *op_ctx, ++ struct panthor_vm *vm, ++ u64 va, u64 size) ++{ ++ u32 pt_count = 0; ++ int ret; ++ ++ memset(op_ctx, 0, sizeof(*op_ctx)); ++ INIT_LIST_HEAD(&op_ctx->returned_vmas); ++ op_ctx->va.range = size; ++ op_ctx->va.addr = va; ++ op_ctx->flags = DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP; ++ ++ /* Pre-allocate L3 page tables to account for the split-2M-block ++ * situation on unmap. ++ */ ++ if (va != ALIGN(va, SZ_2M)) ++ pt_count++; ++ ++ if (va + size != ALIGN(va + size, SZ_2M) && ++ ALIGN(va + size, SZ_2M) != ALIGN(va, SZ_2M)) ++ pt_count++; ++ ++ ret = panthor_vm_op_ctx_prealloc_vmas(op_ctx); ++ if (ret) ++ goto err_cleanup; ++ ++ if (pt_count) { ++ op_ctx->rsvd_page_tables.pages = kcalloc(pt_count, ++ sizeof(*op_ctx->rsvd_page_tables.pages), ++ GFP_KERNEL); ++ if (!op_ctx->rsvd_page_tables.pages) ++ goto err_cleanup; ++ ++ ret = kmem_cache_alloc_bulk(pt_cache, GFP_KERNEL, pt_count, ++ op_ctx->rsvd_page_tables.pages); ++ if (ret != pt_count) { ++ ret = -ENOMEM; ++ goto err_cleanup; ++ } ++ op_ctx->rsvd_page_tables.count = pt_count; ++ } ++ ++ return 0; ++ ++err_cleanup: ++ panthor_vm_cleanup_op_ctx(op_ctx, vm); ++ return ret; ++} ++ ++static void panthor_vm_prepare_sync_only_op_ctx(struct panthor_vm_op_ctx *op_ctx, ++ struct panthor_vm *vm) ++{ ++ memset(op_ctx, 0, sizeof(*op_ctx)); ++ INIT_LIST_HEAD(&op_ctx->returned_vmas); ++ op_ctx->flags = DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY; ++} ++ ++/** ++ * panthor_vm_get_bo_for_va() - Get the GEM object mapped at a virtual address ++ * @vm: VM to look into. ++ * @va: Virtual address to search for. ++ * @bo_offset: Offset of the GEM object mapped at this virtual address. ++ * Only valid on success. ++ * ++ * The object returned by this function might no longer be mapped when the ++ * function returns. It's the caller responsibility to ensure there's no ++ * concurrent map/unmap operations making the returned value invalid, or ++ * make sure it doesn't matter if the object is no longer mapped. ++ * ++ * Return: A valid pointer on success, an ERR_PTR() otherwise. ++ */ ++struct panthor_gem_object * ++panthor_vm_get_bo_for_va(struct panthor_vm *vm, u64 va, u64 *bo_offset) ++{ ++ struct panthor_gem_object *bo = ERR_PTR(-ENOENT); ++ struct drm_gpuva *gpuva; ++ struct panthor_vma *vma; ++ ++ /* Take the VM lock to prevent concurrent map/unmap operations. */ ++ mutex_lock(&vm->op_lock); ++ gpuva = drm_gpuva_find_first(&vm->base, va, 1); ++ vma = gpuva ? container_of(gpuva, struct panthor_vma, base) : NULL; ++ if (vma && vma->base.gem.obj) { ++ drm_gem_object_get(vma->base.gem.obj); ++ bo = to_panthor_bo(vma->base.gem.obj); ++ *bo_offset = vma->base.gem.offset + (va - vma->base.va.addr); ++ } ++ mutex_unlock(&vm->op_lock); ++ ++ return bo; ++} ++ ++#define PANTHOR_VM_MIN_KERNEL_VA_SIZE SZ_256M ++ ++static u64 ++panthor_vm_create_get_user_va_range(const struct drm_panthor_vm_create *args, ++ u64 full_va_range) ++{ ++ u64 user_va_range; ++ ++ /* Make sure we have a minimum amount of VA space for kernel objects. */ ++ if (full_va_range < PANTHOR_VM_MIN_KERNEL_VA_SIZE) ++ return 0; ++ ++ if (args->user_va_range) { ++ /* Use the user provided value if != 0. */ ++ user_va_range = args->user_va_range; ++ } else if (TASK_SIZE_OF(current) < full_va_range) { ++ /* If the task VM size is smaller than the GPU VA range, pick this ++ * as our default user VA range, so userspace can CPU/GPU map buffers ++ * at the same address. ++ */ ++ user_va_range = TASK_SIZE_OF(current); ++ } else { ++ /* If the GPU VA range is smaller than the task VM size, we ++ * just have to live with the fact we won't be able to map ++ * all buffers at the same GPU/CPU address. ++ * ++ * If the GPU VA range is bigger than 4G (more than 32-bit of ++ * VA), we split the range in two, and assign half of it to ++ * the user and the other half to the kernel, if it's not, we ++ * keep the kernel VA space as small as possible. ++ */ ++ user_va_range = full_va_range > SZ_4G ? ++ full_va_range / 2 : ++ full_va_range - PANTHOR_VM_MIN_KERNEL_VA_SIZE; ++ } ++ ++ if (full_va_range - PANTHOR_VM_MIN_KERNEL_VA_SIZE < user_va_range) ++ user_va_range = full_va_range - PANTHOR_VM_MIN_KERNEL_VA_SIZE; ++ ++ return user_va_range; ++} ++ ++#define PANTHOR_VM_CREATE_FLAGS 0 ++ ++static int ++panthor_vm_create_check_args(const struct panthor_device *ptdev, ++ const struct drm_panthor_vm_create *args, ++ u64 *kernel_va_start, u64 *kernel_va_range) ++{ ++ u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features); ++ u64 full_va_range = 1ull << va_bits; ++ u64 user_va_range; ++ ++ if (args->flags & ~PANTHOR_VM_CREATE_FLAGS) ++ return -EINVAL; ++ ++ user_va_range = panthor_vm_create_get_user_va_range(args, full_va_range); ++ if (!user_va_range || (args->user_va_range && args->user_va_range > user_va_range)) ++ return -EINVAL; ++ ++ /* Pick a kernel VA range that's a power of two, to have a clear split. */ ++ *kernel_va_range = rounddown_pow_of_two(full_va_range - user_va_range); ++ *kernel_va_start = full_va_range - *kernel_va_range; ++ return 0; ++} ++ ++/* ++ * Only 32 VMs per open file. If that becomes a limiting factor, we can ++ * increase this number. ++ */ ++#define PANTHOR_MAX_VMS_PER_FILE 32 ++ ++/** ++ * panthor_vm_pool_create_vm() - Create a VM ++ * @pool: The VM to create this VM on. ++ * @kernel_va_start: Start of the region reserved for kernel objects. ++ * @kernel_va_range: Size of the region reserved for kernel objects. ++ * ++ * Return: a positive VM ID on success, a negative error code otherwise. ++ */ ++int panthor_vm_pool_create_vm(struct panthor_device *ptdev, ++ struct panthor_vm_pool *pool, ++ struct drm_panthor_vm_create *args) ++{ ++ u64 kernel_va_start, kernel_va_range; ++ struct panthor_vm *vm; ++ int ret; ++ u32 id; ++ ++ ret = panthor_vm_create_check_args(ptdev, args, &kernel_va_start, &kernel_va_range); ++ if (ret) ++ return ret; ++ ++ vm = panthor_vm_create(ptdev, false, kernel_va_start, kernel_va_range, ++ kernel_va_start, kernel_va_range); ++ if (IS_ERR(vm)) ++ return PTR_ERR(vm); ++ ++ ret = xa_alloc(&pool->xa, &id, vm, ++ XA_LIMIT(1, PANTHOR_MAX_VMS_PER_FILE), GFP_KERNEL); ++ ++ if (ret) { ++ panthor_vm_put(vm); ++ return ret; ++ } ++ ++ args->user_va_range = kernel_va_start; ++ return id; ++} ++ ++static void panthor_vm_destroy(struct panthor_vm *vm) ++{ ++ if (!vm) ++ return; ++ ++ vm->destroyed = true; ++ ++ mutex_lock(&vm->heaps.lock); ++ panthor_heap_pool_destroy(vm->heaps.pool); ++ vm->heaps.pool = NULL; ++ mutex_unlock(&vm->heaps.lock); ++ ++ drm_WARN_ON(&vm->ptdev->base, ++ panthor_vm_unmap_range(vm, vm->base.mm_start, vm->base.mm_range)); ++ panthor_vm_put(vm); ++} ++ ++/** ++ * panthor_vm_pool_destroy_vm() - Destroy a VM. ++ * @pool: VM pool. ++ * @handle: VM handle. ++ * ++ * This function doesn't free the VM object or its resources, it just kills ++ * all mappings, and makes sure nothing can be mapped after that point. ++ * ++ * If there was any active jobs at the time this function is called, these ++ * jobs should experience page faults and be killed as a result. ++ * ++ * The VM resources are freed when the last reference on the VM object is ++ * dropped. ++ */ ++int panthor_vm_pool_destroy_vm(struct panthor_vm_pool *pool, u32 handle) ++{ ++ struct panthor_vm *vm; ++ ++ vm = xa_erase(&pool->xa, handle); ++ ++ panthor_vm_destroy(vm); ++ ++ return vm ? 0 : -EINVAL; ++} ++ ++/** ++ * panthor_vm_pool_get_vm() - Retrieve VM object bound to a VM handle ++ * @pool: VM pool to check. ++ * @handle: Handle of the VM to retrieve. ++ * ++ * Return: A valid pointer if the VM exists, NULL otherwise. ++ */ ++struct panthor_vm * ++panthor_vm_pool_get_vm(struct panthor_vm_pool *pool, u32 handle) ++{ ++ struct panthor_vm *vm; ++ ++ vm = panthor_vm_get(xa_load(&pool->xa, handle)); ++ ++ return vm; ++} ++ ++/** ++ * panthor_vm_pool_destroy() - Destroy a VM pool. ++ * @pfile: File. ++ * ++ * Destroy all VMs in the pool, and release the pool resources. ++ * ++ * Note that VMs can outlive the pool they were created from if other ++ * objects hold a reference to there VMs. ++ */ ++void panthor_vm_pool_destroy(struct panthor_file *pfile) ++{ ++ struct panthor_vm *vm; ++ unsigned long i; ++ ++ if (!pfile->vms) ++ return; ++ ++ xa_for_each(&pfile->vms->xa, i, vm) ++ panthor_vm_destroy(vm); ++ ++ xa_destroy(&pfile->vms->xa); ++ kfree(pfile->vms); ++} ++ ++/** ++ * panthor_vm_pool_create() - Create a VM pool ++ * @pfile: File. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_vm_pool_create(struct panthor_file *pfile) ++{ ++ pfile->vms = kzalloc(sizeof(*pfile->vms), GFP_KERNEL); ++ if (!pfile->vms) ++ return -ENOMEM; ++ ++ xa_init_flags(&pfile->vms->xa, XA_FLAGS_ALLOC1); ++ return 0; ++} ++ ++/* dummy TLB ops, the real TLB flush happens in panthor_vm_flush_range() */ ++static void mmu_tlb_flush_all(void *cookie) ++{ ++} ++ ++static void mmu_tlb_flush_walk(unsigned long iova, size_t size, size_t granule, void *cookie) ++{ ++} ++ ++static const struct iommu_flush_ops mmu_tlb_ops = { ++ .tlb_flush_all = mmu_tlb_flush_all, ++ .tlb_flush_walk = mmu_tlb_flush_walk, ++}; ++ ++static const char *access_type_name(struct panthor_device *ptdev, ++ u32 fault_status) ++{ ++ switch (fault_status & AS_FAULTSTATUS_ACCESS_TYPE_MASK) { ++ case AS_FAULTSTATUS_ACCESS_TYPE_ATOMIC: ++ return "ATOMIC"; ++ case AS_FAULTSTATUS_ACCESS_TYPE_READ: ++ return "READ"; ++ case AS_FAULTSTATUS_ACCESS_TYPE_WRITE: ++ return "WRITE"; ++ case AS_FAULTSTATUS_ACCESS_TYPE_EX: ++ return "EXECUTE"; ++ default: ++ drm_WARN_ON(&ptdev->base, 1); ++ return NULL; ++ } ++} ++ ++static void panthor_mmu_irq_handler(struct panthor_device *ptdev, u32 status) ++{ ++ bool has_unhandled_faults = false; ++ ++ status = panthor_mmu_fault_mask(ptdev, status); ++ while (status) { ++ u32 as = ffs(status | (status >> 16)) - 1; ++ u32 mask = panthor_mmu_as_fault_mask(ptdev, as); ++ u32 new_int_mask; ++ u64 addr; ++ u32 fault_status; ++ u32 exception_type; ++ u32 access_type; ++ u32 source_id; ++ ++ fault_status = gpu_read(ptdev, AS_FAULTSTATUS(as)); ++ addr = gpu_read(ptdev, AS_FAULTADDRESS_LO(as)); ++ addr |= (u64)gpu_read(ptdev, AS_FAULTADDRESS_HI(as)) << 32; ++ ++ /* decode the fault status */ ++ exception_type = fault_status & 0xFF; ++ access_type = (fault_status >> 8) & 0x3; ++ source_id = (fault_status >> 16); ++ ++ mutex_lock(&ptdev->mmu->as.slots_lock); ++ ++ ptdev->mmu->as.faulty_mask |= mask; ++ new_int_mask = ++ panthor_mmu_fault_mask(ptdev, ~ptdev->mmu->as.faulty_mask); ++ ++ /* terminal fault, print info about the fault */ ++ drm_err(&ptdev->base, ++ "Unhandled Page fault in AS%d at VA 0x%016llX\n" ++ "raw fault status: 0x%X\n" ++ "decoded fault status: %s\n" ++ "exception type 0x%X: %s\n" ++ "access type 0x%X: %s\n" ++ "source id 0x%X\n", ++ as, addr, ++ fault_status, ++ (fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"), ++ exception_type, panthor_exception_name(ptdev, exception_type), ++ access_type, access_type_name(ptdev, fault_status), ++ source_id); ++ ++ /* Ignore MMU interrupts on this AS until it's been ++ * re-enabled. ++ */ ++ ptdev->mmu->irq.mask = new_int_mask; ++ gpu_write(ptdev, MMU_INT_MASK, new_int_mask); ++ ++ if (ptdev->mmu->as.slots[as].vm) ++ ptdev->mmu->as.slots[as].vm->unhandled_fault = true; ++ ++ /* Disable the MMU to kill jobs on this AS. */ ++ panthor_mmu_as_disable(ptdev, as); ++ mutex_unlock(&ptdev->mmu->as.slots_lock); ++ ++ status &= ~mask; ++ has_unhandled_faults = true; ++ } ++ ++ if (has_unhandled_faults) ++ panthor_sched_report_mmu_fault(ptdev); ++} ++PANTHOR_IRQ_HANDLER(mmu, MMU, panthor_mmu_irq_handler); ++ ++/** ++ * panthor_mmu_suspend() - Suspend the MMU logic ++ * @ptdev: Device. ++ * ++ * All we do here is de-assign the AS slots on all active VMs, so things ++ * get flushed to the main memory, and no further access to these VMs are ++ * possible. ++ * ++ * We also suspend the MMU IRQ. ++ */ ++void panthor_mmu_suspend(struct panthor_device *ptdev) ++{ ++ mutex_lock(&ptdev->mmu->as.slots_lock); ++ for (u32 i = 0; i < ARRAY_SIZE(ptdev->mmu->as.slots); i++) { ++ struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm; ++ ++ if (vm) { ++ drm_WARN_ON(&ptdev->base, panthor_mmu_as_disable(ptdev, i)); ++ panthor_vm_release_as_locked(vm); ++ } ++ } ++ mutex_unlock(&ptdev->mmu->as.slots_lock); ++ ++ panthor_mmu_irq_suspend(&ptdev->mmu->irq); ++} ++ ++/** ++ * panthor_mmu_resume() - Resume the MMU logic ++ * @ptdev: Device. ++ * ++ * Resume the IRQ. ++ * ++ * We don't re-enable previously active VMs. We assume other parts of the ++ * driver will call panthor_vm_active() on the VMs they intend to use. ++ */ ++void panthor_mmu_resume(struct panthor_device *ptdev) ++{ ++ mutex_lock(&ptdev->mmu->as.slots_lock); ++ ptdev->mmu->as.alloc_mask = 0; ++ ptdev->mmu->as.faulty_mask = 0; ++ mutex_unlock(&ptdev->mmu->as.slots_lock); ++ ++ panthor_mmu_irq_resume(&ptdev->mmu->irq, panthor_mmu_fault_mask(ptdev, ~0)); ++} ++ ++/** ++ * panthor_mmu_pre_reset() - Prepare for a reset ++ * @ptdev: Device. ++ * ++ * Suspend the IRQ, and make sure all VM_BIND queues are stopped, so we ++ * don't get asked to do a VM operation while the GPU is down. ++ * ++ * We don't cleanly shutdown the AS slots here, because the reset might ++ * come from an AS_ACTIVE_BIT stuck situation. ++ */ ++void panthor_mmu_pre_reset(struct panthor_device *ptdev) ++{ ++ struct panthor_vm *vm; ++ ++ panthor_mmu_irq_suspend(&ptdev->mmu->irq); ++ ++ mutex_lock(&ptdev->mmu->vm.lock); ++ ptdev->mmu->vm.reset_in_progress = true; ++ list_for_each_entry(vm, &ptdev->mmu->vm.list, node) ++ panthor_vm_stop(vm); ++ mutex_unlock(&ptdev->mmu->vm.lock); ++} ++ ++/** ++ * panthor_mmu_post_reset() - Restore things after a reset ++ * @ptdev: Device. ++ * ++ * Put the MMU logic back in action after a reset. That implies resuming the ++ * IRQ and re-enabling the VM_BIND queues. ++ */ ++void panthor_mmu_post_reset(struct panthor_device *ptdev) ++{ ++ struct panthor_vm *vm; ++ ++ mutex_lock(&ptdev->mmu->as.slots_lock); ++ ++ /* Now that the reset is effective, we can assume that none of the ++ * AS slots are setup, and clear the faulty flags too. ++ */ ++ ptdev->mmu->as.alloc_mask = 0; ++ ptdev->mmu->as.faulty_mask = 0; ++ ++ for (u32 i = 0; i < ARRAY_SIZE(ptdev->mmu->as.slots); i++) { ++ struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm; ++ ++ if (vm) ++ panthor_vm_release_as_locked(vm); ++ } ++ ++ mutex_unlock(&ptdev->mmu->as.slots_lock); ++ ++ panthor_mmu_irq_resume(&ptdev->mmu->irq, panthor_mmu_fault_mask(ptdev, ~0)); ++ ++ /* Restart the VM_BIND queues. */ ++ mutex_lock(&ptdev->mmu->vm.lock); ++ list_for_each_entry(vm, &ptdev->mmu->vm.list, node) { ++ panthor_vm_start(vm); ++ } ++ ptdev->mmu->vm.reset_in_progress = false; ++ mutex_unlock(&ptdev->mmu->vm.lock); ++} ++ ++static void panthor_vm_free(struct drm_gpuvm *gpuvm) ++{ ++ struct panthor_vm *vm = container_of(gpuvm, struct panthor_vm, base); ++ struct panthor_device *ptdev = vm->ptdev; ++ ++ mutex_lock(&vm->heaps.lock); ++ if (drm_WARN_ON(&ptdev->base, vm->heaps.pool)) ++ panthor_heap_pool_destroy(vm->heaps.pool); ++ mutex_unlock(&vm->heaps.lock); ++ mutex_destroy(&vm->heaps.lock); ++ ++ mutex_lock(&ptdev->mmu->vm.lock); ++ list_del(&vm->node); ++ /* Restore the scheduler state so we can call drm_sched_entity_destroy() ++ * and drm_sched_fini(). If get there, that means we have no job left ++ * and no new jobs can be queued, so we can start the scheduler without ++ * risking interfering with the reset. ++ */ ++ if (ptdev->mmu->vm.reset_in_progress) ++ panthor_vm_start(vm); ++ mutex_unlock(&ptdev->mmu->vm.lock); ++ ++ drm_sched_entity_destroy(&vm->entity); ++ drm_sched_fini(&vm->sched); ++ ++ mutex_lock(&ptdev->mmu->as.slots_lock); ++ if (vm->as.id >= 0) { ++ int cookie; ++ ++ if (drm_dev_enter(&ptdev->base, &cookie)) { ++ panthor_mmu_as_disable(ptdev, vm->as.id); ++ drm_dev_exit(cookie); ++ } ++ ++ ptdev->mmu->as.slots[vm->as.id].vm = NULL; ++ clear_bit(vm->as.id, &ptdev->mmu->as.alloc_mask); ++ list_del(&vm->as.lru_node); ++ } ++ mutex_unlock(&ptdev->mmu->as.slots_lock); ++ ++ free_io_pgtable_ops(vm->pgtbl_ops); ++ ++ drm_mm_takedown(&vm->mm); ++ kfree(vm); ++} ++ ++/** ++ * panthor_vm_put() - Release a reference on a VM ++ * @vm: VM to release the reference on. Can be NULL. ++ */ ++void panthor_vm_put(struct panthor_vm *vm) ++{ ++ drm_gpuvm_put(vm ? &vm->base : NULL); ++} ++ ++/** ++ * panthor_vm_get() - Get a VM reference ++ * @vm: VM to get the reference on. Can be NULL. ++ * ++ * Return: @vm value. ++ */ ++struct panthor_vm *panthor_vm_get(struct panthor_vm *vm) ++{ ++ if (vm) ++ drm_gpuvm_get(&vm->base); ++ ++ return vm; ++} ++ ++/** ++ * panthor_vm_get_heap_pool() - Get the heap pool attached to a VM ++ * @vm: VM to query the heap pool on. ++ * @create: True if the heap pool should be created when it doesn't exist. ++ * ++ * Heap pools are per-VM. This function allows one to retrieve the heap pool ++ * attached to a VM. ++ * ++ * If no heap pool exists yet, and @create is true, we create one. ++ * ++ * The returned panthor_heap_pool should be released with panthor_heap_pool_put(). ++ * ++ * Return: A valid pointer on success, an ERR_PTR() otherwise. ++ */ ++struct panthor_heap_pool *panthor_vm_get_heap_pool(struct panthor_vm *vm, bool create) ++{ ++ struct panthor_heap_pool *pool; ++ ++ mutex_lock(&vm->heaps.lock); ++ if (!vm->heaps.pool && create) { ++ if (vm->destroyed) ++ pool = ERR_PTR(-EINVAL); ++ else ++ pool = panthor_heap_pool_create(vm->ptdev, vm); ++ ++ if (!IS_ERR(pool)) ++ vm->heaps.pool = panthor_heap_pool_get(pool); ++ } else { ++ pool = panthor_heap_pool_get(vm->heaps.pool); ++ } ++ mutex_unlock(&vm->heaps.lock); ++ ++ return pool; ++} ++ ++static u64 mair_to_memattr(u64 mair) ++{ ++ u64 memattr = 0; ++ u32 i; ++ ++ for (i = 0; i < 8; i++) { ++ u8 in_attr = mair >> (8 * i), out_attr; ++ u8 outer = in_attr >> 4, inner = in_attr & 0xf; ++ ++ /* For caching to be enabled, inner and outer caching policy ++ * have to be both write-back, if one of them is write-through ++ * or non-cacheable, we just choose non-cacheable. Device ++ * memory is also translated to non-cacheable. ++ */ ++ if (!(outer & 3) || !(outer & 4) || !(inner & 4)) { ++ out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_NC | ++ AS_MEMATTR_AARCH64_SH_MIDGARD_INNER | ++ AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(false, false); ++ } else { ++ /* Use SH_CPU_INNER mode so SH_IS, which is used when ++ * IOMMU_CACHE is set, actually maps to the standard ++ * definition of inner-shareable and not Mali's ++ * internal-shareable mode. ++ */ ++ out_attr = AS_MEMATTR_AARCH64_INNER_OUTER_WB | ++ AS_MEMATTR_AARCH64_SH_CPU_INNER | ++ AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(inner & 1, inner & 2); ++ } ++ ++ memattr |= (u64)out_attr << (8 * i); ++ } ++ ++ return memattr; ++} ++ ++static void panthor_vma_link(struct panthor_vm *vm, ++ struct panthor_vma *vma, ++ struct drm_gpuvm_bo *vm_bo) ++{ ++ struct panthor_gem_object *bo = to_panthor_bo(vma->base.gem.obj); ++ ++ mutex_lock(&bo->gpuva_list_lock); ++ drm_gpuva_link(&vma->base, vm_bo); ++ drm_WARN_ON(&vm->ptdev->base, drm_gpuvm_bo_put(vm_bo)); ++ mutex_unlock(&bo->gpuva_list_lock); ++} ++ ++static void panthor_vma_unlink(struct panthor_vm *vm, ++ struct panthor_vma *vma) ++{ ++ struct panthor_gem_object *bo = to_panthor_bo(vma->base.gem.obj); ++ struct drm_gpuvm_bo *vm_bo = drm_gpuvm_bo_get(vma->base.vm_bo); ++ ++ mutex_lock(&bo->gpuva_list_lock); ++ drm_gpuva_unlink(&vma->base); ++ mutex_unlock(&bo->gpuva_list_lock); ++ ++ /* drm_gpuva_unlink() release the vm_bo, but we manually retained it ++ * when entering this function, so we can implement deferred VMA ++ * destruction. Re-assign it here. ++ */ ++ vma->base.vm_bo = vm_bo; ++ list_add_tail(&vma->node, &vm->op_ctx->returned_vmas); ++} ++ ++static void panthor_vma_init(struct panthor_vma *vma, u32 flags) ++{ ++ INIT_LIST_HEAD(&vma->node); ++ vma->flags = flags; ++} ++ ++#define PANTHOR_VM_MAP_FLAGS \ ++ (DRM_PANTHOR_VM_BIND_OP_MAP_READONLY | \ ++ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | \ ++ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED) ++ ++static int panthor_gpuva_sm_step_map(struct drm_gpuva_op *op, void *priv) ++{ ++ struct panthor_vm *vm = priv; ++ struct panthor_vm_op_ctx *op_ctx = vm->op_ctx; ++ struct panthor_vma *vma = panthor_vm_op_ctx_get_vma(op_ctx); ++ int ret; ++ ++ if (!vma) ++ return -EINVAL; ++ ++ panthor_vma_init(vma, op_ctx->flags & PANTHOR_VM_MAP_FLAGS); ++ ++ ret = panthor_vm_map_pages(vm, op->map.va.addr, flags_to_prot(vma->flags), ++ op_ctx->map.sgt, op->map.gem.offset, ++ op->map.va.range); ++ if (ret) ++ return ret; ++ ++ /* Ref owned by the mapping now, clear the obj field so we don't release the ++ * pinning/obj ref behind GPUVA's back. ++ */ ++ drm_gpuva_map(&vm->base, &vma->base, &op->map); ++ panthor_vma_link(vm, vma, op_ctx->map.vm_bo); ++ op_ctx->map.vm_bo = NULL; ++ return 0; ++} ++ ++static int panthor_gpuva_sm_step_remap(struct drm_gpuva_op *op, ++ void *priv) ++{ ++ struct panthor_vma *unmap_vma = container_of(op->remap.unmap->va, struct panthor_vma, base); ++ struct panthor_vm *vm = priv; ++ struct panthor_vm_op_ctx *op_ctx = vm->op_ctx; ++ struct panthor_vma *prev_vma = NULL, *next_vma = NULL; ++ u64 unmap_start, unmap_range; ++ int ret; ++ ++ drm_gpuva_op_remap_to_unmap_range(&op->remap, &unmap_start, &unmap_range); ++ ret = panthor_vm_unmap_pages(vm, unmap_start, unmap_range); ++ if (ret) ++ return ret; ++ ++ if (op->remap.prev) { ++ prev_vma = panthor_vm_op_ctx_get_vma(op_ctx); ++ panthor_vma_init(prev_vma, unmap_vma->flags); ++ } ++ ++ if (op->remap.next) { ++ next_vma = panthor_vm_op_ctx_get_vma(op_ctx); ++ panthor_vma_init(next_vma, unmap_vma->flags); ++ } ++ ++ drm_gpuva_remap(prev_vma ? &prev_vma->base : NULL, ++ next_vma ? &next_vma->base : NULL, ++ &op->remap); ++ ++ if (prev_vma) { ++ /* panthor_vma_link() transfers the vm_bo ownership to ++ * the VMA object. Since the vm_bo we're passing is still ++ * owned by the old mapping which will be released when this ++ * mapping is destroyed, we need to grab a ref here. ++ */ ++ panthor_vma_link(vm, prev_vma, ++ drm_gpuvm_bo_get(op->remap.unmap->va->vm_bo)); ++ } ++ ++ if (next_vma) { ++ panthor_vma_link(vm, next_vma, ++ drm_gpuvm_bo_get(op->remap.unmap->va->vm_bo)); ++ } ++ ++ panthor_vma_unlink(vm, unmap_vma); ++ return 0; ++} ++ ++static int panthor_gpuva_sm_step_unmap(struct drm_gpuva_op *op, ++ void *priv) ++{ ++ struct panthor_vma *unmap_vma = container_of(op->unmap.va, struct panthor_vma, base); ++ struct panthor_vm *vm = priv; ++ int ret; ++ ++ ret = panthor_vm_unmap_pages(vm, unmap_vma->base.va.addr, ++ unmap_vma->base.va.range); ++ if (drm_WARN_ON(&vm->ptdev->base, ret)) ++ return ret; ++ ++ drm_gpuva_unmap(&op->unmap); ++ panthor_vma_unlink(vm, unmap_vma); ++ return 0; ++} ++ ++static const struct drm_gpuvm_ops panthor_gpuvm_ops = { ++ .vm_free = panthor_vm_free, ++ .sm_step_map = panthor_gpuva_sm_step_map, ++ .sm_step_remap = panthor_gpuva_sm_step_remap, ++ .sm_step_unmap = panthor_gpuva_sm_step_unmap, ++}; ++ ++/** ++ * panthor_vm_resv() - Get the dma_resv object attached to a VM. ++ * @vm: VM to get the dma_resv of. ++ * ++ * Return: A dma_resv object. ++ */ ++struct dma_resv *panthor_vm_resv(struct panthor_vm *vm) ++{ ++ return drm_gpuvm_resv(&vm->base); ++} ++ ++struct drm_gem_object *panthor_vm_root_gem(struct panthor_vm *vm) ++{ ++ if (!vm) ++ return NULL; ++ ++ return vm->base.r_obj; ++} ++ ++static int ++panthor_vm_exec_op(struct panthor_vm *vm, struct panthor_vm_op_ctx *op, ++ bool flag_vm_unusable_on_failure) ++{ ++ u32 op_type = op->flags & DRM_PANTHOR_VM_BIND_OP_TYPE_MASK; ++ int ret; ++ ++ if (op_type == DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY) ++ return 0; ++ ++ mutex_lock(&vm->op_lock); ++ vm->op_ctx = op; ++ switch (op_type) { ++ case DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: ++ if (vm->unusable) { ++ ret = -EINVAL; ++ break; ++ } ++ ++ ret = drm_gpuvm_sm_map(&vm->base, vm, op->va.addr, op->va.range, ++ op->map.vm_bo->obj, op->map.bo_offset); ++ break; ++ ++ case DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP: ++ ret = drm_gpuvm_sm_unmap(&vm->base, vm, op->va.addr, op->va.range); ++ break; ++ ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ if (ret && flag_vm_unusable_on_failure) ++ vm->unusable = true; ++ ++ vm->op_ctx = NULL; ++ mutex_unlock(&vm->op_lock); ++ ++ return ret; ++} ++ ++static struct dma_fence * ++panthor_vm_bind_run_job(struct drm_sched_job *sched_job) ++{ ++ struct panthor_vm_bind_job *job = container_of(sched_job, struct panthor_vm_bind_job, base); ++ bool cookie; ++ int ret; ++ ++ /* Not only we report an error whose result is propagated to the ++ * drm_sched finished fence, but we also flag the VM as unusable, because ++ * a failure in the async VM_BIND results in an inconsistent state. VM needs ++ * to be destroyed and recreated. ++ */ ++ cookie = dma_fence_begin_signalling(); ++ ret = panthor_vm_exec_op(job->vm, &job->ctx, true); ++ dma_fence_end_signalling(cookie); ++ ++ return ret ? ERR_PTR(ret) : NULL; ++} ++ ++static void panthor_vm_bind_job_release(struct kref *kref) ++{ ++ struct panthor_vm_bind_job *job = container_of(kref, struct panthor_vm_bind_job, refcount); ++ ++ if (job->base.s_fence) ++ drm_sched_job_cleanup(&job->base); ++ ++ panthor_vm_cleanup_op_ctx(&job->ctx, job->vm); ++ panthor_vm_put(job->vm); ++ kfree(job); ++} ++ ++/** ++ * panthor_vm_bind_job_put() - Release a VM_BIND job reference ++ * @sched_job: Job to release the reference on. ++ */ ++void panthor_vm_bind_job_put(struct drm_sched_job *sched_job) ++{ ++ struct panthor_vm_bind_job *job = ++ container_of(sched_job, struct panthor_vm_bind_job, base); ++ ++ if (sched_job) ++ kref_put(&job->refcount, panthor_vm_bind_job_release); ++} ++ ++static void ++panthor_vm_bind_free_job(struct drm_sched_job *sched_job) ++{ ++ struct panthor_vm_bind_job *job = ++ container_of(sched_job, struct panthor_vm_bind_job, base); ++ ++ drm_sched_job_cleanup(sched_job); ++ ++ /* Do the heavy cleanups asynchronously, so we're out of the ++ * dma-signaling path and can acquire dma-resv locks safely. ++ */ ++ queue_work(panthor_cleanup_wq, &job->cleanup_op_ctx_work); ++} ++ ++static enum drm_gpu_sched_stat ++panthor_vm_bind_timedout_job(struct drm_sched_job *sched_job) ++{ ++ WARN(1, "VM_BIND ops are synchronous for now, there should be no timeout!"); ++ return DRM_GPU_SCHED_STAT_NOMINAL; ++} ++ ++static const struct drm_sched_backend_ops panthor_vm_bind_ops = { ++ .run_job = panthor_vm_bind_run_job, ++ .free_job = panthor_vm_bind_free_job, ++ .timedout_job = panthor_vm_bind_timedout_job, ++}; ++ ++/** ++ * panthor_vm_create() - Create a VM ++ * @ptdev: Device. ++ * @for_mcu: True if this is the FW MCU VM. ++ * @kernel_va_start: Start of the range reserved for kernel BO mapping. ++ * @kernel_va_size: Size of the range reserved for kernel BO mapping. ++ * @auto_kernel_va_start: Start of the auto-VA kernel range. ++ * @auto_kernel_va_size: Size of the auto-VA kernel range. ++ * ++ * Return: A valid pointer on success, an ERR_PTR() otherwise. ++ */ ++struct panthor_vm * ++panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, ++ u64 kernel_va_start, u64 kernel_va_size, ++ u64 auto_kernel_va_start, u64 auto_kernel_va_size) ++{ ++ u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features); ++ u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(ptdev->gpu_info.mmu_features); ++ u64 full_va_range = 1ull << va_bits; ++ struct drm_gem_object *dummy_gem; ++ struct drm_gpu_scheduler *sched; ++ struct io_pgtable_cfg pgtbl_cfg; ++ u64 mair, min_va, va_range; ++ struct panthor_vm *vm; ++ int ret; ++ ++ vm = kzalloc(sizeof(*vm), GFP_KERNEL); ++ if (!vm) ++ return ERR_PTR(-ENOMEM); ++ ++ /* We allocate a dummy GEM for the VM. */ ++ dummy_gem = drm_gpuvm_resv_object_alloc(&ptdev->base); ++ if (!dummy_gem) { ++ ret = -ENOMEM; ++ goto err_free_vm; ++ } ++ ++ mutex_init(&vm->heaps.lock); ++ vm->for_mcu = for_mcu; ++ vm->ptdev = ptdev; ++ mutex_init(&vm->op_lock); ++ ++ if (for_mcu) { ++ /* CSF MCU is a cortex M7, and can only address 4G */ ++ min_va = 0; ++ va_range = SZ_4G; ++ } else { ++ min_va = 0; ++ va_range = full_va_range; ++ } ++ ++ mutex_init(&vm->mm_lock); ++ drm_mm_init(&vm->mm, kernel_va_start, kernel_va_size); ++ vm->kernel_auto_va.start = auto_kernel_va_start; ++ vm->kernel_auto_va.end = vm->kernel_auto_va.start + auto_kernel_va_size - 1; ++ ++ INIT_LIST_HEAD(&vm->node); ++ INIT_LIST_HEAD(&vm->as.lru_node); ++ vm->as.id = -1; ++ refcount_set(&vm->as.active_cnt, 0); ++ ++ pgtbl_cfg = (struct io_pgtable_cfg) { ++ .pgsize_bitmap = SZ_4K | SZ_2M, ++ .ias = va_bits, ++ .oas = pa_bits, ++ .coherent_walk = ptdev->coherent, ++ .tlb = &mmu_tlb_ops, ++ .iommu_dev = ptdev->base.dev, ++ .alloc = alloc_pt, ++ .free = free_pt, ++ }; ++ ++ vm->pgtbl_ops = alloc_io_pgtable_ops(ARM_64_LPAE_S1, &pgtbl_cfg, vm); ++ if (!vm->pgtbl_ops) { ++ ret = -EINVAL; ++ goto err_mm_takedown; ++ } ++ ++ /* Bind operations are synchronous for now, no timeout needed. */ ++ ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, ptdev->mmu->vm.wq, ++ 1, 1, 0, ++ MAX_SCHEDULE_TIMEOUT, NULL, NULL, ++ "panthor-vm-bind", ptdev->base.dev); ++ if (ret) ++ goto err_free_io_pgtable; ++ ++ sched = &vm->sched; ++ ret = drm_sched_entity_init(&vm->entity, 0, &sched, 1, NULL); ++ if (ret) ++ goto err_sched_fini; ++ ++ mair = io_pgtable_ops_to_pgtable(vm->pgtbl_ops)->cfg.arm_lpae_s1_cfg.mair; ++ vm->memattr = mair_to_memattr(mair); ++ ++ mutex_lock(&ptdev->mmu->vm.lock); ++ list_add_tail(&vm->node, &ptdev->mmu->vm.list); ++ ++ /* If a reset is in progress, stop the scheduler. */ ++ if (ptdev->mmu->vm.reset_in_progress) ++ panthor_vm_stop(vm); ++ mutex_unlock(&ptdev->mmu->vm.lock); ++ ++ /* We intentionally leave the reserved range to zero, because we want kernel VMAs ++ * to be handled the same way user VMAs are. ++ */ ++ drm_gpuvm_init(&vm->base, for_mcu ? "panthor-MCU-VM" : "panthor-GPU-VM", ++ DRM_GPUVM_RESV_PROTECTED, &ptdev->base, dummy_gem, ++ min_va, va_range, 0, 0, &panthor_gpuvm_ops); ++ drm_gem_object_put(dummy_gem); ++ return vm; ++ ++err_sched_fini: ++ drm_sched_fini(&vm->sched); ++ ++err_free_io_pgtable: ++ free_io_pgtable_ops(vm->pgtbl_ops); ++ ++err_mm_takedown: ++ drm_mm_takedown(&vm->mm); ++ drm_gem_object_put(dummy_gem); ++ ++err_free_vm: ++ kfree(vm); ++ return ERR_PTR(ret); ++} ++ ++static int ++panthor_vm_bind_prepare_op_ctx(struct drm_file *file, ++ struct panthor_vm *vm, ++ const struct drm_panthor_vm_bind_op *op, ++ struct panthor_vm_op_ctx *op_ctx) ++{ ++ struct drm_gem_object *gem; ++ int ret; ++ ++ /* Aligned on page size. */ ++ if ((op->va | op->size) & ~PAGE_MASK) ++ return -EINVAL; ++ ++ switch (op->flags & DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) { ++ case DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: ++ gem = drm_gem_object_lookup(file, op->bo_handle); ++ ret = panthor_vm_prepare_map_op_ctx(op_ctx, vm, ++ gem ? to_panthor_bo(gem) : NULL, ++ op->bo_offset, ++ op->size, ++ op->va, ++ op->flags); ++ drm_gem_object_put(gem); ++ return ret; ++ ++ case DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP: ++ if (op->flags & ~DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) ++ return -EINVAL; ++ ++ if (op->bo_handle || op->bo_offset) ++ return -EINVAL; ++ ++ return panthor_vm_prepare_unmap_op_ctx(op_ctx, vm, op->va, op->size); ++ ++ case DRM_PANTHOR_VM_BIND_OP_TYPE_SYNC_ONLY: ++ if (op->flags & ~DRM_PANTHOR_VM_BIND_OP_TYPE_MASK) ++ return -EINVAL; ++ ++ if (op->bo_handle || op->bo_offset) ++ return -EINVAL; ++ ++ if (op->va || op->size) ++ return -EINVAL; ++ ++ if (!op->syncs.count) ++ return -EINVAL; ++ ++ panthor_vm_prepare_sync_only_op_ctx(op_ctx, vm); ++ return 0; ++ ++ default: ++ return -EINVAL; ++ } ++} ++ ++static void panthor_vm_bind_job_cleanup_op_ctx_work(struct work_struct *work) ++{ ++ struct panthor_vm_bind_job *job = ++ container_of(work, struct panthor_vm_bind_job, cleanup_op_ctx_work); ++ ++ panthor_vm_bind_job_put(&job->base); ++} ++ ++/** ++ * panthor_vm_bind_job_create() - Create a VM_BIND job ++ * @file: File. ++ * @vm: VM targeted by the VM_BIND job. ++ * @op: VM operation data. ++ * ++ * Return: A valid pointer on success, an ERR_PTR() otherwise. ++ */ ++struct drm_sched_job * ++panthor_vm_bind_job_create(struct drm_file *file, ++ struct panthor_vm *vm, ++ const struct drm_panthor_vm_bind_op *op) ++{ ++ struct panthor_vm_bind_job *job; ++ int ret; ++ ++ if (!vm) ++ return ERR_PTR(-EINVAL); ++ ++ if (vm->destroyed || vm->unusable) ++ return ERR_PTR(-EINVAL); ++ ++ job = kzalloc(sizeof(*job), GFP_KERNEL); ++ if (!job) ++ return ERR_PTR(-ENOMEM); ++ ++ ret = panthor_vm_bind_prepare_op_ctx(file, vm, op, &job->ctx); ++ if (ret) { ++ kfree(job); ++ return ERR_PTR(ret); ++ } ++ ++ INIT_WORK(&job->cleanup_op_ctx_work, panthor_vm_bind_job_cleanup_op_ctx_work); ++ kref_init(&job->refcount); ++ job->vm = panthor_vm_get(vm); ++ ++ ret = drm_sched_job_init(&job->base, &vm->entity, 1, vm); ++ if (ret) ++ goto err_put_job; ++ ++ return &job->base; ++ ++err_put_job: ++ panthor_vm_bind_job_put(&job->base); ++ return ERR_PTR(ret); ++} ++ ++/** ++ * panthor_vm_bind_job_prepare_resvs() - Prepare VM_BIND job dma_resvs ++ * @exec: The locking/preparation context. ++ * @sched_job: The job to prepare resvs on. ++ * ++ * Locks and prepare the VM resv. ++ * ++ * If this is a map operation, locks and prepares the GEM resv. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_vm_bind_job_prepare_resvs(struct drm_exec *exec, ++ struct drm_sched_job *sched_job) ++{ ++ struct panthor_vm_bind_job *job = container_of(sched_job, struct panthor_vm_bind_job, base); ++ int ret; ++ ++ /* Acquire the VM lock an reserve a slot for this VM bind job. */ ++ ret = drm_gpuvm_prepare_vm(&job->vm->base, exec, 1); ++ if (ret) ++ return ret; ++ ++ if (job->ctx.map.vm_bo) { ++ /* Lock/prepare the GEM being mapped. */ ++ ret = drm_exec_prepare_obj(exec, job->ctx.map.vm_bo->obj, 1); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * panthor_vm_bind_job_update_resvs() - Update the resv objects touched by a job ++ * @exec: drm_exec context. ++ * @sched_job: Job to update the resvs on. ++ */ ++void panthor_vm_bind_job_update_resvs(struct drm_exec *exec, ++ struct drm_sched_job *sched_job) ++{ ++ struct panthor_vm_bind_job *job = container_of(sched_job, struct panthor_vm_bind_job, base); ++ ++ /* Explicit sync => we just register our job finished fence as bookkeep. */ ++ drm_gpuvm_resv_add_fence(&job->vm->base, exec, ++ &sched_job->s_fence->finished, ++ DMA_RESV_USAGE_BOOKKEEP, ++ DMA_RESV_USAGE_BOOKKEEP); ++} ++ ++void panthor_vm_update_resvs(struct panthor_vm *vm, struct drm_exec *exec, ++ struct dma_fence *fence, ++ enum dma_resv_usage private_usage, ++ enum dma_resv_usage extobj_usage) ++{ ++ drm_gpuvm_resv_add_fence(&vm->base, exec, fence, private_usage, extobj_usage); ++} ++ ++/** ++ * panthor_vm_bind_exec_sync_op() - Execute a VM_BIND operation synchronously. ++ * @file: File. ++ * @vm: VM targeted by the VM operation. ++ * @op: Data describing the VM operation. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_vm_bind_exec_sync_op(struct drm_file *file, ++ struct panthor_vm *vm, ++ struct drm_panthor_vm_bind_op *op) ++{ ++ struct panthor_vm_op_ctx op_ctx; ++ int ret; ++ ++ /* No sync objects allowed on synchronous operations. */ ++ if (op->syncs.count) ++ return -EINVAL; ++ ++ if (!op->size) ++ return 0; ++ ++ ret = panthor_vm_bind_prepare_op_ctx(file, vm, op, &op_ctx); ++ if (ret) ++ return ret; ++ ++ ret = panthor_vm_exec_op(vm, &op_ctx, false); ++ panthor_vm_cleanup_op_ctx(&op_ctx, vm); ++ ++ return ret; ++} ++ ++/** ++ * panthor_vm_map_bo_range() - Map a GEM object range to a VM ++ * @vm: VM to map the GEM to. ++ * @bo: GEM object to map. ++ * @offset: Offset in the GEM object. ++ * @size: Size to map. ++ * @va: Virtual address to map the object to. ++ * @flags: Combination of drm_panthor_vm_bind_op_flags flags. ++ * Only map-related flags are valid. ++ * ++ * Internal use only. For userspace requests, use ++ * panthor_vm_bind_exec_sync_op() instead. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_vm_map_bo_range(struct panthor_vm *vm, struct panthor_gem_object *bo, ++ u64 offset, u64 size, u64 va, u32 flags) ++{ ++ struct panthor_vm_op_ctx op_ctx; ++ int ret; ++ ++ ret = panthor_vm_prepare_map_op_ctx(&op_ctx, vm, bo, offset, size, va, flags); ++ if (ret) ++ return ret; ++ ++ ret = panthor_vm_exec_op(vm, &op_ctx, false); ++ panthor_vm_cleanup_op_ctx(&op_ctx, vm); ++ ++ return ret; ++} ++ ++/** ++ * panthor_vm_unmap_range() - Unmap a portion of the VA space ++ * @vm: VM to unmap the region from. ++ * @va: Virtual address to unmap. Must be 4k aligned. ++ * @size: Size of the region to unmap. Must be 4k aligned. ++ * ++ * Internal use only. For userspace requests, use ++ * panthor_vm_bind_exec_sync_op() instead. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_vm_unmap_range(struct panthor_vm *vm, u64 va, u64 size) ++{ ++ struct panthor_vm_op_ctx op_ctx; ++ int ret; ++ ++ ret = panthor_vm_prepare_unmap_op_ctx(&op_ctx, vm, va, size); ++ if (ret) ++ return ret; ++ ++ ret = panthor_vm_exec_op(vm, &op_ctx, false); ++ panthor_vm_cleanup_op_ctx(&op_ctx, vm); ++ ++ return ret; ++} ++ ++/** ++ * panthor_vm_prepare_mapped_bos_resvs() - Prepare resvs on VM BOs. ++ * @exec: Locking/preparation context. ++ * @vm: VM targeted by the GPU job. ++ * @slot_count: Number of slots to reserve. ++ * ++ * GPU jobs assume all BOs bound to the VM at the time the job is submitted ++ * are available when the job is executed. In order to guarantee that, we ++ * need to reserve a slot on all BOs mapped to a VM and update this slot with ++ * the job fence after its submission. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_vm_prepare_mapped_bos_resvs(struct drm_exec *exec, struct panthor_vm *vm, ++ u32 slot_count) ++{ ++ int ret; ++ ++ /* Acquire the VM lock and reserve a slot for this GPU job. */ ++ ret = drm_gpuvm_prepare_vm(&vm->base, exec, slot_count); ++ if (ret) ++ return ret; ++ ++ return drm_gpuvm_prepare_objects(&vm->base, exec, slot_count); ++} ++ ++/** ++ * panthor_mmu_unplug() - Unplug the MMU logic ++ * @ptdev: Device. ++ * ++ * No access to the MMU regs should be done after this function is called. ++ * We suspend the IRQ and disable all VMs to guarantee that. ++ */ ++void panthor_mmu_unplug(struct panthor_device *ptdev) ++{ ++ panthor_mmu_irq_suspend(&ptdev->mmu->irq); ++ ++ mutex_lock(&ptdev->mmu->as.slots_lock); ++ for (u32 i = 0; i < ARRAY_SIZE(ptdev->mmu->as.slots); i++) { ++ struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm; ++ ++ if (vm) { ++ drm_WARN_ON(&ptdev->base, panthor_mmu_as_disable(ptdev, i)); ++ panthor_vm_release_as_locked(vm); ++ } ++ } ++ mutex_unlock(&ptdev->mmu->as.slots_lock); ++} ++ ++static void panthor_mmu_release_wq(struct drm_device *ddev, void *res) ++{ ++ destroy_workqueue(res); ++} ++ ++/** ++ * panthor_mmu_init() - Initialize the MMU logic. ++ * @ptdev: Device. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_mmu_init(struct panthor_device *ptdev) ++{ ++ u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features); ++ struct panthor_mmu *mmu; ++ int ret, irq; ++ ++ mmu = drmm_kzalloc(&ptdev->base, sizeof(*mmu), GFP_KERNEL); ++ if (!mmu) ++ return -ENOMEM; ++ ++ INIT_LIST_HEAD(&mmu->as.lru_list); ++ ++ ret = drmm_mutex_init(&ptdev->base, &mmu->as.slots_lock); ++ if (ret) ++ return ret; ++ ++ INIT_LIST_HEAD(&mmu->vm.list); ++ ret = drmm_mutex_init(&ptdev->base, &mmu->vm.lock); ++ if (ret) ++ return ret; ++ ++ ptdev->mmu = mmu; ++ ++ irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "mmu"); ++ if (irq <= 0) ++ return -ENODEV; ++ ++ ret = panthor_request_mmu_irq(ptdev, &mmu->irq, irq, ++ panthor_mmu_fault_mask(ptdev, ~0)); ++ if (ret) ++ return ret; ++ ++ mmu->vm.wq = alloc_workqueue("panthor-vm-bind", WQ_UNBOUND, 0); ++ if (!mmu->vm.wq) ++ return -ENOMEM; ++ ++ /* On 32-bit kernels, the VA space is limited by the io_pgtable_ops abstraction, ++ * which passes iova as an unsigned long. Patch the mmu_features to reflect this ++ * limitation. ++ */ ++ if (sizeof(unsigned long) * 8 < va_bits) { ++ ptdev->gpu_info.mmu_features &= ~GENMASK(7, 0); ++ ptdev->gpu_info.mmu_features |= sizeof(unsigned long) * 8; ++ } ++ ++ return drmm_add_action_or_reset(&ptdev->base, panthor_mmu_release_wq, mmu->vm.wq); ++} ++ ++#ifdef CONFIG_DEBUG_FS ++static int show_vm_gpuvas(struct panthor_vm *vm, struct seq_file *m) ++{ ++ int ret; ++ ++ mutex_lock(&vm->op_lock); ++ ret = drm_debugfs_gpuva_info(m, &vm->base); ++ mutex_unlock(&vm->op_lock); ++ ++ return ret; ++} ++ ++static int show_each_vm(struct seq_file *m, void *arg) ++{ ++ struct drm_info_node *node = (struct drm_info_node *)m->private; ++ struct drm_device *ddev = node->minor->dev; ++ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); ++ int (*show)(struct panthor_vm *, struct seq_file *) = node->info_ent->data; ++ struct panthor_vm *vm; ++ int ret = 0; ++ ++ mutex_lock(&ptdev->mmu->vm.lock); ++ list_for_each_entry(vm, &ptdev->mmu->vm.list, node) { ++ ret = show(vm, m); ++ if (ret < 0) ++ break; ++ ++ seq_puts(m, "\n"); ++ } ++ mutex_unlock(&ptdev->mmu->vm.lock); ++ ++ return ret; ++} ++ ++static struct drm_info_list panthor_mmu_debugfs_list[] = { ++ DRM_DEBUGFS_GPUVA_INFO(show_each_vm, show_vm_gpuvas), ++}; ++ ++/** ++ * panthor_mmu_debugfs_init() - Initialize MMU debugfs entries ++ * @minor: Minor. ++ */ ++void panthor_mmu_debugfs_init(struct drm_minor *minor) ++{ ++ drm_debugfs_create_files(panthor_mmu_debugfs_list, ++ ARRAY_SIZE(panthor_mmu_debugfs_list), ++ minor->debugfs_root, minor); ++} ++#endif /* CONFIG_DEBUG_FS */ ++ ++/** ++ * panthor_mmu_pt_cache_init() - Initialize the page table cache. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_mmu_pt_cache_init(void) ++{ ++ pt_cache = kmem_cache_create("panthor-mmu-pt", SZ_4K, SZ_4K, 0, NULL); ++ if (!pt_cache) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++/** ++ * panthor_mmu_pt_cache_fini() - Destroy the page table cache. ++ */ ++void panthor_mmu_pt_cache_fini(void) ++{ ++ kmem_cache_destroy(pt_cache); ++} +diff --git a/drivers/gpu/drm/panthor/panthor_mmu.h b/drivers/gpu/drm/panthor/panthor_mmu.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_mmu.h +@@ -0,0 +1,102 @@ ++/* SPDX-License-Identifier: GPL-2.0 or MIT */ ++/* Copyright 2019 Linaro, Ltd, Rob Herring */ ++/* Copyright 2023 Collabora ltd. */ ++ ++#ifndef __PANTHOR_MMU_H__ ++#define __PANTHOR_MMU_H__ ++ ++#include ++ ++struct drm_exec; ++struct drm_sched_job; ++struct panthor_gem_object; ++struct panthor_heap_pool; ++struct panthor_vm; ++struct panthor_vma; ++struct panthor_mmu; ++ ++int panthor_mmu_init(struct panthor_device *ptdev); ++void panthor_mmu_unplug(struct panthor_device *ptdev); ++void panthor_mmu_pre_reset(struct panthor_device *ptdev); ++void panthor_mmu_post_reset(struct panthor_device *ptdev); ++void panthor_mmu_suspend(struct panthor_device *ptdev); ++void panthor_mmu_resume(struct panthor_device *ptdev); ++ ++int panthor_vm_map_bo_range(struct panthor_vm *vm, struct panthor_gem_object *bo, ++ u64 offset, u64 size, u64 va, u32 flags); ++int panthor_vm_unmap_range(struct panthor_vm *vm, u64 va, u64 size); ++struct panthor_gem_object * ++panthor_vm_get_bo_for_va(struct panthor_vm *vm, u64 va, u64 *bo_offset); ++ ++int panthor_vm_active(struct panthor_vm *vm); ++void panthor_vm_idle(struct panthor_vm *vm); ++int panthor_vm_as(struct panthor_vm *vm); ++ ++struct panthor_heap_pool * ++panthor_vm_get_heap_pool(struct panthor_vm *vm, bool create); ++ ++struct panthor_vm *panthor_vm_get(struct panthor_vm *vm); ++void panthor_vm_put(struct panthor_vm *vm); ++struct panthor_vm *panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, ++ u64 kernel_va_start, u64 kernel_va_size, ++ u64 kernel_auto_va_start, ++ u64 kernel_auto_va_size); ++ ++int panthor_vm_prepare_mapped_bos_resvs(struct drm_exec *exec, ++ struct panthor_vm *vm, ++ u32 slot_count); ++int panthor_vm_add_bos_resvs_deps_to_job(struct panthor_vm *vm, ++ struct drm_sched_job *job); ++void panthor_vm_add_job_fence_to_bos_resvs(struct panthor_vm *vm, ++ struct drm_sched_job *job); ++ ++struct dma_resv *panthor_vm_resv(struct panthor_vm *vm); ++struct drm_gem_object *panthor_vm_root_gem(struct panthor_vm *vm); ++ ++void panthor_vm_pool_destroy(struct panthor_file *pfile); ++int panthor_vm_pool_create(struct panthor_file *pfile); ++int panthor_vm_pool_create_vm(struct panthor_device *ptdev, ++ struct panthor_vm_pool *pool, ++ struct drm_panthor_vm_create *args); ++int panthor_vm_pool_destroy_vm(struct panthor_vm_pool *pool, u32 handle); ++struct panthor_vm *panthor_vm_pool_get_vm(struct panthor_vm_pool *pool, u32 handle); ++ ++bool panthor_vm_has_unhandled_faults(struct panthor_vm *vm); ++bool panthor_vm_is_unusable(struct panthor_vm *vm); ++ ++/* ++ * PANTHOR_VM_KERNEL_AUTO_VA: Use this magic address when you want the GEM ++ * logic to auto-allocate the virtual address in the reserved kernel VA range. ++ */ ++#define PANTHOR_VM_KERNEL_AUTO_VA ~0ull ++ ++int panthor_vm_alloc_va(struct panthor_vm *vm, u64 va, u64 size, ++ struct drm_mm_node *va_node); ++void panthor_vm_free_va(struct panthor_vm *vm, struct drm_mm_node *va_node); ++ ++int panthor_vm_bind_exec_sync_op(struct drm_file *file, ++ struct panthor_vm *vm, ++ struct drm_panthor_vm_bind_op *op); ++ ++struct drm_sched_job * ++panthor_vm_bind_job_create(struct drm_file *file, ++ struct panthor_vm *vm, ++ const struct drm_panthor_vm_bind_op *op); ++void panthor_vm_bind_job_put(struct drm_sched_job *job); ++int panthor_vm_bind_job_prepare_resvs(struct drm_exec *exec, ++ struct drm_sched_job *job); ++void panthor_vm_bind_job_update_resvs(struct drm_exec *exec, struct drm_sched_job *job); ++ ++void panthor_vm_update_resvs(struct panthor_vm *vm, struct drm_exec *exec, ++ struct dma_fence *fence, ++ enum dma_resv_usage private_usage, ++ enum dma_resv_usage extobj_usage); ++ ++int panthor_mmu_pt_cache_init(void); ++void panthor_mmu_pt_cache_fini(void); ++ ++#ifdef CONFIG_DEBUG_FS ++void panthor_mmu_debugfs_init(struct drm_minor *minor); ++#endif ++ ++#endif +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:22 +0100 +Subject: drm/panthor: Add the FW logical block + +Contains everything that's FW related, that includes the code dealing +with the microcontroller unit (MCU) that's running the FW, and anything +related to allocating memory shared between the FW and the CPU. + +A few global FW events are processed in the IRQ handler, the rest is +forwarded to the scheduler, since scheduling is the primary reason for +the FW existence, and also the main source of FW <-> kernel +interactions. + +v6: +- Add Maxime's and Heiko's acks +- Keep header inclusion alphabetically ordered + +v5: +- Fix typo in GLB_PERFCNT_SAMPLE definition +- Fix unbalanced panthor_vm_idle/active() calls +- Fallback to a slow reset when the fast reset fails +- Add extra information when reporting a FW boot failure + +v4: +- Add a MODULE_FIRMWARE() entry for gen 10.8 +- Fix a wrong return ERR_PTR() in panthor_fw_load_section_entry() +- Fix typos +- Add Steve's R-b + +v3: +- Make the FW path more future-proof (Liviu) +- Use one waitqueue for all FW events +- Simplify propagation of FW events to the scheduler logic +- Drop the panthor_fw_mem abstraction and use panthor_kernel_bo instead +- Account for the panthor_vm changes +- Replace magic number with 0x7fffffff with ~0 to better signify that + it's the maximum permitted value. +- More accurate rounding when computing the firmware timeout. +- Add a 'sub iterator' helper function. This also adds a check that a + firmware entry doesn't overflow the firmware image. +- Drop __packed from FW structures, natural alignment is good enough. +- Other minor code improvements. + +Co-developed-by: Steven Price +Signed-off-by: Steven Price +Signed-off-by: Boris Brezillon +Reviewed-by: Steven Price +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + drivers/gpu/drm/panthor/panthor_fw.c | 1362 ++++++++++ + drivers/gpu/drm/panthor/panthor_fw.h | 503 ++++ + 2 files changed, 1865 insertions(+) + +diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_fw.c +@@ -0,0 +1,1362 @@ ++// SPDX-License-Identifier: GPL-2.0 or MIT ++/* Copyright 2023 Collabora ltd. */ ++ ++#ifdef CONFIG_ARM_ARCH_TIMER ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "panthor_device.h" ++#include "panthor_fw.h" ++#include "panthor_gem.h" ++#include "panthor_gpu.h" ++#include "panthor_mmu.h" ++#include "panthor_regs.h" ++#include "panthor_sched.h" ++ ++#define CSF_FW_NAME "mali_csffw.bin" ++ ++#define PING_INTERVAL_MS 12000 ++#define PROGRESS_TIMEOUT_CYCLES (5ull * 500 * 1024 * 1024) ++#define PROGRESS_TIMEOUT_SCALE_SHIFT 10 ++#define IDLE_HYSTERESIS_US 800 ++#define PWROFF_HYSTERESIS_US 10000 ++ ++/** ++ * struct panthor_fw_binary_hdr - Firmware binary header. ++ */ ++struct panthor_fw_binary_hdr { ++ /** @magic: Magic value to check binary validity. */ ++ u32 magic; ++#define CSF_FW_BINARY_HEADER_MAGIC 0xc3f13a6e ++ ++ /** @minor: Minor FW version. */ ++ u8 minor; ++ ++ /** @major: Major FW version. */ ++ u8 major; ++#define CSF_FW_BINARY_HEADER_MAJOR_MAX 0 ++ ++ /** @padding1: MBZ. */ ++ u16 padding1; ++ ++ /** @version_hash: FW version hash. */ ++ u32 version_hash; ++ ++ /** @padding2: MBZ. */ ++ u32 padding2; ++ ++ /** @size: FW binary size. */ ++ u32 size; ++}; ++ ++/** ++ * enum panthor_fw_binary_entry_type - Firmware binary entry type ++ */ ++enum panthor_fw_binary_entry_type { ++ /** @CSF_FW_BINARY_ENTRY_TYPE_IFACE: Host <-> FW interface. */ ++ CSF_FW_BINARY_ENTRY_TYPE_IFACE = 0, ++ ++ /** @CSF_FW_BINARY_ENTRY_TYPE_CONFIG: FW config. */ ++ CSF_FW_BINARY_ENTRY_TYPE_CONFIG = 1, ++ ++ /** @CSF_FW_BINARY_ENTRY_TYPE_FUTF_TEST: Unit-tests. */ ++ CSF_FW_BINARY_ENTRY_TYPE_FUTF_TEST = 2, ++ ++ /** @CSF_FW_BINARY_ENTRY_TYPE_TRACE_BUFFER: Trace buffer interface. */ ++ CSF_FW_BINARY_ENTRY_TYPE_TRACE_BUFFER = 3, ++ ++ /** @CSF_FW_BINARY_ENTRY_TYPE_TIMELINE_METADATA: Timeline metadata interface. */ ++ CSF_FW_BINARY_ENTRY_TYPE_TIMELINE_METADATA = 4, ++}; ++ ++#define CSF_FW_BINARY_ENTRY_TYPE(ehdr) ((ehdr) & 0xff) ++#define CSF_FW_BINARY_ENTRY_SIZE(ehdr) (((ehdr) >> 8) & 0xff) ++#define CSF_FW_BINARY_ENTRY_UPDATE BIT(30) ++#define CSF_FW_BINARY_ENTRY_OPTIONAL BIT(31) ++ ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_RD BIT(0) ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_WR BIT(1) ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_EX BIT(2) ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_NONE (0 << 3) ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_CACHED (1 << 3) ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_UNCACHED_COHERENT (2 << 3) ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_CACHED_COHERENT (3 << 3) ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_MASK GENMASK(4, 3) ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_PROT BIT(5) ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_SHARED BIT(30) ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_ZERO BIT(31) ++ ++#define CSF_FW_BINARY_IFACE_ENTRY_RD_SUPPORTED_FLAGS \ ++ (CSF_FW_BINARY_IFACE_ENTRY_RD_RD | \ ++ CSF_FW_BINARY_IFACE_ENTRY_RD_WR | \ ++ CSF_FW_BINARY_IFACE_ENTRY_RD_EX | \ ++ CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_MASK | \ ++ CSF_FW_BINARY_IFACE_ENTRY_RD_PROT | \ ++ CSF_FW_BINARY_IFACE_ENTRY_RD_SHARED | \ ++ CSF_FW_BINARY_IFACE_ENTRY_RD_ZERO) ++ ++/** ++ * struct panthor_fw_binary_section_entry_hdr - Describes a section of FW binary ++ */ ++struct panthor_fw_binary_section_entry_hdr { ++ /** @flags: Section flags. */ ++ u32 flags; ++ ++ /** @va: MCU virtual range to map this binary section to. */ ++ struct { ++ /** @start: Start address. */ ++ u32 start; ++ ++ /** @end: End address. */ ++ u32 end; ++ } va; ++ ++ /** @data: Data to initialize the FW section with. */ ++ struct { ++ /** @start: Start offset in the FW binary. */ ++ u32 start; ++ ++ /** @end: End offset in the FW binary. */ ++ u32 end; ++ } data; ++}; ++ ++/** ++ * struct panthor_fw_binary_iter - Firmware binary iterator ++ * ++ * Used to parse a firmware binary. ++ */ ++struct panthor_fw_binary_iter { ++ /** @data: FW binary data. */ ++ const void *data; ++ ++ /** @size: FW binary size. */ ++ size_t size; ++ ++ /** @offset: Iterator offset. */ ++ size_t offset; ++}; ++ ++/** ++ * struct panthor_fw_section - FW section ++ */ ++struct panthor_fw_section { ++ /** @node: Used to keep track of FW sections. */ ++ struct list_head node; ++ ++ /** @flags: Section flags, as encoded in the FW binary. */ ++ u32 flags; ++ ++ /** @mem: Section memory. */ ++ struct panthor_kernel_bo *mem; ++ ++ /** ++ * @name: Name of the section, as specified in the binary. ++ * ++ * Can be NULL. ++ */ ++ const char *name; ++ ++ /** ++ * @data: Initial data copied to the FW memory. ++ * ++ * We keep data around so we can reload sections after a reset. ++ */ ++ struct { ++ /** @buf: Buffed used to store init data. */ ++ const void *buf; ++ ++ /** @size: Size of @buf in bytes. */ ++ size_t size; ++ } data; ++}; ++ ++#define CSF_MCU_SHARED_REGION_START 0x04000000ULL ++#define CSF_MCU_SHARED_REGION_SIZE 0x04000000ULL ++ ++#define MIN_CS_PER_CSG 8 ++#define MIN_CSGS 3 ++#define MAX_CSG_PRIO 0xf ++ ++#define CSF_IFACE_VERSION(major, minor, patch) \ ++ (((major) << 24) | ((minor) << 16) | (patch)) ++#define CSF_IFACE_VERSION_MAJOR(v) ((v) >> 24) ++#define CSF_IFACE_VERSION_MINOR(v) (((v) >> 16) & 0xff) ++#define CSF_IFACE_VERSION_PATCH(v) ((v) & 0xffff) ++ ++#define CSF_GROUP_CONTROL_OFFSET 0x1000 ++#define CSF_STREAM_CONTROL_OFFSET 0x40 ++#define CSF_UNPRESERVED_REG_COUNT 4 ++ ++/** ++ * struct panthor_fw_iface - FW interfaces ++ */ ++struct panthor_fw_iface { ++ /** @global: Global interface. */ ++ struct panthor_fw_global_iface global; ++ ++ /** @groups: Group slot interfaces. */ ++ struct panthor_fw_csg_iface groups[MAX_CSGS]; ++ ++ /** @streams: Command stream slot interfaces. */ ++ struct panthor_fw_cs_iface streams[MAX_CSGS][MAX_CS_PER_CSG]; ++}; ++ ++/** ++ * struct panthor_fw - Firmware management ++ */ ++struct panthor_fw { ++ /** @vm: MCU VM. */ ++ struct panthor_vm *vm; ++ ++ /** @sections: List of FW sections. */ ++ struct list_head sections; ++ ++ /** @shared_section: The section containing the FW interfaces. */ ++ struct panthor_fw_section *shared_section; ++ ++ /** @iface: FW interfaces. */ ++ struct panthor_fw_iface iface; ++ ++ /** @watchdog: Collection of fields relating to the FW watchdog. */ ++ struct { ++ /** @ping_work: Delayed work used to ping the FW. */ ++ struct delayed_work ping_work; ++ } watchdog; ++ ++ /** ++ * @req_waitqueue: FW request waitqueue. ++ * ++ * Everytime a request is sent to a command stream group or the global ++ * interface, the caller will first busy wait for the request to be ++ * acknowledged, and then fallback to a sleeping wait. ++ * ++ * This wait queue is here to support the sleeping wait flavor. ++ */ ++ wait_queue_head_t req_waitqueue; ++ ++ /** @booted: True is the FW is booted */ ++ bool booted; ++ ++ /** ++ * @fast_reset: True if the post_reset logic can proceed with a fast reset. ++ * ++ * A fast reset is just a reset where the driver doesn't reload the FW sections. ++ * ++ * Any time the firmware is properly suspended, a fast reset can take place. ++ * On the other hand, if the halt operation failed, the driver will reload ++ * all sections to make sure we start from a fresh state. ++ */ ++ bool fast_reset; ++ ++ /** @irq: Job irq data. */ ++ struct panthor_irq irq; ++}; ++ ++struct panthor_vm *panthor_fw_vm(struct panthor_device *ptdev) ++{ ++ return ptdev->fw->vm; ++} ++ ++/** ++ * panthor_fw_get_glb_iface() - Get the global interface ++ * @ptdev: Device. ++ * ++ * Return: The global interface. ++ */ ++struct panthor_fw_global_iface * ++panthor_fw_get_glb_iface(struct panthor_device *ptdev) ++{ ++ return &ptdev->fw->iface.global; ++} ++ ++/** ++ * panthor_fw_get_csg_iface() - Get a command stream group slot interface ++ * @ptdev: Device. ++ * @csg_slot: Index of the command stream group slot. ++ * ++ * Return: The command stream group slot interface. ++ */ ++struct panthor_fw_csg_iface * ++panthor_fw_get_csg_iface(struct panthor_device *ptdev, u32 csg_slot) ++{ ++ if (drm_WARN_ON(&ptdev->base, csg_slot >= MAX_CSGS)) ++ return NULL; ++ ++ return &ptdev->fw->iface.groups[csg_slot]; ++} ++ ++/** ++ * panthor_fw_get_cs_iface() - Get a command stream slot interface ++ * @ptdev: Device. ++ * @csg_slot: Index of the command stream group slot. ++ * @cs_slot: Index of the command stream slot. ++ * ++ * Return: The command stream slot interface. ++ */ ++struct panthor_fw_cs_iface * ++panthor_fw_get_cs_iface(struct panthor_device *ptdev, u32 csg_slot, u32 cs_slot) ++{ ++ if (drm_WARN_ON(&ptdev->base, csg_slot >= MAX_CSGS || cs_slot > MAX_CS_PER_CSG)) ++ return NULL; ++ ++ return &ptdev->fw->iface.streams[csg_slot][cs_slot]; ++} ++ ++/** ++ * panthor_fw_conv_timeout() - Convert a timeout into a cycle-count ++ * @ptdev: Device. ++ * @timeout_us: Timeout expressed in micro-seconds. ++ * ++ * The FW has two timer sources: the GPU counter or arch-timer. We need ++ * to express timeouts in term of number of cycles and specify which ++ * timer source should be used. ++ * ++ * Return: A value suitable for timeout fields in the global interface. ++ */ ++static u32 panthor_fw_conv_timeout(struct panthor_device *ptdev, u32 timeout_us) ++{ ++ bool use_cycle_counter = false; ++ u32 timer_rate = 0; ++ u64 mod_cycles; ++ ++#ifdef CONFIG_ARM_ARCH_TIMER ++ timer_rate = arch_timer_get_cntfrq(); ++#endif ++ ++ if (!timer_rate) { ++ use_cycle_counter = true; ++ timer_rate = clk_get_rate(ptdev->clks.core); ++ } ++ ++ if (drm_WARN_ON(&ptdev->base, !timer_rate)) { ++ /* We couldn't get a valid clock rate, let's just pick the ++ * maximum value so the FW still handles the core ++ * power on/off requests. ++ */ ++ return GLB_TIMER_VAL(~0) | ++ GLB_TIMER_SOURCE_GPU_COUNTER; ++ } ++ ++ mod_cycles = DIV_ROUND_UP_ULL((u64)timeout_us * timer_rate, ++ 1000000ull << 10); ++ if (drm_WARN_ON(&ptdev->base, mod_cycles > GLB_TIMER_VAL(~0))) ++ mod_cycles = GLB_TIMER_VAL(~0); ++ ++ return GLB_TIMER_VAL(mod_cycles) | ++ (use_cycle_counter ? GLB_TIMER_SOURCE_GPU_COUNTER : 0); ++} ++ ++static int panthor_fw_binary_iter_read(struct panthor_device *ptdev, ++ struct panthor_fw_binary_iter *iter, ++ void *out, size_t size) ++{ ++ size_t new_offset = iter->offset + size; ++ ++ if (new_offset > iter->size || new_offset < iter->offset) { ++ drm_err(&ptdev->base, "Firmware too small\n"); ++ return -EINVAL; ++ } ++ ++ memcpy(out, iter->data + iter->offset, size); ++ iter->offset = new_offset; ++ return 0; ++} ++ ++static int panthor_fw_binary_sub_iter_init(struct panthor_device *ptdev, ++ struct panthor_fw_binary_iter *iter, ++ struct panthor_fw_binary_iter *sub_iter, ++ size_t size) ++{ ++ size_t new_offset = iter->offset + size; ++ ++ if (new_offset > iter->size || new_offset < iter->offset) { ++ drm_err(&ptdev->base, "Firmware entry too long\n"); ++ return -EINVAL; ++ } ++ ++ sub_iter->offset = 0; ++ sub_iter->data = iter->data + iter->offset; ++ sub_iter->size = size; ++ iter->offset = new_offset; ++ return 0; ++} ++ ++static void panthor_fw_init_section_mem(struct panthor_device *ptdev, ++ struct panthor_fw_section *section) ++{ ++ bool was_mapped = !!section->mem->kmap; ++ int ret; ++ ++ if (!section->data.size && ++ !(section->flags & CSF_FW_BINARY_IFACE_ENTRY_RD_ZERO)) ++ return; ++ ++ ret = panthor_kernel_bo_vmap(section->mem); ++ if (drm_WARN_ON(&ptdev->base, ret)) ++ return; ++ ++ memcpy(section->mem->kmap, section->data.buf, section->data.size); ++ if (section->flags & CSF_FW_BINARY_IFACE_ENTRY_RD_ZERO) { ++ memset(section->mem->kmap + section->data.size, 0, ++ panthor_kernel_bo_size(section->mem) - section->data.size); ++ } ++ ++ if (!was_mapped) ++ panthor_kernel_bo_vunmap(section->mem); ++} ++ ++/** ++ * panthor_fw_alloc_queue_iface_mem() - Allocate a ring-buffer interfaces. ++ * @ptdev: Device. ++ * @input: Pointer holding the input interface on success. ++ * Should be ignored on failure. ++ * @output: Pointer holding the output interface on success. ++ * Should be ignored on failure. ++ * @input_fw_va: Pointer holding the input interface FW VA on success. ++ * Should be ignored on failure. ++ * @output_fw_va: Pointer holding the output interface FW VA on success. ++ * Should be ignored on failure. ++ * ++ * Allocates panthor_fw_ringbuf_{input,out}_iface interfaces. The input ++ * interface is at offset 0, and the output interface at offset 4096. ++ * ++ * Return: A valid pointer in case of success, an ERR_PTR() otherwise. ++ */ ++struct panthor_kernel_bo * ++panthor_fw_alloc_queue_iface_mem(struct panthor_device *ptdev, ++ struct panthor_fw_ringbuf_input_iface **input, ++ const struct panthor_fw_ringbuf_output_iface **output, ++ u32 *input_fw_va, u32 *output_fw_va) ++{ ++ struct panthor_kernel_bo *mem; ++ int ret; ++ ++ mem = panthor_kernel_bo_create(ptdev, ptdev->fw->vm, SZ_8K, ++ DRM_PANTHOR_BO_NO_MMAP, ++ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | ++ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED, ++ PANTHOR_VM_KERNEL_AUTO_VA); ++ if (IS_ERR(mem)) ++ return mem; ++ ++ ret = panthor_kernel_bo_vmap(mem); ++ if (ret) { ++ panthor_kernel_bo_destroy(panthor_fw_vm(ptdev), mem); ++ return ERR_PTR(ret); ++ } ++ ++ memset(mem->kmap, 0, panthor_kernel_bo_size(mem)); ++ *input = mem->kmap; ++ *output = mem->kmap + SZ_4K; ++ *input_fw_va = panthor_kernel_bo_gpuva(mem); ++ *output_fw_va = *input_fw_va + SZ_4K; ++ ++ return mem; ++} ++ ++/** ++ * panthor_fw_alloc_suspend_buf_mem() - Allocate a suspend buffer for a command stream group. ++ * @ptdev: Device. ++ * @size: Size of the suspend buffer. ++ * ++ * Return: A valid pointer in case of success, an ERR_PTR() otherwise. ++ */ ++struct panthor_kernel_bo * ++panthor_fw_alloc_suspend_buf_mem(struct panthor_device *ptdev, size_t size) ++{ ++ return panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), size, ++ DRM_PANTHOR_BO_NO_MMAP, ++ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC, ++ PANTHOR_VM_KERNEL_AUTO_VA); ++} ++ ++static int panthor_fw_load_section_entry(struct panthor_device *ptdev, ++ const struct firmware *fw, ++ struct panthor_fw_binary_iter *iter, ++ u32 ehdr) ++{ ++ struct panthor_fw_binary_section_entry_hdr hdr; ++ struct panthor_fw_section *section; ++ u32 section_size; ++ u32 name_len; ++ int ret; ++ ++ ret = panthor_fw_binary_iter_read(ptdev, iter, &hdr, sizeof(hdr)); ++ if (ret) ++ return ret; ++ ++ if (hdr.data.end < hdr.data.start) { ++ drm_err(&ptdev->base, "Firmware corrupted, data.end < data.start (0x%x < 0x%x)\n", ++ hdr.data.end, hdr.data.start); ++ return -EINVAL; ++ } ++ ++ if (hdr.va.end < hdr.va.start) { ++ drm_err(&ptdev->base, "Firmware corrupted, hdr.va.end < hdr.va.start (0x%x < 0x%x)\n", ++ hdr.va.end, hdr.va.start); ++ return -EINVAL; ++ } ++ ++ if (hdr.data.end > fw->size) { ++ drm_err(&ptdev->base, "Firmware corrupted, file truncated? data_end=0x%x > fw size=0x%zx\n", ++ hdr.data.end, fw->size); ++ return -EINVAL; ++ } ++ ++ if ((hdr.va.start & ~PAGE_MASK) != 0 || ++ (hdr.va.end & ~PAGE_MASK) != 0) { ++ drm_err(&ptdev->base, "Firmware corrupted, virtual addresses not page aligned: 0x%x-0x%x\n", ++ hdr.va.start, hdr.va.end); ++ return -EINVAL; ++ } ++ ++ if (hdr.flags & ~CSF_FW_BINARY_IFACE_ENTRY_RD_SUPPORTED_FLAGS) { ++ drm_err(&ptdev->base, "Firmware contains interface with unsupported flags (0x%x)\n", ++ hdr.flags); ++ return -EINVAL; ++ } ++ ++ if (hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_RD_PROT) { ++ drm_warn(&ptdev->base, ++ "Firmware protected mode entry not be supported, ignoring"); ++ return 0; ++ } ++ ++ if (hdr.va.start == CSF_MCU_SHARED_REGION_START && ++ !(hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_RD_SHARED)) { ++ drm_err(&ptdev->base, ++ "Interface at 0x%llx must be shared", CSF_MCU_SHARED_REGION_START); ++ return -EINVAL; ++ } ++ ++ name_len = iter->size - iter->offset; ++ ++ section = drmm_kzalloc(&ptdev->base, sizeof(*section), GFP_KERNEL); ++ if (!section) ++ return -ENOMEM; ++ ++ list_add_tail(§ion->node, &ptdev->fw->sections); ++ section->flags = hdr.flags; ++ section->data.size = hdr.data.end - hdr.data.start; ++ ++ if (section->data.size > 0) { ++ void *data = drmm_kmalloc(&ptdev->base, section->data.size, GFP_KERNEL); ++ ++ if (!data) ++ return -ENOMEM; ++ ++ memcpy(data, fw->data + hdr.data.start, section->data.size); ++ section->data.buf = data; ++ } ++ ++ if (name_len > 0) { ++ char *name = drmm_kmalloc(&ptdev->base, name_len + 1, GFP_KERNEL); ++ ++ if (!name) ++ return -ENOMEM; ++ ++ memcpy(name, iter->data + iter->offset, name_len); ++ name[name_len] = '\0'; ++ section->name = name; ++ } ++ ++ section_size = hdr.va.end - hdr.va.start; ++ if (section_size) { ++ u32 cache_mode = hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_MASK; ++ struct panthor_gem_object *bo; ++ u32 vm_map_flags = 0; ++ struct sg_table *sgt; ++ u64 va = hdr.va.start; ++ ++ if (!(hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_RD_WR)) ++ vm_map_flags |= DRM_PANTHOR_VM_BIND_OP_MAP_READONLY; ++ ++ if (!(hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_RD_EX)) ++ vm_map_flags |= DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC; ++ ++ /* TODO: CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_*_COHERENT are mapped to ++ * non-cacheable for now. We might want to introduce a new ++ * IOMMU_xxx flag (or abuse IOMMU_MMIO, which maps to device ++ * memory and is currently not used by our driver) for ++ * AS_MEMATTR_AARCH64_SHARED memory, so we can take benefit ++ * of IO-coherent systems. ++ */ ++ if (cache_mode != CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_CACHED) ++ vm_map_flags |= DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED; ++ ++ section->mem = panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), ++ section_size, ++ DRM_PANTHOR_BO_NO_MMAP, ++ vm_map_flags, va); ++ if (IS_ERR(section->mem)) ++ return PTR_ERR(section->mem); ++ ++ if (drm_WARN_ON(&ptdev->base, section->mem->va_node.start != hdr.va.start)) ++ return -EINVAL; ++ ++ if (section->flags & CSF_FW_BINARY_IFACE_ENTRY_RD_SHARED) { ++ ret = panthor_kernel_bo_vmap(section->mem); ++ if (ret) ++ return ret; ++ } ++ ++ panthor_fw_init_section_mem(ptdev, section); ++ ++ bo = to_panthor_bo(section->mem->obj); ++ sgt = drm_gem_shmem_get_pages_sgt(&bo->base); ++ if (IS_ERR(sgt)) ++ return PTR_ERR(sgt); ++ ++ dma_sync_sgtable_for_device(ptdev->base.dev, sgt, DMA_TO_DEVICE); ++ } ++ ++ if (hdr.va.start == CSF_MCU_SHARED_REGION_START) ++ ptdev->fw->shared_section = section; ++ ++ return 0; ++} ++ ++static void ++panthor_reload_fw_sections(struct panthor_device *ptdev, bool full_reload) ++{ ++ struct panthor_fw_section *section; ++ ++ list_for_each_entry(section, &ptdev->fw->sections, node) { ++ struct sg_table *sgt; ++ ++ if (!full_reload && !(section->flags & CSF_FW_BINARY_IFACE_ENTRY_RD_WR)) ++ continue; ++ ++ panthor_fw_init_section_mem(ptdev, section); ++ sgt = drm_gem_shmem_get_pages_sgt(&to_panthor_bo(section->mem->obj)->base); ++ if (!drm_WARN_ON(&ptdev->base, IS_ERR_OR_NULL(sgt))) ++ dma_sync_sgtable_for_device(ptdev->base.dev, sgt, DMA_TO_DEVICE); ++ } ++} ++ ++static int panthor_fw_load_entry(struct panthor_device *ptdev, ++ const struct firmware *fw, ++ struct panthor_fw_binary_iter *iter) ++{ ++ struct panthor_fw_binary_iter eiter; ++ u32 ehdr; ++ int ret; ++ ++ ret = panthor_fw_binary_iter_read(ptdev, iter, &ehdr, sizeof(ehdr)); ++ if (ret) ++ return ret; ++ ++ if ((iter->offset % sizeof(u32)) || ++ (CSF_FW_BINARY_ENTRY_SIZE(ehdr) % sizeof(u32))) { ++ drm_err(&ptdev->base, "Firmware entry isn't 32 bit aligned, offset=0x%x size=0x%x\n", ++ (u32)(iter->offset - sizeof(u32)), CSF_FW_BINARY_ENTRY_SIZE(ehdr)); ++ return -EINVAL; ++ } ++ ++ if (panthor_fw_binary_sub_iter_init(ptdev, iter, &eiter, ++ CSF_FW_BINARY_ENTRY_SIZE(ehdr) - sizeof(ehdr))) ++ return -EINVAL; ++ ++ switch (CSF_FW_BINARY_ENTRY_TYPE(ehdr)) { ++ case CSF_FW_BINARY_ENTRY_TYPE_IFACE: ++ return panthor_fw_load_section_entry(ptdev, fw, &eiter, ehdr); ++ ++ /* FIXME: handle those entry types? */ ++ case CSF_FW_BINARY_ENTRY_TYPE_CONFIG: ++ case CSF_FW_BINARY_ENTRY_TYPE_FUTF_TEST: ++ case CSF_FW_BINARY_ENTRY_TYPE_TRACE_BUFFER: ++ case CSF_FW_BINARY_ENTRY_TYPE_TIMELINE_METADATA: ++ return 0; ++ default: ++ break; ++ } ++ ++ if (ehdr & CSF_FW_BINARY_ENTRY_OPTIONAL) ++ return 0; ++ ++ drm_err(&ptdev->base, ++ "Unsupported non-optional entry type %u in firmware\n", ++ CSF_FW_BINARY_ENTRY_TYPE(ehdr)); ++ return -EINVAL; ++} ++ ++static int panthor_fw_load(struct panthor_device *ptdev) ++{ ++ const struct firmware *fw = NULL; ++ struct panthor_fw_binary_iter iter = {}; ++ struct panthor_fw_binary_hdr hdr; ++ char fw_path[128]; ++ int ret; ++ ++ snprintf(fw_path, sizeof(fw_path), "arm/mali/arch%d.%d/%s", ++ (u32)GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id), ++ (u32)GPU_ARCH_MINOR(ptdev->gpu_info.gpu_id), ++ CSF_FW_NAME); ++ ++ ret = request_firmware(&fw, fw_path, ptdev->base.dev); ++ if (ret) { ++ drm_err(&ptdev->base, "Failed to load firmware image '%s'\n", ++ CSF_FW_NAME); ++ return ret; ++ } ++ ++ iter.data = fw->data; ++ iter.size = fw->size; ++ ret = panthor_fw_binary_iter_read(ptdev, &iter, &hdr, sizeof(hdr)); ++ if (ret) ++ goto out; ++ ++ if (hdr.magic != CSF_FW_BINARY_HEADER_MAGIC) { ++ ret = -EINVAL; ++ drm_err(&ptdev->base, "Invalid firmware magic\n"); ++ goto out; ++ } ++ ++ if (hdr.major != CSF_FW_BINARY_HEADER_MAJOR_MAX) { ++ ret = -EINVAL; ++ drm_err(&ptdev->base, "Unsupported firmware binary header version %d.%d (expected %d.x)\n", ++ hdr.major, hdr.minor, CSF_FW_BINARY_HEADER_MAJOR_MAX); ++ goto out; ++ } ++ ++ if (hdr.size > iter.size) { ++ drm_err(&ptdev->base, "Firmware image is truncated\n"); ++ goto out; ++ } ++ ++ iter.size = hdr.size; ++ ++ while (iter.offset < hdr.size) { ++ ret = panthor_fw_load_entry(ptdev, fw, &iter); ++ if (ret) ++ goto out; ++ } ++ ++ if (!ptdev->fw->shared_section) { ++ drm_err(&ptdev->base, "Shared interface region not found\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++out: ++ release_firmware(fw); ++ return ret; ++} ++ ++/** ++ * iface_fw_to_cpu_addr() - Turn an MCU address into a CPU address ++ * @ptdev: Device. ++ * @mcu_va: MCU address. ++ * ++ * Return: NULL if the address is not part of the shared section, non-NULL otherwise. ++ */ ++static void *iface_fw_to_cpu_addr(struct panthor_device *ptdev, u32 mcu_va) ++{ ++ u64 shared_mem_start = panthor_kernel_bo_gpuva(ptdev->fw->shared_section->mem); ++ u64 shared_mem_end = shared_mem_start + ++ panthor_kernel_bo_size(ptdev->fw->shared_section->mem); ++ if (mcu_va < shared_mem_start || mcu_va >= shared_mem_end) ++ return NULL; ++ ++ return ptdev->fw->shared_section->mem->kmap + (mcu_va - shared_mem_start); ++} ++ ++static int panthor_init_cs_iface(struct panthor_device *ptdev, ++ unsigned int csg_idx, unsigned int cs_idx) ++{ ++ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); ++ struct panthor_fw_csg_iface *csg_iface = panthor_fw_get_csg_iface(ptdev, csg_idx); ++ struct panthor_fw_cs_iface *cs_iface = &ptdev->fw->iface.streams[csg_idx][cs_idx]; ++ u64 shared_section_sz = panthor_kernel_bo_size(ptdev->fw->shared_section->mem); ++ u32 iface_offset = CSF_GROUP_CONTROL_OFFSET + ++ (csg_idx * glb_iface->control->group_stride) + ++ CSF_STREAM_CONTROL_OFFSET + ++ (cs_idx * csg_iface->control->stream_stride); ++ struct panthor_fw_cs_iface *first_cs_iface = ++ panthor_fw_get_cs_iface(ptdev, 0, 0); ++ ++ if (iface_offset + sizeof(*cs_iface) >= shared_section_sz) ++ return -EINVAL; ++ ++ spin_lock_init(&cs_iface->lock); ++ cs_iface->control = ptdev->fw->shared_section->mem->kmap + iface_offset; ++ cs_iface->input = iface_fw_to_cpu_addr(ptdev, cs_iface->control->input_va); ++ cs_iface->output = iface_fw_to_cpu_addr(ptdev, cs_iface->control->output_va); ++ ++ if (!cs_iface->input || !cs_iface->output) { ++ drm_err(&ptdev->base, "Invalid stream control interface input/output VA"); ++ return -EINVAL; ++ } ++ ++ if (cs_iface != first_cs_iface) { ++ if (cs_iface->control->features != first_cs_iface->control->features) { ++ drm_err(&ptdev->base, "Expecting identical CS slots"); ++ return -EINVAL; ++ } ++ } else { ++ u32 reg_count = CS_FEATURES_WORK_REGS(cs_iface->control->features); ++ ++ ptdev->csif_info.cs_reg_count = reg_count; ++ ptdev->csif_info.unpreserved_cs_reg_count = CSF_UNPRESERVED_REG_COUNT; ++ } ++ ++ return 0; ++} ++ ++static bool compare_csg(const struct panthor_fw_csg_control_iface *a, ++ const struct panthor_fw_csg_control_iface *b) ++{ ++ if (a->features != b->features) ++ return false; ++ if (a->suspend_size != b->suspend_size) ++ return false; ++ if (a->protm_suspend_size != b->protm_suspend_size) ++ return false; ++ if (a->stream_num != b->stream_num) ++ return false; ++ return true; ++} ++ ++static int panthor_init_csg_iface(struct panthor_device *ptdev, ++ unsigned int csg_idx) ++{ ++ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); ++ struct panthor_fw_csg_iface *csg_iface = &ptdev->fw->iface.groups[csg_idx]; ++ u64 shared_section_sz = panthor_kernel_bo_size(ptdev->fw->shared_section->mem); ++ u32 iface_offset = CSF_GROUP_CONTROL_OFFSET + (csg_idx * glb_iface->control->group_stride); ++ unsigned int i; ++ ++ if (iface_offset + sizeof(*csg_iface) >= shared_section_sz) ++ return -EINVAL; ++ ++ spin_lock_init(&csg_iface->lock); ++ csg_iface->control = ptdev->fw->shared_section->mem->kmap + iface_offset; ++ csg_iface->input = iface_fw_to_cpu_addr(ptdev, csg_iface->control->input_va); ++ csg_iface->output = iface_fw_to_cpu_addr(ptdev, csg_iface->control->output_va); ++ ++ if (csg_iface->control->stream_num < MIN_CS_PER_CSG || ++ csg_iface->control->stream_num > MAX_CS_PER_CSG) ++ return -EINVAL; ++ ++ if (!csg_iface->input || !csg_iface->output) { ++ drm_err(&ptdev->base, "Invalid group control interface input/output VA"); ++ return -EINVAL; ++ } ++ ++ if (csg_idx > 0) { ++ struct panthor_fw_csg_iface *first_csg_iface = ++ panthor_fw_get_csg_iface(ptdev, 0); ++ ++ if (!compare_csg(first_csg_iface->control, csg_iface->control)) { ++ drm_err(&ptdev->base, "Expecting identical CSG slots"); ++ return -EINVAL; ++ } ++ } ++ ++ for (i = 0; i < csg_iface->control->stream_num; i++) { ++ int ret = panthor_init_cs_iface(ptdev, csg_idx, i); ++ ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static u32 panthor_get_instr_features(struct panthor_device *ptdev) ++{ ++ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); ++ ++ if (glb_iface->control->version < CSF_IFACE_VERSION(1, 1, 0)) ++ return 0; ++ ++ return glb_iface->control->instr_features; ++} ++ ++static int panthor_fw_init_ifaces(struct panthor_device *ptdev) ++{ ++ struct panthor_fw_global_iface *glb_iface = &ptdev->fw->iface.global; ++ unsigned int i; ++ ++ if (!ptdev->fw->shared_section->mem->kmap) ++ return -EINVAL; ++ ++ spin_lock_init(&glb_iface->lock); ++ glb_iface->control = ptdev->fw->shared_section->mem->kmap; ++ ++ if (!glb_iface->control->version) { ++ drm_err(&ptdev->base, "Firmware version is 0. Firmware may have failed to boot"); ++ return -EINVAL; ++ } ++ ++ glb_iface->input = iface_fw_to_cpu_addr(ptdev, glb_iface->control->input_va); ++ glb_iface->output = iface_fw_to_cpu_addr(ptdev, glb_iface->control->output_va); ++ if (!glb_iface->input || !glb_iface->output) { ++ drm_err(&ptdev->base, "Invalid global control interface input/output VA"); ++ return -EINVAL; ++ } ++ ++ if (glb_iface->control->group_num > MAX_CSGS || ++ glb_iface->control->group_num < MIN_CSGS) { ++ drm_err(&ptdev->base, "Invalid number of control groups"); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < glb_iface->control->group_num; i++) { ++ int ret = panthor_init_csg_iface(ptdev, i); ++ ++ if (ret) ++ return ret; ++ } ++ ++ drm_info(&ptdev->base, "CSF FW v%d.%d.%d, Features %#x Instrumentation features %#x", ++ CSF_IFACE_VERSION_MAJOR(glb_iface->control->version), ++ CSF_IFACE_VERSION_MINOR(glb_iface->control->version), ++ CSF_IFACE_VERSION_PATCH(glb_iface->control->version), ++ glb_iface->control->features, ++ panthor_get_instr_features(ptdev)); ++ return 0; ++} ++ ++static void panthor_fw_init_global_iface(struct panthor_device *ptdev) ++{ ++ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); ++ ++ /* Enable all cores. */ ++ glb_iface->input->core_en_mask = ptdev->gpu_info.shader_present; ++ ++ /* Setup timers. */ ++ glb_iface->input->poweroff_timer = panthor_fw_conv_timeout(ptdev, PWROFF_HYSTERESIS_US); ++ glb_iface->input->progress_timer = PROGRESS_TIMEOUT_CYCLES >> PROGRESS_TIMEOUT_SCALE_SHIFT; ++ glb_iface->input->idle_timer = panthor_fw_conv_timeout(ptdev, IDLE_HYSTERESIS_US); ++ ++ /* Enable interrupts we care about. */ ++ glb_iface->input->ack_irq_mask = GLB_CFG_ALLOC_EN | ++ GLB_PING | ++ GLB_CFG_PROGRESS_TIMER | ++ GLB_CFG_POWEROFF_TIMER | ++ GLB_IDLE_EN | ++ GLB_IDLE; ++ ++ panthor_fw_update_reqs(glb_iface, req, GLB_IDLE_EN, GLB_IDLE_EN); ++ panthor_fw_toggle_reqs(glb_iface, req, ack, ++ GLB_CFG_ALLOC_EN | ++ GLB_CFG_POWEROFF_TIMER | ++ GLB_CFG_PROGRESS_TIMER); ++ ++ gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1); ++ ++ /* Kick the watchdog. */ ++ mod_delayed_work(ptdev->reset.wq, &ptdev->fw->watchdog.ping_work, ++ msecs_to_jiffies(PING_INTERVAL_MS)); ++} ++ ++static void panthor_job_irq_handler(struct panthor_device *ptdev, u32 status) ++{ ++ if (!ptdev->fw->booted && (status & JOB_INT_GLOBAL_IF)) ++ ptdev->fw->booted = true; ++ ++ wake_up_all(&ptdev->fw->req_waitqueue); ++ ++ /* If the FW is not booted, don't process IRQs, just flag the FW as booted. */ ++ if (!ptdev->fw->booted) ++ return; ++ ++ panthor_sched_report_fw_events(ptdev, status); ++} ++PANTHOR_IRQ_HANDLER(job, JOB, panthor_job_irq_handler); ++ ++static int panthor_fw_start(struct panthor_device *ptdev) ++{ ++ bool timedout = false; ++ ++ ptdev->fw->booted = false; ++ panthor_job_irq_resume(&ptdev->fw->irq, ~0); ++ gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_AUTO); ++ ++ if (!wait_event_timeout(ptdev->fw->req_waitqueue, ++ ptdev->fw->booted, ++ msecs_to_jiffies(1000))) { ++ if (!ptdev->fw->booted && ++ !(gpu_read(ptdev, JOB_INT_STAT) & JOB_INT_GLOBAL_IF)) ++ timedout = true; ++ } ++ ++ if (timedout) { ++ static const char * const status_str[] = { ++ [MCU_STATUS_DISABLED] = "disabled", ++ [MCU_STATUS_ENABLED] = "enabled", ++ [MCU_STATUS_HALT] = "halt", ++ [MCU_STATUS_FATAL] = "fatal", ++ }; ++ u32 status = gpu_read(ptdev, MCU_STATUS); ++ ++ drm_err(&ptdev->base, "Failed to boot MCU (status=%s)", ++ status < ARRAY_SIZE(status_str) ? status_str[status] : "unknown"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static void panthor_fw_stop(struct panthor_device *ptdev) ++{ ++ u32 status; ++ ++ gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_DISABLE); ++ if (readl_poll_timeout(ptdev->iomem + MCU_STATUS, status, ++ status == MCU_STATUS_DISABLED, 10, 100000)) ++ drm_err(&ptdev->base, "Failed to stop MCU"); ++} ++ ++/** ++ * panthor_fw_pre_reset() - Call before a reset. ++ * @ptdev: Device. ++ * @on_hang: true if the reset was triggered on a GPU hang. ++ * ++ * If the reset is not triggered on a hang, we try to gracefully halt the ++ * MCU, so we can do a fast-reset when panthor_fw_post_reset() is called. ++ */ ++void panthor_fw_pre_reset(struct panthor_device *ptdev, bool on_hang) ++{ ++ /* Make sure we won't be woken up by a ping. */ ++ cancel_delayed_work_sync(&ptdev->fw->watchdog.ping_work); ++ ++ ptdev->fw->fast_reset = false; ++ ++ if (!on_hang) { ++ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); ++ u32 status; ++ ++ panthor_fw_update_reqs(glb_iface, req, GLB_HALT, GLB_HALT); ++ gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1); ++ if (!readl_poll_timeout(ptdev->iomem + MCU_STATUS, status, ++ status == MCU_STATUS_HALT, 10, 100000) && ++ glb_iface->output->halt_status == PANTHOR_FW_HALT_OK) { ++ ptdev->fw->fast_reset = true; ++ } else { ++ drm_warn(&ptdev->base, "Failed to cleanly suspend MCU"); ++ } ++ ++ /* The FW detects 0 -> 1 transitions. Make sure we reset ++ * the HALT bit before the FW is rebooted. ++ */ ++ panthor_fw_update_reqs(glb_iface, req, 0, GLB_HALT); ++ } ++ ++ panthor_job_irq_suspend(&ptdev->fw->irq); ++} ++ ++/** ++ * panthor_fw_post_reset() - Call after a reset. ++ * @ptdev: Device. ++ * ++ * Start the FW. If this is not a fast reset, all FW sections are reloaded to ++ * make sure we can recover from a memory corruption. ++ */ ++int panthor_fw_post_reset(struct panthor_device *ptdev) ++{ ++ int ret; ++ ++ /* Make the MCU VM active. */ ++ ret = panthor_vm_active(ptdev->fw->vm); ++ if (ret) ++ return ret; ++ ++ /* If this is a fast reset, try to start the MCU without reloading ++ * the FW sections. If it fails, go for a full reset. ++ */ ++ if (ptdev->fw->fast_reset) { ++ ret = panthor_fw_start(ptdev); ++ if (!ret) ++ goto out; ++ ++ /* Force a disable, so we get a fresh boot on the next ++ * panthor_fw_start() call. ++ */ ++ gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_DISABLE); ++ drm_err(&ptdev->base, "FW fast reset failed, trying a slow reset"); ++ } ++ ++ /* Reload all sections, including RO ones. We're not supposed ++ * to end up here anyway, let's just assume the overhead of ++ * reloading everything is acceptable. ++ */ ++ panthor_reload_fw_sections(ptdev, true); ++ ++ ret = panthor_fw_start(ptdev); ++ if (ret) { ++ drm_err(&ptdev->base, "FW slow reset failed"); ++ return ret; ++ } ++ ++out: ++ /* We must re-initialize the global interface even on fast-reset. */ ++ panthor_fw_init_global_iface(ptdev); ++ return 0; ++} ++ ++/** ++ * panthor_fw_unplug() - Called when the device is unplugged. ++ * @ptdev: Device. ++ * ++ * This function must make sure all pending operations are flushed before ++ * will release device resources, thus preventing any interaction with ++ * the HW. ++ * ++ * If there is still FW-related work running after this function returns, ++ * they must use drm_dev_{enter,exit}() and skip any HW access when ++ * drm_dev_enter() returns false. ++ */ ++void panthor_fw_unplug(struct panthor_device *ptdev) ++{ ++ struct panthor_fw_section *section; ++ ++ cancel_delayed_work_sync(&ptdev->fw->watchdog.ping_work); ++ ++ /* Make sure the IRQ handler can be called after that point. */ ++ if (ptdev->fw->irq.irq) ++ panthor_job_irq_suspend(&ptdev->fw->irq); ++ ++ panthor_fw_stop(ptdev); ++ ++ list_for_each_entry(section, &ptdev->fw->sections, node) ++ panthor_kernel_bo_destroy(panthor_fw_vm(ptdev), section->mem); ++ ++ /* We intentionally don't call panthor_vm_idle() and let ++ * panthor_mmu_unplug() release the AS we acquired with ++ * panthor_vm_active() so we don't have to track the VM active/idle ++ * state to keep the active_refcnt balanced. ++ */ ++ panthor_vm_put(ptdev->fw->vm); ++ ++ panthor_gpu_power_off(ptdev, L2, ptdev->gpu_info.l2_present, 20000); ++} ++ ++/** ++ * panthor_fw_wait_acks() - Wait for requests to be acknowledged by the FW. ++ * @req_ptr: Pointer to the req register. ++ * @ack_ptr: Pointer to the ack register. ++ * @wq: Wait queue to use for the sleeping wait. ++ * @req_mask: Mask of requests to wait for. ++ * @acked: Pointer to field that's updated with the acked requests. ++ * If the function returns 0, *acked == req_mask. ++ * @timeout_ms: Timeout expressed in milliseconds. ++ * ++ * Return: 0 on success, -ETIMEDOUT otherwise. ++ */ ++static int panthor_fw_wait_acks(const u32 *req_ptr, const u32 *ack_ptr, ++ wait_queue_head_t *wq, ++ u32 req_mask, u32 *acked, ++ u32 timeout_ms) ++{ ++ u32 ack, req = READ_ONCE(*req_ptr) & req_mask; ++ int ret; ++ ++ /* Busy wait for a few µsecs before falling back to a sleeping wait. */ ++ *acked = req_mask; ++ ret = read_poll_timeout_atomic(READ_ONCE, ack, ++ (ack & req_mask) == req, ++ 0, 10, 0, ++ *ack_ptr); ++ if (!ret) ++ return 0; ++ ++ if (wait_event_timeout(*wq, (READ_ONCE(*ack_ptr) & req_mask) == req, ++ msecs_to_jiffies(timeout_ms))) ++ return 0; ++ ++ /* Check one last time, in case we were not woken up for some reason. */ ++ ack = READ_ONCE(*ack_ptr); ++ if ((ack & req_mask) == req) ++ return 0; ++ ++ *acked = ~(req ^ ack) & req_mask; ++ return -ETIMEDOUT; ++} ++ ++/** ++ * panthor_fw_glb_wait_acks() - Wait for global requests to be acknowledged. ++ * @ptdev: Device. ++ * @req_mask: Mask of requests to wait for. ++ * @acked: Pointer to field that's updated with the acked requests. ++ * If the function returns 0, *acked == req_mask. ++ * @timeout_ms: Timeout expressed in milliseconds. ++ * ++ * Return: 0 on success, -ETIMEDOUT otherwise. ++ */ ++int panthor_fw_glb_wait_acks(struct panthor_device *ptdev, ++ u32 req_mask, u32 *acked, ++ u32 timeout_ms) ++{ ++ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); ++ ++ /* GLB_HALT doesn't get acked through the FW interface. */ ++ if (drm_WARN_ON(&ptdev->base, req_mask & (~GLB_REQ_MASK | GLB_HALT))) ++ return -EINVAL; ++ ++ return panthor_fw_wait_acks(&glb_iface->input->req, ++ &glb_iface->output->ack, ++ &ptdev->fw->req_waitqueue, ++ req_mask, acked, timeout_ms); ++} ++ ++/** ++ * panthor_fw_csg_wait_acks() - Wait for command stream group requests to be acknowledged. ++ * @ptdev: Device. ++ * @csg_slot: CSG slot ID. ++ * @req_mask: Mask of requests to wait for. ++ * @acked: Pointer to field that's updated with the acked requests. ++ * If the function returns 0, *acked == req_mask. ++ * @timeout_ms: Timeout expressed in milliseconds. ++ * ++ * Return: 0 on success, -ETIMEDOUT otherwise. ++ */ ++int panthor_fw_csg_wait_acks(struct panthor_device *ptdev, u32 csg_slot, ++ u32 req_mask, u32 *acked, u32 timeout_ms) ++{ ++ struct panthor_fw_csg_iface *csg_iface = panthor_fw_get_csg_iface(ptdev, csg_slot); ++ int ret; ++ ++ if (drm_WARN_ON(&ptdev->base, req_mask & ~CSG_REQ_MASK)) ++ return -EINVAL; ++ ++ ret = panthor_fw_wait_acks(&csg_iface->input->req, ++ &csg_iface->output->ack, ++ &ptdev->fw->req_waitqueue, ++ req_mask, acked, timeout_ms); ++ ++ /* ++ * Check that all bits in the state field were updated, if any mismatch ++ * then clear all bits in the state field. This allows code to do ++ * (acked & CSG_STATE_MASK) and get the right value. ++ */ ++ ++ if ((*acked & CSG_STATE_MASK) != CSG_STATE_MASK) ++ *acked &= ~CSG_STATE_MASK; ++ ++ return ret; ++} ++ ++/** ++ * panthor_fw_ring_csg_doorbells() - Ring command stream group doorbells. ++ * @ptdev: Device. ++ * @csg_mask: Bitmask encoding the command stream group doorbells to ring. ++ * ++ * This function is toggling bits in the doorbell_req and ringing the ++ * global doorbell. It doesn't require a user doorbell to be attached to ++ * the group. ++ */ ++void panthor_fw_ring_csg_doorbells(struct panthor_device *ptdev, u32 csg_mask) ++{ ++ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); ++ ++ panthor_fw_toggle_reqs(glb_iface, doorbell_req, doorbell_ack, csg_mask); ++ gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1); ++} ++ ++static void panthor_fw_ping_work(struct work_struct *work) ++{ ++ struct panthor_fw *fw = container_of(work, struct panthor_fw, watchdog.ping_work.work); ++ struct panthor_device *ptdev = fw->irq.ptdev; ++ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); ++ u32 acked; ++ int ret; ++ ++ if (panthor_device_reset_is_pending(ptdev)) ++ return; ++ ++ panthor_fw_toggle_reqs(glb_iface, req, ack, GLB_PING); ++ gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1); ++ ++ ret = panthor_fw_glb_wait_acks(ptdev, GLB_PING, &acked, 100); ++ if (ret) { ++ panthor_device_schedule_reset(ptdev); ++ drm_err(&ptdev->base, "FW ping timeout, scheduling a reset"); ++ } else { ++ mod_delayed_work(ptdev->reset.wq, &fw->watchdog.ping_work, ++ msecs_to_jiffies(PING_INTERVAL_MS)); ++ } ++} ++ ++/** ++ * panthor_fw_init() - Initialize FW related data. ++ * @ptdev: Device. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++int panthor_fw_init(struct panthor_device *ptdev) ++{ ++ struct panthor_fw *fw; ++ int ret, irq; ++ ++ fw = drmm_kzalloc(&ptdev->base, sizeof(*fw), GFP_KERNEL); ++ if (!fw) ++ return -ENOMEM; ++ ++ ptdev->fw = fw; ++ init_waitqueue_head(&fw->req_waitqueue); ++ INIT_LIST_HEAD(&fw->sections); ++ INIT_DELAYED_WORK(&fw->watchdog.ping_work, panthor_fw_ping_work); ++ ++ irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "job"); ++ if (irq <= 0) ++ return -ENODEV; ++ ++ ret = panthor_request_job_irq(ptdev, &fw->irq, irq, 0); ++ if (ret) { ++ drm_err(&ptdev->base, "failed to request job irq"); ++ return ret; ++ } ++ ++ ret = panthor_gpu_l2_power_on(ptdev); ++ if (ret) ++ return ret; ++ ++ fw->vm = panthor_vm_create(ptdev, true, ++ 0, SZ_4G, ++ CSF_MCU_SHARED_REGION_START, ++ CSF_MCU_SHARED_REGION_SIZE); ++ if (IS_ERR(fw->vm)) { ++ ret = PTR_ERR(fw->vm); ++ fw->vm = NULL; ++ goto err_unplug_fw; ++ } ++ ++ ret = panthor_fw_load(ptdev); ++ if (ret) ++ goto err_unplug_fw; ++ ++ ret = panthor_vm_active(fw->vm); ++ if (ret) ++ goto err_unplug_fw; ++ ++ ret = panthor_fw_start(ptdev); ++ if (ret) ++ goto err_unplug_fw; ++ ++ ret = panthor_fw_init_ifaces(ptdev); ++ if (ret) ++ goto err_unplug_fw; ++ ++ panthor_fw_init_global_iface(ptdev); ++ return 0; ++ ++err_unplug_fw: ++ panthor_fw_unplug(ptdev); ++ return ret; ++} ++ ++MODULE_FIRMWARE("arm/mali/arch10.8/mali_csffw.bin"); +diff --git a/drivers/gpu/drm/panthor/panthor_fw.h b/drivers/gpu/drm/panthor/panthor_fw.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_fw.h +@@ -0,0 +1,503 @@ ++/* SPDX-License-Identifier: GPL-2.0 or MIT */ ++/* Copyright 2023 Collabora ltd. */ ++ ++#ifndef __PANTHOR_MCU_H__ ++#define __PANTHOR_MCU_H__ ++ ++#include ++ ++struct panthor_device; ++struct panthor_kernel_bo; ++ ++#define MAX_CSGS 31 ++#define MAX_CS_PER_CSG 32 ++ ++struct panthor_fw_ringbuf_input_iface { ++ u64 insert; ++ u64 extract; ++}; ++ ++struct panthor_fw_ringbuf_output_iface { ++ u64 extract; ++ u32 active; ++}; ++ ++struct panthor_fw_cs_control_iface { ++#define CS_FEATURES_WORK_REGS(x) (((x) & GENMASK(7, 0)) + 1) ++#define CS_FEATURES_SCOREBOARDS(x) (((x) & GENMASK(15, 8)) >> 8) ++#define CS_FEATURES_COMPUTE BIT(16) ++#define CS_FEATURES_FRAGMENT BIT(17) ++#define CS_FEATURES_TILER BIT(18) ++ u32 features; ++ u32 input_va; ++ u32 output_va; ++}; ++ ++struct panthor_fw_cs_input_iface { ++#define CS_STATE_MASK GENMASK(2, 0) ++#define CS_STATE_STOP 0 ++#define CS_STATE_START 1 ++#define CS_EXTRACT_EVENT BIT(4) ++#define CS_IDLE_SYNC_WAIT BIT(8) ++#define CS_IDLE_PROTM_PENDING BIT(9) ++#define CS_IDLE_EMPTY BIT(10) ++#define CS_IDLE_RESOURCE_REQ BIT(11) ++#define CS_TILER_OOM BIT(26) ++#define CS_PROTM_PENDING BIT(27) ++#define CS_FATAL BIT(30) ++#define CS_FAULT BIT(31) ++#define CS_REQ_MASK (CS_STATE_MASK | \ ++ CS_EXTRACT_EVENT | \ ++ CS_IDLE_SYNC_WAIT | \ ++ CS_IDLE_PROTM_PENDING | \ ++ CS_IDLE_EMPTY | \ ++ CS_IDLE_RESOURCE_REQ) ++#define CS_EVT_MASK (CS_TILER_OOM | \ ++ CS_PROTM_PENDING | \ ++ CS_FATAL | \ ++ CS_FAULT) ++ u32 req; ++ ++#define CS_CONFIG_PRIORITY(x) ((x) & GENMASK(3, 0)) ++#define CS_CONFIG_DOORBELL(x) (((x) << 8) & GENMASK(15, 8)) ++ u32 config; ++ u32 reserved1; ++ u32 ack_irq_mask; ++ u64 ringbuf_base; ++ u32 ringbuf_size; ++ u32 reserved2; ++ u64 heap_start; ++ u64 heap_end; ++ u64 ringbuf_input; ++ u64 ringbuf_output; ++ u32 instr_config; ++ u32 instrbuf_size; ++ u64 instrbuf_base; ++ u64 instrbuf_offset_ptr; ++}; ++ ++struct panthor_fw_cs_output_iface { ++ u32 ack; ++ u32 reserved1[15]; ++ u64 status_cmd_ptr; ++ ++#define CS_STATUS_WAIT_SB_MASK GENMASK(15, 0) ++#define CS_STATUS_WAIT_SB_SRC_MASK GENMASK(19, 16) ++#define CS_STATUS_WAIT_SB_SRC_NONE (0 << 16) ++#define CS_STATUS_WAIT_SB_SRC_WAIT (8 << 16) ++#define CS_STATUS_WAIT_SYNC_COND_LE (0 << 24) ++#define CS_STATUS_WAIT_SYNC_COND_GT (1 << 24) ++#define CS_STATUS_WAIT_SYNC_COND_MASK GENMASK(27, 24) ++#define CS_STATUS_WAIT_PROGRESS BIT(28) ++#define CS_STATUS_WAIT_PROTM BIT(29) ++#define CS_STATUS_WAIT_SYNC_64B BIT(30) ++#define CS_STATUS_WAIT_SYNC BIT(31) ++ u32 status_wait; ++ u32 status_req_resource; ++ u64 status_wait_sync_ptr; ++ u32 status_wait_sync_value; ++ u32 status_scoreboards; ++ ++#define CS_STATUS_BLOCKED_REASON_UNBLOCKED 0 ++#define CS_STATUS_BLOCKED_REASON_SB_WAIT 1 ++#define CS_STATUS_BLOCKED_REASON_PROGRESS_WAIT 2 ++#define CS_STATUS_BLOCKED_REASON_SYNC_WAIT 3 ++#define CS_STATUS_BLOCKED_REASON_DEFERRED 5 ++#define CS_STATUS_BLOCKED_REASON_RES 6 ++#define CS_STATUS_BLOCKED_REASON_FLUSH 7 ++#define CS_STATUS_BLOCKED_REASON_MASK GENMASK(3, 0) ++ u32 status_blocked_reason; ++ u32 status_wait_sync_value_hi; ++ u32 reserved2[6]; ++ ++#define CS_EXCEPTION_TYPE(x) ((x) & GENMASK(7, 0)) ++#define CS_EXCEPTION_DATA(x) (((x) >> 8) & GENMASK(23, 0)) ++ u32 fault; ++ u32 fatal; ++ u64 fault_info; ++ u64 fatal_info; ++ u32 reserved3[10]; ++ u32 heap_vt_start; ++ u32 heap_vt_end; ++ u32 reserved4; ++ u32 heap_frag_end; ++ u64 heap_address; ++}; ++ ++struct panthor_fw_csg_control_iface { ++ u32 features; ++ u32 input_va; ++ u32 output_va; ++ u32 suspend_size; ++ u32 protm_suspend_size; ++ u32 stream_num; ++ u32 stream_stride; ++}; ++ ++struct panthor_fw_csg_input_iface { ++#define CSG_STATE_MASK GENMASK(2, 0) ++#define CSG_STATE_TERMINATE 0 ++#define CSG_STATE_START 1 ++#define CSG_STATE_SUSPEND 2 ++#define CSG_STATE_RESUME 3 ++#define CSG_ENDPOINT_CONFIG BIT(4) ++#define CSG_STATUS_UPDATE BIT(5) ++#define CSG_SYNC_UPDATE BIT(28) ++#define CSG_IDLE BIT(29) ++#define CSG_DOORBELL BIT(30) ++#define CSG_PROGRESS_TIMER_EVENT BIT(31) ++#define CSG_REQ_MASK (CSG_STATE_MASK | \ ++ CSG_ENDPOINT_CONFIG | \ ++ CSG_STATUS_UPDATE) ++#define CSG_EVT_MASK (CSG_SYNC_UPDATE | \ ++ CSG_IDLE | \ ++ CSG_PROGRESS_TIMER_EVENT) ++ u32 req; ++ u32 ack_irq_mask; ++ ++ u32 doorbell_req; ++ u32 cs_irq_ack; ++ u32 reserved1[4]; ++ u64 allow_compute; ++ u64 allow_fragment; ++ u32 allow_other; ++ ++#define CSG_EP_REQ_COMPUTE(x) ((x) & GENMASK(7, 0)) ++#define CSG_EP_REQ_FRAGMENT(x) (((x) << 8) & GENMASK(15, 8)) ++#define CSG_EP_REQ_TILER(x) (((x) << 16) & GENMASK(19, 16)) ++#define CSG_EP_REQ_EXCL_COMPUTE BIT(20) ++#define CSG_EP_REQ_EXCL_FRAGMENT BIT(21) ++#define CSG_EP_REQ_PRIORITY(x) (((x) << 28) & GENMASK(31, 28)) ++#define CSG_EP_REQ_PRIORITY_MASK GENMASK(31, 28) ++ u32 endpoint_req; ++ u32 reserved2[2]; ++ u64 suspend_buf; ++ u64 protm_suspend_buf; ++ u32 config; ++ u32 iter_trace_config; ++}; ++ ++struct panthor_fw_csg_output_iface { ++ u32 ack; ++ u32 reserved1; ++ u32 doorbell_ack; ++ u32 cs_irq_req; ++ u32 status_endpoint_current; ++ u32 status_endpoint_req; ++ ++#define CSG_STATUS_STATE_IS_IDLE BIT(0) ++ u32 status_state; ++ u32 resource_dep; ++}; ++ ++struct panthor_fw_global_control_iface { ++ u32 version; ++ u32 features; ++ u32 input_va; ++ u32 output_va; ++ u32 group_num; ++ u32 group_stride; ++ u32 perfcnt_size; ++ u32 instr_features; ++}; ++ ++struct panthor_fw_global_input_iface { ++#define GLB_HALT BIT(0) ++#define GLB_CFG_PROGRESS_TIMER BIT(1) ++#define GLB_CFG_ALLOC_EN BIT(2) ++#define GLB_CFG_POWEROFF_TIMER BIT(3) ++#define GLB_PROTM_ENTER BIT(4) ++#define GLB_PERFCNT_EN BIT(5) ++#define GLB_PERFCNT_SAMPLE BIT(6) ++#define GLB_COUNTER_EN BIT(7) ++#define GLB_PING BIT(8) ++#define GLB_FWCFG_UPDATE BIT(9) ++#define GLB_IDLE_EN BIT(10) ++#define GLB_SLEEP BIT(12) ++#define GLB_INACTIVE_COMPUTE BIT(20) ++#define GLB_INACTIVE_FRAGMENT BIT(21) ++#define GLB_INACTIVE_TILER BIT(22) ++#define GLB_PROTM_EXIT BIT(23) ++#define GLB_PERFCNT_THRESHOLD BIT(24) ++#define GLB_PERFCNT_OVERFLOW BIT(25) ++#define GLB_IDLE BIT(26) ++#define GLB_DBG_CSF BIT(30) ++#define GLB_DBG_HOST BIT(31) ++#define GLB_REQ_MASK GENMASK(10, 0) ++#define GLB_EVT_MASK GENMASK(26, 20) ++ u32 req; ++ u32 ack_irq_mask; ++ u32 doorbell_req; ++ u32 reserved1; ++ u32 progress_timer; ++ ++#define GLB_TIMER_VAL(x) ((x) & GENMASK(30, 0)) ++#define GLB_TIMER_SOURCE_GPU_COUNTER BIT(31) ++ u32 poweroff_timer; ++ u64 core_en_mask; ++ u32 reserved2; ++ u32 perfcnt_as; ++ u64 perfcnt_base; ++ u32 perfcnt_extract; ++ u32 reserved3[3]; ++ u32 perfcnt_config; ++ u32 perfcnt_csg_select; ++ u32 perfcnt_fw_enable; ++ u32 perfcnt_csg_enable; ++ u32 perfcnt_csf_enable; ++ u32 perfcnt_shader_enable; ++ u32 perfcnt_tiler_enable; ++ u32 perfcnt_mmu_l2_enable; ++ u32 reserved4[8]; ++ u32 idle_timer; ++}; ++ ++enum panthor_fw_halt_status { ++ PANTHOR_FW_HALT_OK = 0, ++ PANTHOR_FW_HALT_ON_PANIC = 0x4e, ++ PANTHOR_FW_HALT_ON_WATCHDOG_EXPIRATION = 0x4f, ++}; ++ ++struct panthor_fw_global_output_iface { ++ u32 ack; ++ u32 reserved1; ++ u32 doorbell_ack; ++ u32 reserved2; ++ u32 halt_status; ++ u32 perfcnt_status; ++ u32 perfcnt_insert; ++}; ++ ++/** ++ * struct panthor_fw_cs_iface - Firmware command stream slot interface ++ */ ++struct panthor_fw_cs_iface { ++ /** ++ * @lock: Lock protecting access to the panthor_fw_cs_input_iface::req ++ * field. ++ * ++ * Needed so we can update the req field concurrently from the interrupt ++ * handler and the scheduler logic. ++ * ++ * TODO: Ideally we'd want to use a cmpxchg() to update the req, but FW ++ * interface sections are mapped uncached/write-combined right now, and ++ * using cmpxchg() on such mappings leads to SError faults. Revisit when ++ * we have 'SHARED' GPU mappings hooked up. ++ */ ++ spinlock_t lock; ++ ++ /** ++ * @control: Command stream slot control interface. ++ * ++ * Used to expose command stream slot properties. ++ * ++ * This interface is read-only. ++ */ ++ struct panthor_fw_cs_control_iface *control; ++ ++ /** ++ * @input: Command stream slot input interface. ++ * ++ * Used for host updates/events. ++ */ ++ struct panthor_fw_cs_input_iface *input; ++ ++ /** ++ * @output: Command stream slot output interface. ++ * ++ * Used for FW updates/events. ++ * ++ * This interface is read-only. ++ */ ++ const struct panthor_fw_cs_output_iface *output; ++}; ++ ++/** ++ * struct panthor_fw_csg_iface - Firmware command stream group slot interface ++ */ ++struct panthor_fw_csg_iface { ++ /** ++ * @lock: Lock protecting access to the panthor_fw_csg_input_iface::req ++ * field. ++ * ++ * Needed so we can update the req field concurrently from the interrupt ++ * handler and the scheduler logic. ++ * ++ * TODO: Ideally we'd want to use a cmpxchg() to update the req, but FW ++ * interface sections are mapped uncached/write-combined right now, and ++ * using cmpxchg() on such mappings leads to SError faults. Revisit when ++ * we have 'SHARED' GPU mappings hooked up. ++ */ ++ spinlock_t lock; ++ ++ /** ++ * @control: Command stream group slot control interface. ++ * ++ * Used to expose command stream group slot properties. ++ * ++ * This interface is read-only. ++ */ ++ const struct panthor_fw_csg_control_iface *control; ++ ++ /** ++ * @input: Command stream slot input interface. ++ * ++ * Used for host updates/events. ++ */ ++ struct panthor_fw_csg_input_iface *input; ++ ++ /** ++ * @output: Command stream group slot output interface. ++ * ++ * Used for FW updates/events. ++ * ++ * This interface is read-only. ++ */ ++ const struct panthor_fw_csg_output_iface *output; ++}; ++ ++/** ++ * struct panthor_fw_global_iface - Firmware global interface ++ */ ++struct panthor_fw_global_iface { ++ /** ++ * @lock: Lock protecting access to the panthor_fw_global_input_iface::req ++ * field. ++ * ++ * Needed so we can update the req field concurrently from the interrupt ++ * handler and the scheduler/FW management logic. ++ * ++ * TODO: Ideally we'd want to use a cmpxchg() to update the req, but FW ++ * interface sections are mapped uncached/write-combined right now, and ++ * using cmpxchg() on such mappings leads to SError faults. Revisit when ++ * we have 'SHARED' GPU mappings hooked up. ++ */ ++ spinlock_t lock; ++ ++ /** ++ * @control: Command stream group slot control interface. ++ * ++ * Used to expose global FW properties. ++ * ++ * This interface is read-only. ++ */ ++ const struct panthor_fw_global_control_iface *control; ++ ++ /** ++ * @input: Global input interface. ++ * ++ * Used for host updates/events. ++ */ ++ struct panthor_fw_global_input_iface *input; ++ ++ /** ++ * @output: Global output interface. ++ * ++ * Used for FW updates/events. ++ * ++ * This interface is read-only. ++ */ ++ const struct panthor_fw_global_output_iface *output; ++}; ++ ++/** ++ * panthor_fw_toggle_reqs() - Toggle acknowledge bits to send an event to the FW ++ * @__iface: The interface to operate on. ++ * @__in_reg: Name of the register to update in the input section of the interface. ++ * @__out_reg: Name of the register to take as a reference in the output section of the ++ * interface. ++ * @__mask: Mask to apply to the update. ++ * ++ * The Host -> FW event/message passing was designed to be lockless, with each side of ++ * the channel having its writeable section. Events are signaled as a difference between ++ * the host and FW side in the req/ack registers (when a bit differs, there's an event ++ * pending, when they are the same, nothing needs attention). ++ * ++ * This helper allows one to update the req register based on the current value of the ++ * ack register managed by the FW. Toggling a specific bit will flag an event. In order ++ * for events to be re-evaluated, the interface doorbell needs to be rung. ++ * ++ * Concurrent accesses to the same req register is covered. ++ * ++ * Anything requiring atomic updates to multiple registers requires a dedicated lock. ++ */ ++#define panthor_fw_toggle_reqs(__iface, __in_reg, __out_reg, __mask) \ ++ do { \ ++ u32 __cur_val, __new_val, __out_val; \ ++ spin_lock(&(__iface)->lock); \ ++ __cur_val = READ_ONCE((__iface)->input->__in_reg); \ ++ __out_val = READ_ONCE((__iface)->output->__out_reg); \ ++ __new_val = ((__out_val ^ (__mask)) & (__mask)) | (__cur_val & ~(__mask)); \ ++ WRITE_ONCE((__iface)->input->__in_reg, __new_val); \ ++ spin_unlock(&(__iface)->lock); \ ++ } while (0) ++ ++/** ++ * panthor_fw_update_reqs() - Update bits to reflect a configuration change ++ * @__iface: The interface to operate on. ++ * @__in_reg: Name of the register to update in the input section of the interface. ++ * @__val: Value to set. ++ * @__mask: Mask to apply to the update. ++ * ++ * Some configuration get passed through req registers that are also used to ++ * send events to the FW. Those req registers being updated from the interrupt ++ * handler, they require special helpers to update the configuration part as well. ++ * ++ * Concurrent accesses to the same req register is covered. ++ * ++ * Anything requiring atomic updates to multiple registers requires a dedicated lock. ++ */ ++#define panthor_fw_update_reqs(__iface, __in_reg, __val, __mask) \ ++ do { \ ++ u32 __cur_val, __new_val; \ ++ spin_lock(&(__iface)->lock); \ ++ __cur_val = READ_ONCE((__iface)->input->__in_reg); \ ++ __new_val = (__cur_val & ~(__mask)) | ((__val) & (__mask)); \ ++ WRITE_ONCE((__iface)->input->__in_reg, __new_val); \ ++ spin_unlock(&(__iface)->lock); \ ++ } while (0) ++ ++struct panthor_fw_global_iface * ++panthor_fw_get_glb_iface(struct panthor_device *ptdev); ++ ++struct panthor_fw_csg_iface * ++panthor_fw_get_csg_iface(struct panthor_device *ptdev, u32 csg_slot); ++ ++struct panthor_fw_cs_iface * ++panthor_fw_get_cs_iface(struct panthor_device *ptdev, u32 csg_slot, u32 cs_slot); ++ ++int panthor_fw_csg_wait_acks(struct panthor_device *ptdev, u32 csg_id, u32 req_mask, ++ u32 *acked, u32 timeout_ms); ++ ++int panthor_fw_glb_wait_acks(struct panthor_device *ptdev, u32 req_mask, u32 *acked, ++ u32 timeout_ms); ++ ++void panthor_fw_ring_csg_doorbells(struct panthor_device *ptdev, u32 csg_slot); ++ ++struct panthor_kernel_bo * ++panthor_fw_alloc_queue_iface_mem(struct panthor_device *ptdev, ++ struct panthor_fw_ringbuf_input_iface **input, ++ const struct panthor_fw_ringbuf_output_iface **output, ++ u32 *input_fw_va, u32 *output_fw_va); ++struct panthor_kernel_bo * ++panthor_fw_alloc_suspend_buf_mem(struct panthor_device *ptdev, size_t size); ++ ++struct panthor_vm *panthor_fw_vm(struct panthor_device *ptdev); ++ ++void panthor_fw_pre_reset(struct panthor_device *ptdev, bool on_hang); ++int panthor_fw_post_reset(struct panthor_device *ptdev); ++ ++static inline void panthor_fw_suspend(struct panthor_device *ptdev) ++{ ++ panthor_fw_pre_reset(ptdev, false); ++} ++ ++static inline int panthor_fw_resume(struct panthor_device *ptdev) ++{ ++ return panthor_fw_post_reset(ptdev); ++} ++ ++int panthor_fw_init(struct panthor_device *ptdev); ++void panthor_fw_unplug(struct panthor_device *ptdev); ++ ++#endif +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:23 +0100 +Subject: drm/panthor: Add the heap logical block + +Tiler heap growing requires some kernel driver involvement: when the +tiler runs out of heap memory, it will raise an exception which is +either directly handled by the firmware if some free heap chunks are +available in the heap context, or passed back to the kernel otherwise. +The heap helpers will be used by the scheduler logic to allocate more +heap chunks to a heap context, when such a situation happens. + +Heap context creation is explicitly requested by userspace (using +the TILER_HEAP_CREATE ioctl), and the returned context is attached to a +queue through some command stream instruction. + +All the kernel does is keep the list of heap chunks allocated to a +context, so they can be freed when TILER_HEAP_DESTROY is called, or +extended when the FW requests a new chunk. + +v6: +- Add Maxime's and Heiko's acks + +v5: +- Fix FIXME comment +- Add Steve's R-b + +v4: +- Rework locking to allow concurrent calls to panthor_heap_grow() +- Add a helper to return a heap chunk if we couldn't pass it to the + FW because the group was scheduled out + +v3: +- Add a FIXME for the heap OOM deadlock +- Use the panthor_kernel_bo abstraction for the heap context and heap + chunks +- Drop the panthor_heap_gpu_ctx struct as it is opaque to the driver +- Ensure that the heap context is aligned to the GPU cache line size +- Minor code tidy ups + +Co-developed-by: Steven Price +Signed-off-by: Steven Price +Signed-off-by: Boris Brezillon +Reviewed-by: Steven Price +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + drivers/gpu/drm/panthor/panthor_heap.c | 597 ++++++++++ + drivers/gpu/drm/panthor/panthor_heap.h | 39 + + 2 files changed, 636 insertions(+) + +diff --git a/drivers/gpu/drm/panthor/panthor_heap.c b/drivers/gpu/drm/panthor/panthor_heap.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_heap.c +@@ -0,0 +1,597 @@ ++// SPDX-License-Identifier: GPL-2.0 or MIT ++/* Copyright 2023 Collabora ltd. */ ++ ++#include ++#include ++ ++#include ++ ++#include "panthor_device.h" ++#include "panthor_gem.h" ++#include "panthor_heap.h" ++#include "panthor_mmu.h" ++#include "panthor_regs.h" ++ ++/* ++ * The GPU heap context is an opaque structure used by the GPU to track the ++ * heap allocations. The driver should only touch it to initialize it (zero all ++ * fields). Because the CPU and GPU can both access this structure it is ++ * required to be GPU cache line aligned. ++ */ ++#define HEAP_CONTEXT_SIZE 32 ++ ++/** ++ * struct panthor_heap_chunk_header - Heap chunk header ++ */ ++struct panthor_heap_chunk_header { ++ /** ++ * @next: Next heap chunk in the list. ++ * ++ * This is a GPU VA. ++ */ ++ u64 next; ++ ++ /** @unknown: MBZ. */ ++ u32 unknown[14]; ++}; ++ ++/** ++ * struct panthor_heap_chunk - Structure used to keep track of allocated heap chunks. ++ */ ++struct panthor_heap_chunk { ++ /** @node: Used to insert the heap chunk in panthor_heap::chunks. */ ++ struct list_head node; ++ ++ /** @bo: Buffer object backing the heap chunk. */ ++ struct panthor_kernel_bo *bo; ++}; ++ ++/** ++ * struct panthor_heap - Structure used to manage tiler heap contexts. ++ */ ++struct panthor_heap { ++ /** @chunks: List containing all heap chunks allocated so far. */ ++ struct list_head chunks; ++ ++ /** @lock: Lock protecting insertion in the chunks list. */ ++ struct mutex lock; ++ ++ /** @chunk_size: Size of each chunk. */ ++ u32 chunk_size; ++ ++ /** @max_chunks: Maximum number of chunks. */ ++ u32 max_chunks; ++ ++ /** ++ * @target_in_flight: Number of in-flight render passes after which ++ * we'd let the FW wait for fragment job to finish instead of allocating new chunks. ++ */ ++ u32 target_in_flight; ++ ++ /** @chunk_count: Number of heap chunks currently allocated. */ ++ u32 chunk_count; ++}; ++ ++#define MAX_HEAPS_PER_POOL 128 ++ ++/** ++ * struct panthor_heap_pool - Pool of heap contexts ++ * ++ * The pool is attached to a panthor_file and can't be shared across processes. ++ */ ++struct panthor_heap_pool { ++ /** @refcount: Reference count. */ ++ struct kref refcount; ++ ++ /** @ptdev: Device. */ ++ struct panthor_device *ptdev; ++ ++ /** @vm: VM this pool is bound to. */ ++ struct panthor_vm *vm; ++ ++ /** @lock: Lock protecting access to @xa. */ ++ struct rw_semaphore lock; ++ ++ /** @xa: Array storing panthor_heap objects. */ ++ struct xarray xa; ++ ++ /** @gpu_contexts: Buffer object containing the GPU heap contexts. */ ++ struct panthor_kernel_bo *gpu_contexts; ++}; ++ ++static int panthor_heap_ctx_stride(struct panthor_device *ptdev) ++{ ++ u32 l2_features = ptdev->gpu_info.l2_features; ++ u32 gpu_cache_line_size = GPU_L2_FEATURES_LINE_SIZE(l2_features); ++ ++ return ALIGN(HEAP_CONTEXT_SIZE, gpu_cache_line_size); ++} ++ ++static int panthor_get_heap_ctx_offset(struct panthor_heap_pool *pool, int id) ++{ ++ return panthor_heap_ctx_stride(pool->ptdev) * id; ++} ++ ++static void *panthor_get_heap_ctx(struct panthor_heap_pool *pool, int id) ++{ ++ return pool->gpu_contexts->kmap + ++ panthor_get_heap_ctx_offset(pool, id); ++} ++ ++static void panthor_free_heap_chunk(struct panthor_vm *vm, ++ struct panthor_heap *heap, ++ struct panthor_heap_chunk *chunk) ++{ ++ mutex_lock(&heap->lock); ++ list_del(&chunk->node); ++ heap->chunk_count--; ++ mutex_unlock(&heap->lock); ++ ++ panthor_kernel_bo_destroy(vm, chunk->bo); ++ kfree(chunk); ++} ++ ++static int panthor_alloc_heap_chunk(struct panthor_device *ptdev, ++ struct panthor_vm *vm, ++ struct panthor_heap *heap, ++ bool initial_chunk) ++{ ++ struct panthor_heap_chunk *chunk; ++ struct panthor_heap_chunk_header *hdr; ++ int ret; ++ ++ chunk = kmalloc(sizeof(*chunk), GFP_KERNEL); ++ if (!chunk) ++ return -ENOMEM; ++ ++ chunk->bo = panthor_kernel_bo_create(ptdev, vm, heap->chunk_size, ++ DRM_PANTHOR_BO_NO_MMAP, ++ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC, ++ PANTHOR_VM_KERNEL_AUTO_VA); ++ if (IS_ERR(chunk->bo)) { ++ ret = PTR_ERR(chunk->bo); ++ goto err_free_chunk; ++ } ++ ++ ret = panthor_kernel_bo_vmap(chunk->bo); ++ if (ret) ++ goto err_destroy_bo; ++ ++ hdr = chunk->bo->kmap; ++ memset(hdr, 0, sizeof(*hdr)); ++ ++ if (initial_chunk && !list_empty(&heap->chunks)) { ++ struct panthor_heap_chunk *prev_chunk; ++ u64 prev_gpuva; ++ ++ prev_chunk = list_first_entry(&heap->chunks, ++ struct panthor_heap_chunk, ++ node); ++ ++ prev_gpuva = panthor_kernel_bo_gpuva(prev_chunk->bo); ++ hdr->next = (prev_gpuva & GENMASK_ULL(63, 12)) | ++ (heap->chunk_size >> 12); ++ } ++ ++ panthor_kernel_bo_vunmap(chunk->bo); ++ ++ mutex_lock(&heap->lock); ++ list_add(&chunk->node, &heap->chunks); ++ heap->chunk_count++; ++ mutex_unlock(&heap->lock); ++ ++ return 0; ++ ++err_destroy_bo: ++ panthor_kernel_bo_destroy(vm, chunk->bo); ++ ++err_free_chunk: ++ kfree(chunk); ++ ++ return ret; ++} ++ ++static void panthor_free_heap_chunks(struct panthor_vm *vm, ++ struct panthor_heap *heap) ++{ ++ struct panthor_heap_chunk *chunk, *tmp; ++ ++ list_for_each_entry_safe(chunk, tmp, &heap->chunks, node) ++ panthor_free_heap_chunk(vm, heap, chunk); ++} ++ ++static int panthor_alloc_heap_chunks(struct panthor_device *ptdev, ++ struct panthor_vm *vm, ++ struct panthor_heap *heap, ++ u32 chunk_count) ++{ ++ int ret; ++ u32 i; ++ ++ for (i = 0; i < chunk_count; i++) { ++ ret = panthor_alloc_heap_chunk(ptdev, vm, heap, true); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++panthor_heap_destroy_locked(struct panthor_heap_pool *pool, u32 handle) ++{ ++ struct panthor_heap *heap; ++ ++ heap = xa_erase(&pool->xa, handle); ++ if (!heap) ++ return -EINVAL; ++ ++ panthor_free_heap_chunks(pool->vm, heap); ++ mutex_destroy(&heap->lock); ++ kfree(heap); ++ return 0; ++} ++ ++/** ++ * panthor_heap_destroy() - Destroy a heap context ++ * @pool: Pool this context belongs to. ++ * @handle: Handle returned by panthor_heap_create(). ++ */ ++int panthor_heap_destroy(struct panthor_heap_pool *pool, u32 handle) ++{ ++ int ret; ++ ++ down_write(&pool->lock); ++ ret = panthor_heap_destroy_locked(pool, handle); ++ up_write(&pool->lock); ++ ++ return ret; ++} ++ ++/** ++ * panthor_heap_create() - Create a heap context ++ * @pool: Pool to instantiate the heap context from. ++ * @initial_chunk_count: Number of chunk allocated at initialization time. ++ * Must be at least 1. ++ * @chunk_size: The size of each chunk. Must be a power of two between 256k ++ * and 2M. ++ * @max_chunks: Maximum number of chunks that can be allocated. ++ * @target_in_flight: Maximum number of in-flight render passes. ++ * @heap_ctx_gpu_va: Pointer holding the GPU address of the allocated heap ++ * context. ++ * @first_chunk_gpu_va: Pointer holding the GPU address of the first chunk ++ * assigned to the heap context. ++ * ++ * Return: a positive handle on success, a negative error otherwise. ++ */ ++int panthor_heap_create(struct panthor_heap_pool *pool, ++ u32 initial_chunk_count, ++ u32 chunk_size, ++ u32 max_chunks, ++ u32 target_in_flight, ++ u64 *heap_ctx_gpu_va, ++ u64 *first_chunk_gpu_va) ++{ ++ struct panthor_heap *heap; ++ struct panthor_heap_chunk *first_chunk; ++ struct panthor_vm *vm; ++ int ret = 0; ++ u32 id; ++ ++ if (initial_chunk_count == 0) ++ return -EINVAL; ++ ++ if (hweight32(chunk_size) != 1 || ++ chunk_size < SZ_256K || chunk_size > SZ_2M) ++ return -EINVAL; ++ ++ down_read(&pool->lock); ++ vm = panthor_vm_get(pool->vm); ++ up_read(&pool->lock); ++ ++ /* The pool has been destroyed, we can't create a new heap. */ ++ if (!vm) ++ return -EINVAL; ++ ++ heap = kzalloc(sizeof(*heap), GFP_KERNEL); ++ if (!heap) { ++ ret = -ENOMEM; ++ goto err_put_vm; ++ } ++ ++ mutex_init(&heap->lock); ++ INIT_LIST_HEAD(&heap->chunks); ++ heap->chunk_size = chunk_size; ++ heap->max_chunks = max_chunks; ++ heap->target_in_flight = target_in_flight; ++ ++ ret = panthor_alloc_heap_chunks(pool->ptdev, vm, heap, ++ initial_chunk_count); ++ if (ret) ++ goto err_free_heap; ++ ++ first_chunk = list_first_entry(&heap->chunks, ++ struct panthor_heap_chunk, ++ node); ++ *first_chunk_gpu_va = panthor_kernel_bo_gpuva(first_chunk->bo); ++ ++ down_write(&pool->lock); ++ /* The pool has been destroyed, we can't create a new heap. */ ++ if (!pool->vm) { ++ ret = -EINVAL; ++ } else { ++ ret = xa_alloc(&pool->xa, &id, heap, XA_LIMIT(1, MAX_HEAPS_PER_POOL), GFP_KERNEL); ++ if (!ret) { ++ void *gpu_ctx = panthor_get_heap_ctx(pool, id); ++ ++ memset(gpu_ctx, 0, panthor_heap_ctx_stride(pool->ptdev)); ++ *heap_ctx_gpu_va = panthor_kernel_bo_gpuva(pool->gpu_contexts) + ++ panthor_get_heap_ctx_offset(pool, id); ++ } ++ } ++ up_write(&pool->lock); ++ ++ if (ret) ++ goto err_free_heap; ++ ++ panthor_vm_put(vm); ++ return id; ++ ++err_free_heap: ++ panthor_free_heap_chunks(pool->vm, heap); ++ mutex_destroy(&heap->lock); ++ kfree(heap); ++ ++err_put_vm: ++ panthor_vm_put(vm); ++ return ret; ++} ++ ++/** ++ * panthor_heap_return_chunk() - Return an unused heap chunk ++ * @pool: The pool this heap belongs to. ++ * @heap_gpu_va: The GPU address of the heap context. ++ * @chunk_gpu_va: The chunk VA to return. ++ * ++ * This function is used when a chunk allocated with panthor_heap_grow() ++ * couldn't be linked to the heap context through the FW interface because ++ * the group requesting the allocation was scheduled out in the meantime. ++ */ ++int panthor_heap_return_chunk(struct panthor_heap_pool *pool, ++ u64 heap_gpu_va, ++ u64 chunk_gpu_va) ++{ ++ u64 offset = heap_gpu_va - panthor_kernel_bo_gpuva(pool->gpu_contexts); ++ u32 heap_id = (u32)offset / panthor_heap_ctx_stride(pool->ptdev); ++ struct panthor_heap_chunk *chunk, *tmp, *removed = NULL; ++ struct panthor_heap *heap; ++ int ret; ++ ++ if (offset > U32_MAX || heap_id >= MAX_HEAPS_PER_POOL) ++ return -EINVAL; ++ ++ down_read(&pool->lock); ++ heap = xa_load(&pool->xa, heap_id); ++ if (!heap) { ++ ret = -EINVAL; ++ goto out_unlock; ++ } ++ ++ chunk_gpu_va &= GENMASK_ULL(63, 12); ++ ++ mutex_lock(&heap->lock); ++ list_for_each_entry_safe(chunk, tmp, &heap->chunks, node) { ++ if (panthor_kernel_bo_gpuva(chunk->bo) == chunk_gpu_va) { ++ removed = chunk; ++ list_del(&chunk->node); ++ heap->chunk_count--; ++ break; ++ } ++ } ++ mutex_unlock(&heap->lock); ++ ++ if (removed) { ++ panthor_kernel_bo_destroy(pool->vm, chunk->bo); ++ kfree(chunk); ++ ret = 0; ++ } else { ++ ret = -EINVAL; ++ } ++ ++out_unlock: ++ up_read(&pool->lock); ++ return ret; ++} ++ ++/** ++ * panthor_heap_grow() - Make a heap context grow. ++ * @pool: The pool this heap belongs to. ++ * @heap_gpu_va: The GPU address of the heap context. ++ * @renderpasses_in_flight: Number of render passes currently in-flight. ++ * @pending_frag_count: Number of fragment jobs waiting for execution/completion. ++ * @new_chunk_gpu_va: Pointer used to return the chunk VA. ++ */ ++int panthor_heap_grow(struct panthor_heap_pool *pool, ++ u64 heap_gpu_va, ++ u32 renderpasses_in_flight, ++ u32 pending_frag_count, ++ u64 *new_chunk_gpu_va) ++{ ++ u64 offset = heap_gpu_va - panthor_kernel_bo_gpuva(pool->gpu_contexts); ++ u32 heap_id = (u32)offset / panthor_heap_ctx_stride(pool->ptdev); ++ struct panthor_heap_chunk *chunk; ++ struct panthor_heap *heap; ++ int ret; ++ ++ if (offset > U32_MAX || heap_id >= MAX_HEAPS_PER_POOL) ++ return -EINVAL; ++ ++ down_read(&pool->lock); ++ heap = xa_load(&pool->xa, heap_id); ++ if (!heap) { ++ ret = -EINVAL; ++ goto out_unlock; ++ } ++ ++ /* If we reached the target in-flight render passes, or if we ++ * reached the maximum number of chunks, let the FW figure another way to ++ * find some memory (wait for render passes to finish, or call the exception ++ * handler provided by the userspace driver, if any). ++ */ ++ if (renderpasses_in_flight > heap->target_in_flight || ++ (pending_frag_count > 0 && heap->chunk_count >= heap->max_chunks)) { ++ ret = -EBUSY; ++ goto out_unlock; ++ } else if (heap->chunk_count >= heap->max_chunks) { ++ ret = -ENOMEM; ++ goto out_unlock; ++ } ++ ++ /* FIXME: panthor_alloc_heap_chunk() triggers a kernel BO creation, ++ * which goes through the blocking allocation path. Ultimately, we ++ * want a non-blocking allocation, so we can immediately report to the ++ * FW when the system is running out of memory. In that case, the FW ++ * can call a user-provided exception handler, which might try to free ++ * some tiler memory by issuing an intermediate fragment job. If the ++ * exception handler can't do anything, it will flag the queue as ++ * faulty so the job that triggered this tiler chunk allocation and all ++ * further jobs in this queue fail immediately instead of having to ++ * wait for the job timeout. ++ */ ++ ret = panthor_alloc_heap_chunk(pool->ptdev, pool->vm, heap, false); ++ if (ret) ++ goto out_unlock; ++ ++ chunk = list_first_entry(&heap->chunks, ++ struct panthor_heap_chunk, ++ node); ++ *new_chunk_gpu_va = (panthor_kernel_bo_gpuva(chunk->bo) & GENMASK_ULL(63, 12)) | ++ (heap->chunk_size >> 12); ++ ret = 0; ++ ++out_unlock: ++ up_read(&pool->lock); ++ return ret; ++} ++ ++static void panthor_heap_pool_release(struct kref *refcount) ++{ ++ struct panthor_heap_pool *pool = ++ container_of(refcount, struct panthor_heap_pool, refcount); ++ ++ xa_destroy(&pool->xa); ++ kfree(pool); ++} ++ ++/** ++ * panthor_heap_pool_put() - Release a heap pool reference ++ * @pool: Pool to release the reference on. Can be NULL. ++ */ ++void panthor_heap_pool_put(struct panthor_heap_pool *pool) ++{ ++ if (pool) ++ kref_put(&pool->refcount, panthor_heap_pool_release); ++} ++ ++/** ++ * panthor_heap_pool_get() - Get a heap pool reference ++ * @pool: Pool to get the reference on. Can be NULL. ++ * ++ * Return: @pool. ++ */ ++struct panthor_heap_pool * ++panthor_heap_pool_get(struct panthor_heap_pool *pool) ++{ ++ if (pool) ++ kref_get(&pool->refcount); ++ ++ return pool; ++} ++ ++/** ++ * panthor_heap_pool_create() - Create a heap pool ++ * @ptdev: Device. ++ * @vm: The VM this heap pool will be attached to. ++ * ++ * Heap pools might contain up to 128 heap contexts, and are per-VM. ++ * ++ * Return: A valid pointer on success, a negative error code otherwise. ++ */ ++struct panthor_heap_pool * ++panthor_heap_pool_create(struct panthor_device *ptdev, struct panthor_vm *vm) ++{ ++ size_t bosize = ALIGN(MAX_HEAPS_PER_POOL * ++ panthor_heap_ctx_stride(ptdev), ++ 4096); ++ struct panthor_heap_pool *pool; ++ int ret = 0; ++ ++ pool = kzalloc(sizeof(*pool), GFP_KERNEL); ++ if (!pool) ++ return ERR_PTR(-ENOMEM); ++ ++ /* We want a weak ref here: the heap pool belongs to the VM, so we're ++ * sure that, as long as the heap pool exists, the VM exists too. ++ */ ++ pool->vm = vm; ++ pool->ptdev = ptdev; ++ init_rwsem(&pool->lock); ++ xa_init_flags(&pool->xa, XA_FLAGS_ALLOC1); ++ kref_init(&pool->refcount); ++ ++ pool->gpu_contexts = panthor_kernel_bo_create(ptdev, vm, bosize, ++ DRM_PANTHOR_BO_NO_MMAP, ++ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC, ++ PANTHOR_VM_KERNEL_AUTO_VA); ++ if (IS_ERR(pool->gpu_contexts)) { ++ ret = PTR_ERR(pool->gpu_contexts); ++ goto err_destroy_pool; ++ } ++ ++ ret = panthor_kernel_bo_vmap(pool->gpu_contexts); ++ if (ret) ++ goto err_destroy_pool; ++ ++ return pool; ++ ++err_destroy_pool: ++ panthor_heap_pool_destroy(pool); ++ return ERR_PTR(ret); ++} ++ ++/** ++ * panthor_heap_pool_destroy() - Destroy a heap pool. ++ * @pool: Pool to destroy. ++ * ++ * This function destroys all heap contexts and their resources. Thus ++ * preventing any use of the heap context or the chunk attached to them ++ * after that point. ++ * ++ * If the GPU still has access to some heap contexts, a fault should be ++ * triggered, which should flag the command stream groups using these ++ * context as faulty. ++ * ++ * The heap pool object is only released when all references to this pool ++ * are released. ++ */ ++void panthor_heap_pool_destroy(struct panthor_heap_pool *pool) ++{ ++ struct panthor_heap *heap; ++ unsigned long i; ++ ++ if (!pool) ++ return; ++ ++ down_write(&pool->lock); ++ xa_for_each(&pool->xa, i, heap) ++ drm_WARN_ON(&pool->ptdev->base, panthor_heap_destroy_locked(pool, i)); ++ ++ if (!IS_ERR_OR_NULL(pool->gpu_contexts)) ++ panthor_kernel_bo_destroy(pool->vm, pool->gpu_contexts); ++ ++ /* Reflects the fact the pool has been destroyed. */ ++ pool->vm = NULL; ++ up_write(&pool->lock); ++ ++ panthor_heap_pool_put(pool); ++} +diff --git a/drivers/gpu/drm/panthor/panthor_heap.h b/drivers/gpu/drm/panthor/panthor_heap.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_heap.h +@@ -0,0 +1,39 @@ ++/* SPDX-License-Identifier: GPL-2.0 or MIT */ ++/* Copyright 2023 Collabora ltd. */ ++ ++#ifndef __PANTHOR_HEAP_H__ ++#define __PANTHOR_HEAP_H__ ++ ++#include ++ ++struct panthor_device; ++struct panthor_heap_pool; ++struct panthor_vm; ++ ++int panthor_heap_create(struct panthor_heap_pool *pool, ++ u32 initial_chunk_count, ++ u32 chunk_size, ++ u32 max_chunks, ++ u32 target_in_flight, ++ u64 *heap_ctx_gpu_va, ++ u64 *first_chunk_gpu_va); ++int panthor_heap_destroy(struct panthor_heap_pool *pool, u32 handle); ++ ++struct panthor_heap_pool * ++panthor_heap_pool_create(struct panthor_device *ptdev, struct panthor_vm *vm); ++void panthor_heap_pool_destroy(struct panthor_heap_pool *pool); ++ ++struct panthor_heap_pool * ++panthor_heap_pool_get(struct panthor_heap_pool *pool); ++void panthor_heap_pool_put(struct panthor_heap_pool *pool); ++ ++int panthor_heap_grow(struct panthor_heap_pool *pool, ++ u64 heap_gpu_va, ++ u32 renderpasses_in_flight, ++ u32 pending_frag_count, ++ u64 *new_chunk_gpu_va); ++int panthor_heap_return_chunk(struct panthor_heap_pool *pool, ++ u64 heap_gpu_va, ++ u64 chunk_gpu_va); ++ ++#endif +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:24 +0100 +Subject: drm/panthor: Add the scheduler logical block + +This is the piece of software interacting with the FW scheduler, and +taking care of some scheduling aspects when the FW comes short of slots +scheduling slots. Indeed, the FW only expose a few slots, and the kernel +has to give all submission contexts, a chance to execute their jobs. + +The kernel-side scheduler is timeslice-based, with a round-robin queue +per priority level. + +Job submission is handled with a 1:1 drm_sched_entity:drm_gpu_scheduler, +allowing us to delegate the dependency tracking to the core. + +All the gory details should be documented inline. + +v6: +- Add Maxime's and Heiko's acks +- Make sure the scheduler is initialized before queueing the tick work + in the MMU fault handler +- Keep header inclusion alphabetically ordered + +v5: +- Fix typos +- Call panthor_kernel_bo_destroy(group->syncobjs) unconditionally +- Don't move the group to the waiting list tail when it was already + waiting for a different syncobj +- Fix fatal_queues flagging in the tiler OOM path +- Don't warn when more than one job timesout on a group +- Add a warning message when we fail to allocate a heap chunk +- Add Steve's R-b + +v4: +- Check drmm_mutex_init() return code +- s/drm_gem_vmap_unlocked/drm_gem_vunmap_unlocked/ in + panthor_queue_put_syncwait_obj() +- Drop unneeded WARN_ON() in cs_slot_sync_queue_state_locked() +- Use atomic_xchg() instead of atomic_fetch_and(0) +- Fix typos +- Let panthor_kernel_bo_destroy() check for IS_ERR_OR_NULL() BOs +- Defer TILER_OOM event handling to a separate workqueue to prevent + deadlocks when the heap chunk allocation is blocked on mem-reclaim. + This is just a temporary solution, until we add support for + non-blocking/failable allocations +- Pass the scheduler workqueue to drm_sched instead of instantiating + a separate one (no longer needed now that heap chunk allocation + happens on a dedicated wq) +- Set WQ_MEM_RECLAIM on the scheduler workqueue, so we can handle + job timeouts when the system is under mem pressure, and hopefully + free up some memory retained by these jobs + +v3: +- Rework the FW event handling logic to avoid races +- Make sure MMU faults kill the group immediately +- Use the panthor_kernel_bo abstraction for group/queue buffers +- Make in_progress an atomic_t, so we can check it without the reset lock + held +- Don't limit the number of groups per context to the FW scheduler + capacity. Fix the limit to 128 for now. +- Add a panthor_job_vm() helper +- Account for panthor_vm changes +- Add our job fence as DMA_RESV_USAGE_WRITE to all external objects + (was previously DMA_RESV_USAGE_BOOKKEEP). I don't get why, given + we're supposed to be fully-explicit, but other drivers do that, so + there must be a good reason +- Account for drm_sched changes +- Provide a panthor_queue_put_syncwait_obj() +- Unconditionally return groups to their idle list in + panthor_sched_suspend() +- Condition of sched_queue_{,delayed_}work fixed to be only when a reset + isn't pending or in progress. +- Several typos in comments fixed. + +Co-developed-by: Steven Price +Signed-off-by: Steven Price +Signed-off-by: Boris Brezillon +Reviewed-by: Steven Price +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + drivers/gpu/drm/panthor/panthor_sched.c | 3502 ++++++++++ + drivers/gpu/drm/panthor/panthor_sched.h | 50 + + 2 files changed, 3552 insertions(+) + +diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_sched.c +@@ -0,0 +1,3502 @@ ++// SPDX-License-Identifier: GPL-2.0 or MIT ++/* Copyright 2023 Collabora ltd. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "panthor_devfreq.h" ++#include "panthor_device.h" ++#include "panthor_fw.h" ++#include "panthor_gem.h" ++#include "panthor_gpu.h" ++#include "panthor_heap.h" ++#include "panthor_mmu.h" ++#include "panthor_regs.h" ++#include "panthor_sched.h" ++ ++/** ++ * DOC: Scheduler ++ * ++ * Mali CSF hardware adopts a firmware-assisted scheduling model, where ++ * the firmware takes care of scheduling aspects, to some extent. ++ * ++ * The scheduling happens at the scheduling group level, each group ++ * contains 1 to N queues (N is FW/hardware dependent, and exposed ++ * through the firmware interface). Each queue is assigned a command ++ * stream ring buffer, which serves as a way to get jobs submitted to ++ * the GPU, among other things. ++ * ++ * The firmware can schedule a maximum of M groups (M is FW/hardware ++ * dependent, and exposed through the firmware interface). Passed ++ * this maximum number of groups, the kernel must take care of ++ * rotating the groups passed to the firmware so every group gets ++ * a chance to have his queues scheduled for execution. ++ * ++ * The current implementation only supports with kernel-mode queues. ++ * In other terms, userspace doesn't have access to the ring-buffer. ++ * Instead, userspace passes indirect command stream buffers that are ++ * called from the queue ring-buffer by the kernel using a pre-defined ++ * sequence of command stream instructions to ensure the userspace driver ++ * always gets consistent results (cache maintenance, ++ * synchronization, ...). ++ * ++ * We rely on the drm_gpu_scheduler framework to deal with job ++ * dependencies and submission. As any other driver dealing with a ++ * FW-scheduler, we use the 1:1 entity:scheduler mode, such that each ++ * entity has its own job scheduler. When a job is ready to be executed ++ * (all its dependencies are met), it is pushed to the appropriate ++ * queue ring-buffer, and the group is scheduled for execution if it ++ * wasn't already active. ++ * ++ * Kernel-side group scheduling is timeslice-based. When we have less ++ * groups than there are slots, the periodic tick is disabled and we ++ * just let the FW schedule the active groups. When there are more ++ * groups than slots, we let each group a chance to execute stuff for ++ * a given amount of time, and then re-evaluate and pick new groups ++ * to schedule. The group selection algorithm is based on ++ * priority+round-robin. ++ * ++ * Even though user-mode queues is out of the scope right now, the ++ * current design takes them into account by avoiding any guess on the ++ * group/queue state that would be based on information we wouldn't have ++ * if userspace was in charge of the ring-buffer. That's also one of the ++ * reason we don't do 'cooperative' scheduling (encoding FW group slot ++ * reservation as dma_fence that would be returned from the ++ * drm_gpu_scheduler::prepare_job() hook, and treating group rotation as ++ * a queue of waiters, ordered by job submission order). This approach ++ * would work for kernel-mode queues, but would make user-mode queues a ++ * lot more complicated to retrofit. ++ */ ++ ++#define JOB_TIMEOUT_MS 5000 ++ ++#define MIN_CS_PER_CSG 8 ++ ++#define MIN_CSGS 3 ++#define MAX_CSG_PRIO 0xf ++ ++struct panthor_group; ++ ++/** ++ * struct panthor_csg_slot - Command stream group slot ++ * ++ * This represents a FW slot for a scheduling group. ++ */ ++struct panthor_csg_slot { ++ /** @group: Scheduling group bound to this slot. */ ++ struct panthor_group *group; ++ ++ /** @priority: Group priority. */ ++ u8 priority; ++ ++ /** ++ * @idle: True if the group bound to this slot is idle. ++ * ++ * A group is idle when it has nothing waiting for execution on ++ * all its queues, or when queues are blocked waiting for something ++ * to happen (synchronization object). ++ */ ++ bool idle; ++}; ++ ++/** ++ * enum panthor_csg_priority - Group priority ++ */ ++enum panthor_csg_priority { ++ /** @PANTHOR_CSG_PRIORITY_LOW: Low priority group. */ ++ PANTHOR_CSG_PRIORITY_LOW = 0, ++ ++ /** @PANTHOR_CSG_PRIORITY_MEDIUM: Medium priority group. */ ++ PANTHOR_CSG_PRIORITY_MEDIUM, ++ ++ /** @PANTHOR_CSG_PRIORITY_HIGH: High priority group. */ ++ PANTHOR_CSG_PRIORITY_HIGH, ++ ++ /** ++ * @PANTHOR_CSG_PRIORITY_RT: Real-time priority group. ++ * ++ * Real-time priority allows one to preempt scheduling of other ++ * non-real-time groups. When such a group becomes executable, ++ * it will evict the group with the lowest non-rt priority if ++ * there's no free group slot available. ++ * ++ * Currently not exposed to userspace. ++ */ ++ PANTHOR_CSG_PRIORITY_RT, ++ ++ /** @PANTHOR_CSG_PRIORITY_COUNT: Number of priority levels. */ ++ PANTHOR_CSG_PRIORITY_COUNT, ++}; ++ ++/** ++ * struct panthor_scheduler - Object used to manage the scheduler ++ */ ++struct panthor_scheduler { ++ /** @ptdev: Device. */ ++ struct panthor_device *ptdev; ++ ++ /** ++ * @wq: Workqueue used by our internal scheduler logic and ++ * drm_gpu_scheduler. ++ * ++ * Used for the scheduler tick, group update or other kind of FW ++ * event processing that can't be handled in the threaded interrupt ++ * path. Also passed to the drm_gpu_scheduler instances embedded ++ * in panthor_queue. ++ */ ++ struct workqueue_struct *wq; ++ ++ /** ++ * @heap_alloc_wq: Workqueue used to schedule tiler_oom works. ++ * ++ * We have a queue dedicated to heap chunk allocation works to avoid ++ * blocking the rest of the scheduler if the allocation tries to ++ * reclaim memory. ++ */ ++ struct workqueue_struct *heap_alloc_wq; ++ ++ /** @tick_work: Work executed on a scheduling tick. */ ++ struct delayed_work tick_work; ++ ++ /** ++ * @sync_upd_work: Work used to process synchronization object updates. ++ * ++ * We use this work to unblock queues/groups that were waiting on a ++ * synchronization object. ++ */ ++ struct work_struct sync_upd_work; ++ ++ /** ++ * @fw_events_work: Work used to process FW events outside the interrupt path. ++ * ++ * Even if the interrupt is threaded, we need any event processing ++ * that require taking the panthor_scheduler::lock to be processed ++ * outside the interrupt path so we don't block the tick logic when ++ * it calls panthor_fw_{csg,wait}_wait_acks(). Since most of the ++ * event processing requires taking this lock, we just delegate all ++ * FW event processing to the scheduler workqueue. ++ */ ++ struct work_struct fw_events_work; ++ ++ /** ++ * @fw_events: Bitmask encoding pending FW events. ++ */ ++ atomic_t fw_events; ++ ++ /** ++ * @resched_target: When the next tick should occur. ++ * ++ * Expressed in jiffies. ++ */ ++ u64 resched_target; ++ ++ /** ++ * @last_tick: When the last tick occurred. ++ * ++ * Expressed in jiffies. ++ */ ++ u64 last_tick; ++ ++ /** @tick_period: Tick period in jiffies. */ ++ u64 tick_period; ++ ++ /** ++ * @lock: Lock protecting access to all the scheduler fields. ++ * ++ * Should be taken in the tick work, the irq handler, and anywhere the @groups ++ * fields are touched. ++ */ ++ struct mutex lock; ++ ++ /** @groups: Various lists used to classify groups. */ ++ struct { ++ /** ++ * @runnable: Runnable group lists. ++ * ++ * When a group has queues that want to execute something, ++ * its panthor_group::run_node should be inserted here. ++ * ++ * One list per-priority. ++ */ ++ struct list_head runnable[PANTHOR_CSG_PRIORITY_COUNT]; ++ ++ /** ++ * @idle: Idle group lists. ++ * ++ * When all queues of a group are idle (either because they ++ * have nothing to execute, or because they are blocked), the ++ * panthor_group::run_node field should be inserted here. ++ * ++ * One list per-priority. ++ */ ++ struct list_head idle[PANTHOR_CSG_PRIORITY_COUNT]; ++ ++ /** ++ * @waiting: List of groups whose queues are blocked on a ++ * synchronization object. ++ * ++ * Insert panthor_group::wait_node here when a group is waiting ++ * for synchronization objects to be signaled. ++ * ++ * This list is evaluated in the @sync_upd_work work. ++ */ ++ struct list_head waiting; ++ } groups; ++ ++ /** ++ * @csg_slots: FW command stream group slots. ++ */ ++ struct panthor_csg_slot csg_slots[MAX_CSGS]; ++ ++ /** @csg_slot_count: Number of command stream group slots exposed by the FW. */ ++ u32 csg_slot_count; ++ ++ /** @cs_slot_count: Number of command stream slot per group slot exposed by the FW. */ ++ u32 cs_slot_count; ++ ++ /** @as_slot_count: Number of address space slots supported by the MMU. */ ++ u32 as_slot_count; ++ ++ /** @used_csg_slot_count: Number of command stream group slot currently used. */ ++ u32 used_csg_slot_count; ++ ++ /** @sb_slot_count: Number of scoreboard slots. */ ++ u32 sb_slot_count; ++ ++ /** ++ * @might_have_idle_groups: True if an active group might have become idle. ++ * ++ * This will force a tick, so other runnable groups can be scheduled if one ++ * or more active groups became idle. ++ */ ++ bool might_have_idle_groups; ++ ++ /** @pm: Power management related fields. */ ++ struct { ++ /** @has_ref: True if the scheduler owns a runtime PM reference. */ ++ bool has_ref; ++ } pm; ++ ++ /** @reset: Reset related fields. */ ++ struct { ++ /** @lock: Lock protecting the other reset fields. */ ++ struct mutex lock; ++ ++ /** ++ * @in_progress: True if a reset is in progress. ++ * ++ * Set to true in panthor_sched_pre_reset() and back to false in ++ * panthor_sched_post_reset(). ++ */ ++ atomic_t in_progress; ++ ++ /** ++ * @stopped_groups: List containing all groups that were stopped ++ * before a reset. ++ * ++ * Insert panthor_group::run_node in the pre_reset path. ++ */ ++ struct list_head stopped_groups; ++ } reset; ++}; ++ ++/** ++ * struct panthor_syncobj_32b - 32-bit FW synchronization object ++ */ ++struct panthor_syncobj_32b { ++ /** @seqno: Sequence number. */ ++ u32 seqno; ++ ++ /** ++ * @status: Status. ++ * ++ * Not zero on failure. ++ */ ++ u32 status; ++}; ++ ++/** ++ * struct panthor_syncobj_64b - 64-bit FW synchronization object ++ */ ++struct panthor_syncobj_64b { ++ /** @seqno: Sequence number. */ ++ u64 seqno; ++ ++ /** ++ * @status: Status. ++ * ++ * Not zero on failure. ++ */ ++ u32 status; ++ ++ /** @pad: MBZ. */ ++ u32 pad; ++}; ++ ++/** ++ * struct panthor_queue - Execution queue ++ */ ++struct panthor_queue { ++ /** @scheduler: DRM scheduler used for this queue. */ ++ struct drm_gpu_scheduler scheduler; ++ ++ /** @entity: DRM scheduling entity used for this queue. */ ++ struct drm_sched_entity entity; ++ ++ /** ++ * @remaining_time: Time remaining before the job timeout expires. ++ * ++ * The job timeout is suspended when the queue is not scheduled by the ++ * FW. Every time we suspend the timer, we need to save the remaining ++ * time so we can restore it later on. ++ */ ++ unsigned long remaining_time; ++ ++ /** @timeout_suspended: True if the job timeout was suspended. */ ++ bool timeout_suspended; ++ ++ /** ++ * @doorbell_id: Doorbell assigned to this queue. ++ * ++ * Right now, all groups share the same doorbell, and the doorbell ID ++ * is assigned to group_slot + 1 when the group is assigned a slot. But ++ * we might decide to provide fine grained doorbell assignment at some ++ * point, so don't have to wake up all queues in a group every time one ++ * of them is updated. ++ */ ++ u8 doorbell_id; ++ ++ /** ++ * @priority: Priority of the queue inside the group. ++ * ++ * Must be less than 16 (Only 4 bits available). ++ */ ++ u8 priority; ++#define CSF_MAX_QUEUE_PRIO GENMASK(3, 0) ++ ++ /** @ringbuf: Command stream ring-buffer. */ ++ struct panthor_kernel_bo *ringbuf; ++ ++ /** @iface: Firmware interface. */ ++ struct { ++ /** @mem: FW memory allocated for this interface. */ ++ struct panthor_kernel_bo *mem; ++ ++ /** @input: Input interface. */ ++ struct panthor_fw_ringbuf_input_iface *input; ++ ++ /** @output: Output interface. */ ++ const struct panthor_fw_ringbuf_output_iface *output; ++ ++ /** @input_fw_va: FW virtual address of the input interface buffer. */ ++ u32 input_fw_va; ++ ++ /** @output_fw_va: FW virtual address of the output interface buffer. */ ++ u32 output_fw_va; ++ } iface; ++ ++ /** ++ * @syncwait: Stores information about the synchronization object this ++ * queue is waiting on. ++ */ ++ struct { ++ /** @gpu_va: GPU address of the synchronization object. */ ++ u64 gpu_va; ++ ++ /** @ref: Reference value to compare against. */ ++ u64 ref; ++ ++ /** @gt: True if this is a greater-than test. */ ++ bool gt; ++ ++ /** @sync64: True if this is a 64-bit sync object. */ ++ bool sync64; ++ ++ /** @bo: Buffer object holding the synchronization object. */ ++ struct drm_gem_object *obj; ++ ++ /** @offset: Offset of the synchronization object inside @bo. */ ++ u64 offset; ++ ++ /** ++ * @kmap: Kernel mapping of the buffer object holding the ++ * synchronization object. ++ */ ++ void *kmap; ++ } syncwait; ++ ++ /** @fence_ctx: Fence context fields. */ ++ struct { ++ /** @lock: Used to protect access to all fences allocated by this context. */ ++ spinlock_t lock; ++ ++ /** ++ * @id: Fence context ID. ++ * ++ * Allocated with dma_fence_context_alloc(). ++ */ ++ u64 id; ++ ++ /** @seqno: Sequence number of the last initialized fence. */ ++ atomic64_t seqno; ++ ++ /** ++ * @in_flight_jobs: List containing all in-flight jobs. ++ * ++ * Used to keep track and signal panthor_job::done_fence when the ++ * synchronization object attached to the queue is signaled. ++ */ ++ struct list_head in_flight_jobs; ++ } fence_ctx; ++}; ++ ++/** ++ * enum panthor_group_state - Scheduling group state. ++ */ ++enum panthor_group_state { ++ /** @PANTHOR_CS_GROUP_CREATED: Group was created, but not scheduled yet. */ ++ PANTHOR_CS_GROUP_CREATED, ++ ++ /** @PANTHOR_CS_GROUP_ACTIVE: Group is currently scheduled. */ ++ PANTHOR_CS_GROUP_ACTIVE, ++ ++ /** ++ * @PANTHOR_CS_GROUP_SUSPENDED: Group was scheduled at least once, but is ++ * inactive/suspended right now. ++ */ ++ PANTHOR_CS_GROUP_SUSPENDED, ++ ++ /** ++ * @PANTHOR_CS_GROUP_TERMINATED: Group was terminated. ++ * ++ * Can no longer be scheduled. The only allowed action is a destruction. ++ */ ++ PANTHOR_CS_GROUP_TERMINATED, ++}; ++ ++/** ++ * struct panthor_group - Scheduling group object ++ */ ++struct panthor_group { ++ /** @refcount: Reference count */ ++ struct kref refcount; ++ ++ /** @ptdev: Device. */ ++ struct panthor_device *ptdev; ++ ++ /** @vm: VM bound to the group. */ ++ struct panthor_vm *vm; ++ ++ /** @compute_core_mask: Mask of shader cores that can be used for compute jobs. */ ++ u64 compute_core_mask; ++ ++ /** @fragment_core_mask: Mask of shader cores that can be used for fragment jobs. */ ++ u64 fragment_core_mask; ++ ++ /** @tiler_core_mask: Mask of tiler cores that can be used for tiler jobs. */ ++ u64 tiler_core_mask; ++ ++ /** @max_compute_cores: Maximum number of shader cores used for compute jobs. */ ++ u8 max_compute_cores; ++ ++ /** @max_compute_cores: Maximum number of shader cores used for fragment jobs. */ ++ u8 max_fragment_cores; ++ ++ /** @max_tiler_cores: Maximum number of tiler cores used for tiler jobs. */ ++ u8 max_tiler_cores; ++ ++ /** @priority: Group priority (check panthor_csg_priority). */ ++ u8 priority; ++ ++ /** @blocked_queues: Bitmask reflecting the blocked queues. */ ++ u32 blocked_queues; ++ ++ /** @idle_queues: Bitmask reflecting the idle queues. */ ++ u32 idle_queues; ++ ++ /** @fatal_lock: Lock used to protect access to fatal fields. */ ++ spinlock_t fatal_lock; ++ ++ /** @fatal_queues: Bitmask reflecting the queues that hit a fatal exception. */ ++ u32 fatal_queues; ++ ++ /** @tiler_oom: Mask of queues that have a tiler OOM event to process. */ ++ atomic_t tiler_oom; ++ ++ /** @queue_count: Number of queues in this group. */ ++ u32 queue_count; ++ ++ /** @queues: Queues owned by this group. */ ++ struct panthor_queue *queues[MAX_CS_PER_CSG]; ++ ++ /** ++ * @csg_id: ID of the FW group slot. ++ * ++ * -1 when the group is not scheduled/active. ++ */ ++ int csg_id; ++ ++ /** ++ * @destroyed: True when the group has been destroyed. ++ * ++ * If a group is destroyed it becomes useless: no further jobs can be submitted ++ * to its queues. We simply wait for all references to be dropped so we can ++ * release the group object. ++ */ ++ bool destroyed; ++ ++ /** ++ * @timedout: True when a timeout occurred on any of the queues owned by ++ * this group. ++ * ++ * Timeouts can be reported by drm_sched or by the FW. In any case, any ++ * timeout situation is unrecoverable, and the group becomes useless. ++ * We simply wait for all references to be dropped so we can release the ++ * group object. ++ */ ++ bool timedout; ++ ++ /** ++ * @syncobjs: Pool of per-queue synchronization objects. ++ * ++ * One sync object per queue. The position of the sync object is ++ * determined by the queue index. ++ */ ++ struct panthor_kernel_bo *syncobjs; ++ ++ /** @state: Group state. */ ++ enum panthor_group_state state; ++ ++ /** ++ * @suspend_buf: Suspend buffer. ++ * ++ * Stores the state of the group and its queues when a group is suspended. ++ * Used at resume time to restore the group in its previous state. ++ * ++ * The size of the suspend buffer is exposed through the FW interface. ++ */ ++ struct panthor_kernel_bo *suspend_buf; ++ ++ /** ++ * @protm_suspend_buf: Protection mode suspend buffer. ++ * ++ * Stores the state of the group and its queues when a group that's in ++ * protection mode is suspended. ++ * ++ * Used at resume time to restore the group in its previous state. ++ * ++ * The size of the protection mode suspend buffer is exposed through the ++ * FW interface. ++ */ ++ struct panthor_kernel_bo *protm_suspend_buf; ++ ++ /** @sync_upd_work: Work used to check/signal job fences. */ ++ struct work_struct sync_upd_work; ++ ++ /** @tiler_oom_work: Work used to process tiler OOM events happening on this group. */ ++ struct work_struct tiler_oom_work; ++ ++ /** @term_work: Work used to finish the group termination procedure. */ ++ struct work_struct term_work; ++ ++ /** ++ * @release_work: Work used to release group resources. ++ * ++ * We need to postpone the group release to avoid a deadlock when ++ * the last ref is released in the tick work. ++ */ ++ struct work_struct release_work; ++ ++ /** ++ * @run_node: Node used to insert the group in the ++ * panthor_group::groups::{runnable,idle} and ++ * panthor_group::reset.stopped_groups lists. ++ */ ++ struct list_head run_node; ++ ++ /** ++ * @wait_node: Node used to insert the group in the ++ * panthor_group::groups::waiting list. ++ */ ++ struct list_head wait_node; ++}; ++ ++/** ++ * group_queue_work() - Queue a group work ++ * @group: Group to queue the work for. ++ * @wname: Work name. ++ * ++ * Grabs a ref and queue a work item to the scheduler workqueue. If ++ * the work was already queued, we release the reference we grabbed. ++ * ++ * Work callbacks must release the reference we grabbed here. ++ */ ++#define group_queue_work(group, wname) \ ++ do { \ ++ group_get(group); \ ++ if (!queue_work((group)->ptdev->scheduler->wq, &(group)->wname ## _work)) \ ++ group_put(group); \ ++ } while (0) ++ ++/** ++ * sched_queue_work() - Queue a scheduler work. ++ * @sched: Scheduler object. ++ * @wname: Work name. ++ * ++ * Conditionally queues a scheduler work if no reset is pending/in-progress. ++ */ ++#define sched_queue_work(sched, wname) \ ++ do { \ ++ if (!atomic_read(&(sched)->reset.in_progress) && \ ++ !panthor_device_reset_is_pending((sched)->ptdev)) \ ++ queue_work((sched)->wq, &(sched)->wname ## _work); \ ++ } while (0) ++ ++/** ++ * sched_queue_delayed_work() - Queue a scheduler delayed work. ++ * @sched: Scheduler object. ++ * @wname: Work name. ++ * @delay: Work delay in jiffies. ++ * ++ * Conditionally queues a scheduler delayed work if no reset is ++ * pending/in-progress. ++ */ ++#define sched_queue_delayed_work(sched, wname, delay) \ ++ do { \ ++ if (!atomic_read(&sched->reset.in_progress) && \ ++ !panthor_device_reset_is_pending((sched)->ptdev)) \ ++ mod_delayed_work((sched)->wq, &(sched)->wname ## _work, delay); \ ++ } while (0) ++ ++/* ++ * We currently set the maximum of groups per file to an arbitrary low value. ++ * But this can be updated if we need more. ++ */ ++#define MAX_GROUPS_PER_POOL 128 ++ ++/** ++ * struct panthor_group_pool - Group pool ++ * ++ * Each file get assigned a group pool. ++ */ ++struct panthor_group_pool { ++ /** @xa: Xarray used to manage group handles. */ ++ struct xarray xa; ++}; ++ ++/** ++ * struct panthor_job - Used to manage GPU job ++ */ ++struct panthor_job { ++ /** @base: Inherit from drm_sched_job. */ ++ struct drm_sched_job base; ++ ++ /** @refcount: Reference count. */ ++ struct kref refcount; ++ ++ /** @group: Group of the queue this job will be pushed to. */ ++ struct panthor_group *group; ++ ++ /** @queue_idx: Index of the queue inside @group. */ ++ u32 queue_idx; ++ ++ /** @call_info: Information about the userspace command stream call. */ ++ struct { ++ /** @start: GPU address of the userspace command stream. */ ++ u64 start; ++ ++ /** @size: Size of the userspace command stream. */ ++ u32 size; ++ ++ /** ++ * @latest_flush: Flush ID at the time the userspace command ++ * stream was built. ++ * ++ * Needed for the flush reduction mechanism. ++ */ ++ u32 latest_flush; ++ } call_info; ++ ++ /** @ringbuf: Position of this job is in the ring buffer. */ ++ struct { ++ /** @start: Start offset. */ ++ u64 start; ++ ++ /** @end: End offset. */ ++ u64 end; ++ } ringbuf; ++ ++ /** ++ * @node: Used to insert the job in the panthor_queue::fence_ctx::in_flight_jobs ++ * list. ++ */ ++ struct list_head node; ++ ++ /** @done_fence: Fence signaled when the job is finished or cancelled. */ ++ struct dma_fence *done_fence; ++}; ++ ++static void ++panthor_queue_put_syncwait_obj(struct panthor_queue *queue) ++{ ++ if (queue->syncwait.kmap) { ++ struct iosys_map map = IOSYS_MAP_INIT_VADDR(queue->syncwait.kmap); ++ ++ drm_gem_vunmap_unlocked(queue->syncwait.obj, &map); ++ queue->syncwait.kmap = NULL; ++ } ++ ++ drm_gem_object_put(queue->syncwait.obj); ++ queue->syncwait.obj = NULL; ++} ++ ++static void * ++panthor_queue_get_syncwait_obj(struct panthor_group *group, struct panthor_queue *queue) ++{ ++ struct panthor_device *ptdev = group->ptdev; ++ struct panthor_gem_object *bo; ++ struct iosys_map map; ++ int ret; ++ ++ if (queue->syncwait.kmap) ++ return queue->syncwait.kmap + queue->syncwait.offset; ++ ++ bo = panthor_vm_get_bo_for_va(group->vm, ++ queue->syncwait.gpu_va, ++ &queue->syncwait.offset); ++ if (drm_WARN_ON(&ptdev->base, IS_ERR_OR_NULL(bo))) ++ goto err_put_syncwait_obj; ++ ++ queue->syncwait.obj = &bo->base.base; ++ ret = drm_gem_vmap_unlocked(queue->syncwait.obj, &map); ++ if (drm_WARN_ON(&ptdev->base, ret)) ++ goto err_put_syncwait_obj; ++ ++ queue->syncwait.kmap = map.vaddr; ++ if (drm_WARN_ON(&ptdev->base, !queue->syncwait.kmap)) ++ goto err_put_syncwait_obj; ++ ++ return queue->syncwait.kmap + queue->syncwait.offset; ++ ++err_put_syncwait_obj: ++ panthor_queue_put_syncwait_obj(queue); ++ return NULL; ++} ++ ++static void group_free_queue(struct panthor_group *group, struct panthor_queue *queue) ++{ ++ if (IS_ERR_OR_NULL(queue)) ++ return; ++ ++ if (queue->entity.fence_context) ++ drm_sched_entity_destroy(&queue->entity); ++ ++ if (queue->scheduler.ops) ++ drm_sched_fini(&queue->scheduler); ++ ++ panthor_queue_put_syncwait_obj(queue); ++ ++ panthor_kernel_bo_destroy(group->vm, queue->ringbuf); ++ panthor_kernel_bo_destroy(panthor_fw_vm(group->ptdev), queue->iface.mem); ++ ++ kfree(queue); ++} ++ ++static void group_release_work(struct work_struct *work) ++{ ++ struct panthor_group *group = container_of(work, ++ struct panthor_group, ++ release_work); ++ struct panthor_device *ptdev = group->ptdev; ++ u32 i; ++ ++ for (i = 0; i < group->queue_count; i++) ++ group_free_queue(group, group->queues[i]); ++ ++ panthor_kernel_bo_destroy(panthor_fw_vm(ptdev), group->suspend_buf); ++ panthor_kernel_bo_destroy(panthor_fw_vm(ptdev), group->protm_suspend_buf); ++ panthor_kernel_bo_destroy(group->vm, group->syncobjs); ++ ++ panthor_vm_put(group->vm); ++ kfree(group); ++} ++ ++static void group_release(struct kref *kref) ++{ ++ struct panthor_group *group = container_of(kref, ++ struct panthor_group, ++ refcount); ++ struct panthor_device *ptdev = group->ptdev; ++ ++ drm_WARN_ON(&ptdev->base, group->csg_id >= 0); ++ drm_WARN_ON(&ptdev->base, !list_empty(&group->run_node)); ++ drm_WARN_ON(&ptdev->base, !list_empty(&group->wait_node)); ++ ++ queue_work(panthor_cleanup_wq, &group->release_work); ++} ++ ++static void group_put(struct panthor_group *group) ++{ ++ if (group) ++ kref_put(&group->refcount, group_release); ++} ++ ++static struct panthor_group * ++group_get(struct panthor_group *group) ++{ ++ if (group) ++ kref_get(&group->refcount); ++ ++ return group; ++} ++ ++/** ++ * group_bind_locked() - Bind a group to a group slot ++ * @group: Group. ++ * @csg_id: Slot. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++static int ++group_bind_locked(struct panthor_group *group, u32 csg_id) ++{ ++ struct panthor_device *ptdev = group->ptdev; ++ struct panthor_csg_slot *csg_slot; ++ int ret; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ if (drm_WARN_ON(&ptdev->base, group->csg_id != -1 || csg_id >= MAX_CSGS || ++ ptdev->scheduler->csg_slots[csg_id].group)) ++ return -EINVAL; ++ ++ ret = panthor_vm_active(group->vm); ++ if (ret) ++ return ret; ++ ++ csg_slot = &ptdev->scheduler->csg_slots[csg_id]; ++ group_get(group); ++ group->csg_id = csg_id; ++ ++ /* Dummy doorbell allocation: doorbell is assigned to the group and ++ * all queues use the same doorbell. ++ * ++ * TODO: Implement LRU-based doorbell assignment, so the most often ++ * updated queues get their own doorbell, thus avoiding useless checks ++ * on queues belonging to the same group that are rarely updated. ++ */ ++ for (u32 i = 0; i < group->queue_count; i++) ++ group->queues[i]->doorbell_id = csg_id + 1; ++ ++ csg_slot->group = group; ++ ++ return 0; ++} ++ ++/** ++ * group_unbind_locked() - Unbind a group from a slot. ++ * @group: Group to unbind. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++static int ++group_unbind_locked(struct panthor_group *group) ++{ ++ struct panthor_device *ptdev = group->ptdev; ++ struct panthor_csg_slot *slot; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ if (drm_WARN_ON(&ptdev->base, group->csg_id < 0 || group->csg_id >= MAX_CSGS)) ++ return -EINVAL; ++ ++ if (drm_WARN_ON(&ptdev->base, group->state == PANTHOR_CS_GROUP_ACTIVE)) ++ return -EINVAL; ++ ++ slot = &ptdev->scheduler->csg_slots[group->csg_id]; ++ panthor_vm_idle(group->vm); ++ group->csg_id = -1; ++ ++ /* Tiler OOM events will be re-issued next time the group is scheduled. */ ++ atomic_set(&group->tiler_oom, 0); ++ cancel_work(&group->tiler_oom_work); ++ ++ for (u32 i = 0; i < group->queue_count; i++) ++ group->queues[i]->doorbell_id = -1; ++ ++ slot->group = NULL; ++ ++ group_put(group); ++ return 0; ++} ++ ++/** ++ * cs_slot_prog_locked() - Program a queue slot ++ * @ptdev: Device. ++ * @csg_id: Group slot ID. ++ * @cs_id: Queue slot ID. ++ * ++ * Program a queue slot with the queue information so things can start being ++ * executed on this queue. ++ * ++ * The group slot must have a group bound to it already (group_bind_locked()). ++ */ ++static void ++cs_slot_prog_locked(struct panthor_device *ptdev, u32 csg_id, u32 cs_id) ++{ ++ struct panthor_queue *queue = ptdev->scheduler->csg_slots[csg_id].group->queues[cs_id]; ++ struct panthor_fw_cs_iface *cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ queue->iface.input->extract = queue->iface.output->extract; ++ drm_WARN_ON(&ptdev->base, queue->iface.input->insert < queue->iface.input->extract); ++ ++ cs_iface->input->ringbuf_base = panthor_kernel_bo_gpuva(queue->ringbuf); ++ cs_iface->input->ringbuf_size = panthor_kernel_bo_size(queue->ringbuf); ++ cs_iface->input->ringbuf_input = queue->iface.input_fw_va; ++ cs_iface->input->ringbuf_output = queue->iface.output_fw_va; ++ cs_iface->input->config = CS_CONFIG_PRIORITY(queue->priority) | ++ CS_CONFIG_DOORBELL(queue->doorbell_id); ++ cs_iface->input->ack_irq_mask = ~0; ++ panthor_fw_update_reqs(cs_iface, req, ++ CS_IDLE_SYNC_WAIT | ++ CS_IDLE_EMPTY | ++ CS_STATE_START | ++ CS_EXTRACT_EVENT, ++ CS_IDLE_SYNC_WAIT | ++ CS_IDLE_EMPTY | ++ CS_STATE_MASK | ++ CS_EXTRACT_EVENT); ++ if (queue->iface.input->insert != queue->iface.input->extract && queue->timeout_suspended) { ++ drm_sched_resume_timeout(&queue->scheduler, queue->remaining_time); ++ queue->timeout_suspended = false; ++ } ++} ++ ++/** ++ * @cs_slot_reset_locked() - Reset a queue slot ++ * @ptdev: Device. ++ * @csg_id: Group slot. ++ * @cs_id: Queue slot. ++ * ++ * Change the queue slot state to STOP and suspend the queue timeout if ++ * the queue is not blocked. ++ * ++ * The group slot must have a group bound to it (group_bind_locked()). ++ */ ++static int ++cs_slot_reset_locked(struct panthor_device *ptdev, u32 csg_id, u32 cs_id) ++{ ++ struct panthor_fw_cs_iface *cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); ++ struct panthor_group *group = ptdev->scheduler->csg_slots[csg_id].group; ++ struct panthor_queue *queue = group->queues[cs_id]; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ panthor_fw_update_reqs(cs_iface, req, ++ CS_STATE_STOP, ++ CS_STATE_MASK); ++ ++ /* If the queue is blocked, we want to keep the timeout running, so ++ * we can detect unbounded waits and kill the group when that happens. ++ */ ++ if (!(group->blocked_queues & BIT(cs_id)) && !queue->timeout_suspended) { ++ queue->remaining_time = drm_sched_suspend_timeout(&queue->scheduler); ++ queue->timeout_suspended = true; ++ WARN_ON(queue->remaining_time > msecs_to_jiffies(JOB_TIMEOUT_MS)); ++ } ++ ++ return 0; ++} ++ ++/** ++ * csg_slot_sync_priority_locked() - Synchronize the group slot priority ++ * @ptdev: Device. ++ * @csg_id: Group slot ID. ++ * ++ * Group slot priority update happens asynchronously. When we receive a ++ * %CSG_ENDPOINT_CONFIG, we know the update is effective, and can ++ * reflect it to our panthor_csg_slot object. ++ */ ++static void ++csg_slot_sync_priority_locked(struct panthor_device *ptdev, u32 csg_id) ++{ ++ struct panthor_csg_slot *csg_slot = &ptdev->scheduler->csg_slots[csg_id]; ++ struct panthor_fw_csg_iface *csg_iface; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); ++ csg_slot->priority = (csg_iface->input->endpoint_req & CSG_EP_REQ_PRIORITY_MASK) >> 28; ++} ++ ++/** ++ * cs_slot_sync_queue_state_locked() - Synchronize the queue slot priority ++ * @ptdev: Device. ++ * @csg_id: Group slot. ++ * @cs_id: Queue slot. ++ * ++ * Queue state is updated on group suspend or STATUS_UPDATE event. ++ */ ++static void ++cs_slot_sync_queue_state_locked(struct panthor_device *ptdev, u32 csg_id, u32 cs_id) ++{ ++ struct panthor_group *group = ptdev->scheduler->csg_slots[csg_id].group; ++ struct panthor_queue *queue = group->queues[cs_id]; ++ struct panthor_fw_cs_iface *cs_iface = ++ panthor_fw_get_cs_iface(group->ptdev, csg_id, cs_id); ++ ++ u32 status_wait_cond; ++ ++ switch (cs_iface->output->status_blocked_reason) { ++ case CS_STATUS_BLOCKED_REASON_UNBLOCKED: ++ if (queue->iface.input->insert == queue->iface.output->extract && ++ cs_iface->output->status_scoreboards == 0) ++ group->idle_queues |= BIT(cs_id); ++ break; ++ ++ case CS_STATUS_BLOCKED_REASON_SYNC_WAIT: ++ if (list_empty(&group->wait_node)) { ++ list_move_tail(&group->wait_node, ++ &group->ptdev->scheduler->groups.waiting); ++ } ++ group->blocked_queues |= BIT(cs_id); ++ queue->syncwait.gpu_va = cs_iface->output->status_wait_sync_ptr; ++ queue->syncwait.ref = cs_iface->output->status_wait_sync_value; ++ status_wait_cond = cs_iface->output->status_wait & CS_STATUS_WAIT_SYNC_COND_MASK; ++ queue->syncwait.gt = status_wait_cond == CS_STATUS_WAIT_SYNC_COND_GT; ++ if (cs_iface->output->status_wait & CS_STATUS_WAIT_SYNC_64B) { ++ u64 sync_val_hi = cs_iface->output->status_wait_sync_value_hi; ++ ++ queue->syncwait.sync64 = true; ++ queue->syncwait.ref |= sync_val_hi << 32; ++ } else { ++ queue->syncwait.sync64 = false; ++ } ++ break; ++ ++ default: ++ /* Other reasons are not blocking. Consider the queue as runnable ++ * in those cases. ++ */ ++ break; ++ } ++} ++ ++static void ++csg_slot_sync_queues_state_locked(struct panthor_device *ptdev, u32 csg_id) ++{ ++ struct panthor_csg_slot *csg_slot = &ptdev->scheduler->csg_slots[csg_id]; ++ struct panthor_group *group = csg_slot->group; ++ u32 i; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ group->idle_queues = 0; ++ group->blocked_queues = 0; ++ ++ for (i = 0; i < group->queue_count; i++) { ++ if (group->queues[i]) ++ cs_slot_sync_queue_state_locked(ptdev, csg_id, i); ++ } ++} ++ ++static void ++csg_slot_sync_state_locked(struct panthor_device *ptdev, u32 csg_id) ++{ ++ struct panthor_csg_slot *csg_slot = &ptdev->scheduler->csg_slots[csg_id]; ++ struct panthor_fw_csg_iface *csg_iface; ++ struct panthor_group *group; ++ enum panthor_group_state new_state, old_state; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); ++ group = csg_slot->group; ++ ++ if (!group) ++ return; ++ ++ old_state = group->state; ++ switch (csg_iface->output->ack & CSG_STATE_MASK) { ++ case CSG_STATE_START: ++ case CSG_STATE_RESUME: ++ new_state = PANTHOR_CS_GROUP_ACTIVE; ++ break; ++ case CSG_STATE_TERMINATE: ++ new_state = PANTHOR_CS_GROUP_TERMINATED; ++ break; ++ case CSG_STATE_SUSPEND: ++ new_state = PANTHOR_CS_GROUP_SUSPENDED; ++ break; ++ } ++ ++ if (old_state == new_state) ++ return; ++ ++ if (new_state == PANTHOR_CS_GROUP_SUSPENDED) ++ csg_slot_sync_queues_state_locked(ptdev, csg_id); ++ ++ if (old_state == PANTHOR_CS_GROUP_ACTIVE) { ++ u32 i; ++ ++ /* Reset the queue slots so we start from a clean ++ * state when starting/resuming a new group on this ++ * CSG slot. No wait needed here, and no ringbell ++ * either, since the CS slot will only be re-used ++ * on the next CSG start operation. ++ */ ++ for (i = 0; i < group->queue_count; i++) { ++ if (group->queues[i]) ++ cs_slot_reset_locked(ptdev, csg_id, i); ++ } ++ } ++ ++ group->state = new_state; ++} ++ ++static int ++csg_slot_prog_locked(struct panthor_device *ptdev, u32 csg_id, u32 priority) ++{ ++ struct panthor_fw_csg_iface *csg_iface; ++ struct panthor_csg_slot *csg_slot; ++ struct panthor_group *group; ++ u32 queue_mask = 0, i; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ if (priority > MAX_CSG_PRIO) ++ return -EINVAL; ++ ++ if (drm_WARN_ON(&ptdev->base, csg_id >= MAX_CSGS)) ++ return -EINVAL; ++ ++ csg_slot = &ptdev->scheduler->csg_slots[csg_id]; ++ group = csg_slot->group; ++ if (!group || group->state == PANTHOR_CS_GROUP_ACTIVE) ++ return 0; ++ ++ csg_iface = panthor_fw_get_csg_iface(group->ptdev, csg_id); ++ ++ for (i = 0; i < group->queue_count; i++) { ++ if (group->queues[i]) { ++ cs_slot_prog_locked(ptdev, csg_id, i); ++ queue_mask |= BIT(i); ++ } ++ } ++ ++ csg_iface->input->allow_compute = group->compute_core_mask; ++ csg_iface->input->allow_fragment = group->fragment_core_mask; ++ csg_iface->input->allow_other = group->tiler_core_mask; ++ csg_iface->input->endpoint_req = CSG_EP_REQ_COMPUTE(group->max_compute_cores) | ++ CSG_EP_REQ_FRAGMENT(group->max_fragment_cores) | ++ CSG_EP_REQ_TILER(group->max_tiler_cores) | ++ CSG_EP_REQ_PRIORITY(priority); ++ csg_iface->input->config = panthor_vm_as(group->vm); ++ ++ if (group->suspend_buf) ++ csg_iface->input->suspend_buf = panthor_kernel_bo_gpuva(group->suspend_buf); ++ else ++ csg_iface->input->suspend_buf = 0; ++ ++ if (group->protm_suspend_buf) { ++ csg_iface->input->protm_suspend_buf = ++ panthor_kernel_bo_gpuva(group->protm_suspend_buf); ++ } else { ++ csg_iface->input->protm_suspend_buf = 0; ++ } ++ ++ csg_iface->input->ack_irq_mask = ~0; ++ panthor_fw_toggle_reqs(csg_iface, doorbell_req, doorbell_ack, queue_mask); ++ return 0; ++} ++ ++static void ++cs_slot_process_fatal_event_locked(struct panthor_device *ptdev, ++ u32 csg_id, u32 cs_id) ++{ ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; ++ struct panthor_group *group = csg_slot->group; ++ struct panthor_fw_cs_iface *cs_iface; ++ u32 fatal; ++ u64 info; ++ ++ lockdep_assert_held(&sched->lock); ++ ++ cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); ++ fatal = cs_iface->output->fatal; ++ info = cs_iface->output->fatal_info; ++ ++ if (group) ++ group->fatal_queues |= BIT(cs_id); ++ ++ sched_queue_delayed_work(sched, tick, 0); ++ drm_warn(&ptdev->base, ++ "CSG slot %d CS slot: %d\n" ++ "CS_FATAL.EXCEPTION_TYPE: 0x%x (%s)\n" ++ "CS_FATAL.EXCEPTION_DATA: 0x%x\n" ++ "CS_FATAL_INFO.EXCEPTION_DATA: 0x%llx\n", ++ csg_id, cs_id, ++ (unsigned int)CS_EXCEPTION_TYPE(fatal), ++ panthor_exception_name(ptdev, CS_EXCEPTION_TYPE(fatal)), ++ (unsigned int)CS_EXCEPTION_DATA(fatal), ++ info); ++} ++ ++static void ++cs_slot_process_fault_event_locked(struct panthor_device *ptdev, ++ u32 csg_id, u32 cs_id) ++{ ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; ++ struct panthor_group *group = csg_slot->group; ++ struct panthor_queue *queue = group && cs_id < group->queue_count ? ++ group->queues[cs_id] : NULL; ++ struct panthor_fw_cs_iface *cs_iface; ++ u32 fault; ++ u64 info; ++ ++ lockdep_assert_held(&sched->lock); ++ ++ cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); ++ fault = cs_iface->output->fault; ++ info = cs_iface->output->fault_info; ++ ++ if (queue && CS_EXCEPTION_TYPE(fault) == DRM_PANTHOR_EXCEPTION_CS_INHERIT_FAULT) { ++ u64 cs_extract = queue->iface.output->extract; ++ struct panthor_job *job; ++ ++ spin_lock(&queue->fence_ctx.lock); ++ list_for_each_entry(job, &queue->fence_ctx.in_flight_jobs, node) { ++ if (cs_extract >= job->ringbuf.end) ++ continue; ++ ++ if (cs_extract < job->ringbuf.start) ++ break; ++ ++ dma_fence_set_error(job->done_fence, -EINVAL); ++ } ++ spin_unlock(&queue->fence_ctx.lock); ++ } ++ ++ drm_warn(&ptdev->base, ++ "CSG slot %d CS slot: %d\n" ++ "CS_FAULT.EXCEPTION_TYPE: 0x%x (%s)\n" ++ "CS_FAULT.EXCEPTION_DATA: 0x%x\n" ++ "CS_FAULT_INFO.EXCEPTION_DATA: 0x%llx\n", ++ csg_id, cs_id, ++ (unsigned int)CS_EXCEPTION_TYPE(fault), ++ panthor_exception_name(ptdev, CS_EXCEPTION_TYPE(fault)), ++ (unsigned int)CS_EXCEPTION_DATA(fault), ++ info); ++} ++ ++static int group_process_tiler_oom(struct panthor_group *group, u32 cs_id) ++{ ++ struct panthor_device *ptdev = group->ptdev; ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ u32 renderpasses_in_flight, pending_frag_count; ++ struct panthor_heap_pool *heaps = NULL; ++ u64 heap_address, new_chunk_va = 0; ++ u32 vt_start, vt_end, frag_end; ++ int ret, csg_id; ++ ++ mutex_lock(&sched->lock); ++ csg_id = group->csg_id; ++ if (csg_id >= 0) { ++ struct panthor_fw_cs_iface *cs_iface; ++ ++ cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); ++ heaps = panthor_vm_get_heap_pool(group->vm, false); ++ heap_address = cs_iface->output->heap_address; ++ vt_start = cs_iface->output->heap_vt_start; ++ vt_end = cs_iface->output->heap_vt_end; ++ frag_end = cs_iface->output->heap_frag_end; ++ renderpasses_in_flight = vt_start - frag_end; ++ pending_frag_count = vt_end - frag_end; ++ } ++ mutex_unlock(&sched->lock); ++ ++ /* The group got scheduled out, we stop here. We will get a new tiler OOM event ++ * when it's scheduled again. ++ */ ++ if (unlikely(csg_id < 0)) ++ return 0; ++ ++ if (!heaps || frag_end > vt_end || vt_end >= vt_start) { ++ ret = -EINVAL; ++ } else { ++ /* We do the allocation without holding the scheduler lock to avoid ++ * blocking the scheduling. ++ */ ++ ret = panthor_heap_grow(heaps, heap_address, ++ renderpasses_in_flight, ++ pending_frag_count, &new_chunk_va); ++ } ++ ++ if (ret && ret != -EBUSY) { ++ drm_warn(&ptdev->base, "Failed to extend the tiler heap\n"); ++ group->fatal_queues |= BIT(cs_id); ++ sched_queue_delayed_work(sched, tick, 0); ++ goto out_put_heap_pool; ++ } ++ ++ mutex_lock(&sched->lock); ++ csg_id = group->csg_id; ++ if (csg_id >= 0) { ++ struct panthor_fw_csg_iface *csg_iface; ++ struct panthor_fw_cs_iface *cs_iface; ++ ++ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); ++ cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); ++ ++ cs_iface->input->heap_start = new_chunk_va; ++ cs_iface->input->heap_end = new_chunk_va; ++ panthor_fw_update_reqs(cs_iface, req, cs_iface->output->ack, CS_TILER_OOM); ++ panthor_fw_toggle_reqs(csg_iface, doorbell_req, doorbell_ack, BIT(cs_id)); ++ panthor_fw_ring_csg_doorbells(ptdev, BIT(csg_id)); ++ } ++ mutex_unlock(&sched->lock); ++ ++ /* We allocated a chunck, but couldn't link it to the heap ++ * context because the group was scheduled out while we were ++ * allocating memory. We need to return this chunk to the heap. ++ */ ++ if (unlikely(csg_id < 0 && new_chunk_va)) ++ panthor_heap_return_chunk(heaps, heap_address, new_chunk_va); ++ ++ ret = 0; ++ ++out_put_heap_pool: ++ panthor_heap_pool_put(heaps); ++ return ret; ++} ++ ++static void group_tiler_oom_work(struct work_struct *work) ++{ ++ struct panthor_group *group = ++ container_of(work, struct panthor_group, tiler_oom_work); ++ u32 tiler_oom = atomic_xchg(&group->tiler_oom, 0); ++ ++ while (tiler_oom) { ++ u32 cs_id = ffs(tiler_oom) - 1; ++ ++ group_process_tiler_oom(group, cs_id); ++ tiler_oom &= ~BIT(cs_id); ++ } ++ ++ group_put(group); ++} ++ ++static void ++cs_slot_process_tiler_oom_event_locked(struct panthor_device *ptdev, ++ u32 csg_id, u32 cs_id) ++{ ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; ++ struct panthor_group *group = csg_slot->group; ++ ++ lockdep_assert_held(&sched->lock); ++ ++ if (drm_WARN_ON(&ptdev->base, !group)) ++ return; ++ ++ atomic_or(BIT(cs_id), &group->tiler_oom); ++ ++ /* We don't use group_queue_work() here because we want to queue the ++ * work item to the heap_alloc_wq. ++ */ ++ group_get(group); ++ if (!queue_work(sched->heap_alloc_wq, &group->tiler_oom_work)) ++ group_put(group); ++} ++ ++static bool cs_slot_process_irq_locked(struct panthor_device *ptdev, ++ u32 csg_id, u32 cs_id) ++{ ++ struct panthor_fw_cs_iface *cs_iface; ++ u32 req, ack, events; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ cs_iface = panthor_fw_get_cs_iface(ptdev, csg_id, cs_id); ++ req = cs_iface->input->req; ++ ack = cs_iface->output->ack; ++ events = (req ^ ack) & CS_EVT_MASK; ++ ++ if (events & CS_FATAL) ++ cs_slot_process_fatal_event_locked(ptdev, csg_id, cs_id); ++ ++ if (events & CS_FAULT) ++ cs_slot_process_fault_event_locked(ptdev, csg_id, cs_id); ++ ++ if (events & CS_TILER_OOM) ++ cs_slot_process_tiler_oom_event_locked(ptdev, csg_id, cs_id); ++ ++ /* We don't acknowledge the TILER_OOM event since its handling is ++ * deferred to a separate work. ++ */ ++ panthor_fw_update_reqs(cs_iface, req, ack, CS_FATAL | CS_FAULT); ++ ++ return (events & (CS_FAULT | CS_TILER_OOM)) != 0; ++} ++ ++static void csg_slot_sync_idle_state_locked(struct panthor_device *ptdev, u32 csg_id) ++{ ++ struct panthor_csg_slot *csg_slot = &ptdev->scheduler->csg_slots[csg_id]; ++ struct panthor_fw_csg_iface *csg_iface; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); ++ csg_slot->idle = csg_iface->output->status_state & CSG_STATUS_STATE_IS_IDLE; ++} ++ ++static void csg_slot_process_idle_event_locked(struct panthor_device *ptdev, u32 csg_id) ++{ ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ ++ lockdep_assert_held(&sched->lock); ++ ++ sched->might_have_idle_groups = true; ++ ++ /* Schedule a tick so we can evict idle groups and schedule non-idle ++ * ones. This will also update runtime PM and devfreq busy/idle states, ++ * so the device can lower its frequency or get suspended. ++ */ ++ sched_queue_delayed_work(sched, tick, 0); ++} ++ ++static void csg_slot_sync_update_locked(struct panthor_device *ptdev, ++ u32 csg_id) ++{ ++ struct panthor_csg_slot *csg_slot = &ptdev->scheduler->csg_slots[csg_id]; ++ struct panthor_group *group = csg_slot->group; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ if (group) ++ group_queue_work(group, sync_upd); ++ ++ sched_queue_work(ptdev->scheduler, sync_upd); ++} ++ ++static void ++csg_slot_process_progress_timer_event_locked(struct panthor_device *ptdev, u32 csg_id) ++{ ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; ++ struct panthor_group *group = csg_slot->group; ++ ++ lockdep_assert_held(&sched->lock); ++ ++ drm_warn(&ptdev->base, "CSG slot %d progress timeout\n", csg_id); ++ ++ group = csg_slot->group; ++ if (!drm_WARN_ON(&ptdev->base, !group)) ++ group->timedout = true; ++ ++ sched_queue_delayed_work(sched, tick, 0); ++} ++ ++static void sched_process_csg_irq_locked(struct panthor_device *ptdev, u32 csg_id) ++{ ++ u32 req, ack, cs_irq_req, cs_irq_ack, cs_irqs, csg_events; ++ struct panthor_fw_csg_iface *csg_iface; ++ u32 ring_cs_db_mask = 0; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ if (drm_WARN_ON(&ptdev->base, csg_id >= ptdev->scheduler->csg_slot_count)) ++ return; ++ ++ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); ++ req = READ_ONCE(csg_iface->input->req); ++ ack = READ_ONCE(csg_iface->output->ack); ++ cs_irq_req = READ_ONCE(csg_iface->output->cs_irq_req); ++ cs_irq_ack = READ_ONCE(csg_iface->input->cs_irq_ack); ++ csg_events = (req ^ ack) & CSG_EVT_MASK; ++ ++ /* There may not be any pending CSG/CS interrupts to process */ ++ if (req == ack && cs_irq_req == cs_irq_ack) ++ return; ++ ++ /* Immediately set IRQ_ACK bits to be same as the IRQ_REQ bits before ++ * examining the CS_ACK & CS_REQ bits. This would ensure that Host ++ * doesn't miss an interrupt for the CS in the race scenario where ++ * whilst Host is servicing an interrupt for the CS, firmware sends ++ * another interrupt for that CS. ++ */ ++ csg_iface->input->cs_irq_ack = cs_irq_req; ++ ++ panthor_fw_update_reqs(csg_iface, req, ack, ++ CSG_SYNC_UPDATE | ++ CSG_IDLE | ++ CSG_PROGRESS_TIMER_EVENT); ++ ++ if (csg_events & CSG_IDLE) ++ csg_slot_process_idle_event_locked(ptdev, csg_id); ++ ++ if (csg_events & CSG_PROGRESS_TIMER_EVENT) ++ csg_slot_process_progress_timer_event_locked(ptdev, csg_id); ++ ++ cs_irqs = cs_irq_req ^ cs_irq_ack; ++ while (cs_irqs) { ++ u32 cs_id = ffs(cs_irqs) - 1; ++ ++ if (cs_slot_process_irq_locked(ptdev, csg_id, cs_id)) ++ ring_cs_db_mask |= BIT(cs_id); ++ ++ cs_irqs &= ~BIT(cs_id); ++ } ++ ++ if (csg_events & CSG_SYNC_UPDATE) ++ csg_slot_sync_update_locked(ptdev, csg_id); ++ ++ if (ring_cs_db_mask) ++ panthor_fw_toggle_reqs(csg_iface, doorbell_req, doorbell_ack, ring_cs_db_mask); ++ ++ panthor_fw_ring_csg_doorbells(ptdev, BIT(csg_id)); ++} ++ ++static void sched_process_idle_event_locked(struct panthor_device *ptdev) ++{ ++ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ /* Acknowledge the idle event and schedule a tick. */ ++ panthor_fw_update_reqs(glb_iface, req, glb_iface->output->ack, GLB_IDLE); ++ sched_queue_delayed_work(ptdev->scheduler, tick, 0); ++} ++ ++/** ++ * panthor_sched_process_global_irq() - Process the scheduling part of a global IRQ ++ * @ptdev: Device. ++ */ ++static void sched_process_global_irq_locked(struct panthor_device *ptdev) ++{ ++ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); ++ u32 req, ack, evts; ++ ++ lockdep_assert_held(&ptdev->scheduler->lock); ++ ++ req = READ_ONCE(glb_iface->input->req); ++ ack = READ_ONCE(glb_iface->output->ack); ++ evts = (req ^ ack) & GLB_EVT_MASK; ++ ++ if (evts & GLB_IDLE) ++ sched_process_idle_event_locked(ptdev); ++} ++ ++static void process_fw_events_work(struct work_struct *work) ++{ ++ struct panthor_scheduler *sched = container_of(work, struct panthor_scheduler, ++ fw_events_work); ++ u32 events = atomic_xchg(&sched->fw_events, 0); ++ struct panthor_device *ptdev = sched->ptdev; ++ ++ mutex_lock(&sched->lock); ++ ++ if (events & JOB_INT_GLOBAL_IF) { ++ sched_process_global_irq_locked(ptdev); ++ events &= ~JOB_INT_GLOBAL_IF; ++ } ++ ++ while (events) { ++ u32 csg_id = ffs(events) - 1; ++ ++ sched_process_csg_irq_locked(ptdev, csg_id); ++ events &= ~BIT(csg_id); ++ } ++ ++ mutex_unlock(&sched->lock); ++} ++ ++/** ++ * panthor_sched_report_fw_events() - Report FW events to the scheduler. ++ */ ++void panthor_sched_report_fw_events(struct panthor_device *ptdev, u32 events) ++{ ++ if (!ptdev->scheduler) ++ return; ++ ++ atomic_or(events, &ptdev->scheduler->fw_events); ++ sched_queue_work(ptdev->scheduler, fw_events); ++} ++ ++static const char *fence_get_driver_name(struct dma_fence *fence) ++{ ++ return "panthor"; ++} ++ ++static const char *queue_fence_get_timeline_name(struct dma_fence *fence) ++{ ++ return "queue-fence"; ++} ++ ++static const struct dma_fence_ops panthor_queue_fence_ops = { ++ .get_driver_name = fence_get_driver_name, ++ .get_timeline_name = queue_fence_get_timeline_name, ++}; ++ ++/** ++ */ ++struct panthor_csg_slots_upd_ctx { ++ u32 update_mask; ++ u32 timedout_mask; ++ struct { ++ u32 value; ++ u32 mask; ++ } requests[MAX_CSGS]; ++}; ++ ++static void csgs_upd_ctx_init(struct panthor_csg_slots_upd_ctx *ctx) ++{ ++ memset(ctx, 0, sizeof(*ctx)); ++} ++ ++static void csgs_upd_ctx_queue_reqs(struct panthor_device *ptdev, ++ struct panthor_csg_slots_upd_ctx *ctx, ++ u32 csg_id, u32 value, u32 mask) ++{ ++ if (drm_WARN_ON(&ptdev->base, !mask) || ++ drm_WARN_ON(&ptdev->base, csg_id >= ptdev->scheduler->csg_slot_count)) ++ return; ++ ++ ctx->requests[csg_id].value = (ctx->requests[csg_id].value & ~mask) | (value & mask); ++ ctx->requests[csg_id].mask |= mask; ++ ctx->update_mask |= BIT(csg_id); ++} ++ ++static int csgs_upd_ctx_apply_locked(struct panthor_device *ptdev, ++ struct panthor_csg_slots_upd_ctx *ctx) ++{ ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ u32 update_slots = ctx->update_mask; ++ ++ lockdep_assert_held(&sched->lock); ++ ++ if (!ctx->update_mask) ++ return 0; ++ ++ while (update_slots) { ++ struct panthor_fw_csg_iface *csg_iface; ++ u32 csg_id = ffs(update_slots) - 1; ++ ++ update_slots &= ~BIT(csg_id); ++ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); ++ panthor_fw_update_reqs(csg_iface, req, ++ ctx->requests[csg_id].value, ++ ctx->requests[csg_id].mask); ++ } ++ ++ panthor_fw_ring_csg_doorbells(ptdev, ctx->update_mask); ++ ++ update_slots = ctx->update_mask; ++ while (update_slots) { ++ struct panthor_fw_csg_iface *csg_iface; ++ u32 csg_id = ffs(update_slots) - 1; ++ u32 req_mask = ctx->requests[csg_id].mask, acked; ++ int ret; ++ ++ update_slots &= ~BIT(csg_id); ++ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); ++ ++ ret = panthor_fw_csg_wait_acks(ptdev, csg_id, req_mask, &acked, 100); ++ ++ if (acked & CSG_ENDPOINT_CONFIG) ++ csg_slot_sync_priority_locked(ptdev, csg_id); ++ ++ if (acked & CSG_STATE_MASK) ++ csg_slot_sync_state_locked(ptdev, csg_id); ++ ++ if (acked & CSG_STATUS_UPDATE) { ++ csg_slot_sync_queues_state_locked(ptdev, csg_id); ++ csg_slot_sync_idle_state_locked(ptdev, csg_id); ++ } ++ ++ if (ret && acked != req_mask && ++ ((csg_iface->input->req ^ csg_iface->output->ack) & req_mask) != 0) { ++ drm_err(&ptdev->base, "CSG %d update request timedout", csg_id); ++ ctx->timedout_mask |= BIT(csg_id); ++ } ++ } ++ ++ if (ctx->timedout_mask) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ ++struct panthor_sched_tick_ctx { ++ struct list_head old_groups[PANTHOR_CSG_PRIORITY_COUNT]; ++ struct list_head groups[PANTHOR_CSG_PRIORITY_COUNT]; ++ u32 idle_group_count; ++ u32 group_count; ++ enum panthor_csg_priority min_priority; ++ struct panthor_vm *vms[MAX_CS_PER_CSG]; ++ u32 as_count; ++ bool immediate_tick; ++ u32 csg_upd_failed_mask; ++}; ++ ++static bool ++tick_ctx_is_full(const struct panthor_scheduler *sched, ++ const struct panthor_sched_tick_ctx *ctx) ++{ ++ return ctx->group_count == sched->csg_slot_count; ++} ++ ++static bool ++group_is_idle(struct panthor_group *group) ++{ ++ struct panthor_device *ptdev = group->ptdev; ++ u32 inactive_queues; ++ ++ if (group->csg_id >= 0) ++ return ptdev->scheduler->csg_slots[group->csg_id].idle; ++ ++ inactive_queues = group->idle_queues | group->blocked_queues; ++ return hweight32(inactive_queues) == group->queue_count; ++} ++ ++static bool ++group_can_run(struct panthor_group *group) ++{ ++ return group->state != PANTHOR_CS_GROUP_TERMINATED && ++ !group->destroyed && group->fatal_queues == 0 && ++ !group->timedout; ++} ++ ++static void ++tick_ctx_pick_groups_from_list(const struct panthor_scheduler *sched, ++ struct panthor_sched_tick_ctx *ctx, ++ struct list_head *queue, ++ bool skip_idle_groups, ++ bool owned_by_tick_ctx) ++{ ++ struct panthor_group *group, *tmp; ++ ++ if (tick_ctx_is_full(sched, ctx)) ++ return; ++ ++ list_for_each_entry_safe(group, tmp, queue, run_node) { ++ u32 i; ++ ++ if (!group_can_run(group)) ++ continue; ++ ++ if (skip_idle_groups && group_is_idle(group)) ++ continue; ++ ++ for (i = 0; i < ctx->as_count; i++) { ++ if (ctx->vms[i] == group->vm) ++ break; ++ } ++ ++ if (i == ctx->as_count && ctx->as_count == sched->as_slot_count) ++ continue; ++ ++ if (!owned_by_tick_ctx) ++ group_get(group); ++ ++ list_move_tail(&group->run_node, &ctx->groups[group->priority]); ++ ctx->group_count++; ++ if (group_is_idle(group)) ++ ctx->idle_group_count++; ++ ++ if (i == ctx->as_count) ++ ctx->vms[ctx->as_count++] = group->vm; ++ ++ if (ctx->min_priority > group->priority) ++ ctx->min_priority = group->priority; ++ ++ if (tick_ctx_is_full(sched, ctx)) ++ return; ++ } ++} ++ ++static void ++tick_ctx_insert_old_group(struct panthor_scheduler *sched, ++ struct panthor_sched_tick_ctx *ctx, ++ struct panthor_group *group, ++ bool full_tick) ++{ ++ struct panthor_csg_slot *csg_slot = &sched->csg_slots[group->csg_id]; ++ struct panthor_group *other_group; ++ ++ if (!full_tick) { ++ list_add_tail(&group->run_node, &ctx->old_groups[group->priority]); ++ return; ++ } ++ ++ /* Rotate to make sure groups with lower CSG slot ++ * priorities have a chance to get a higher CSG slot ++ * priority next time they get picked. This priority ++ * has an impact on resource request ordering, so it's ++ * important to make sure we don't let one group starve ++ * all other groups with the same group priority. ++ */ ++ list_for_each_entry(other_group, ++ &ctx->old_groups[csg_slot->group->priority], ++ run_node) { ++ struct panthor_csg_slot *other_csg_slot = &sched->csg_slots[other_group->csg_id]; ++ ++ if (other_csg_slot->priority > csg_slot->priority) { ++ list_add_tail(&csg_slot->group->run_node, &other_group->run_node); ++ return; ++ } ++ } ++ ++ list_add_tail(&group->run_node, &ctx->old_groups[group->priority]); ++} ++ ++static void ++tick_ctx_init(struct panthor_scheduler *sched, ++ struct panthor_sched_tick_ctx *ctx, ++ bool full_tick) ++{ ++ struct panthor_device *ptdev = sched->ptdev; ++ struct panthor_csg_slots_upd_ctx upd_ctx; ++ int ret; ++ u32 i; ++ ++ memset(ctx, 0, sizeof(*ctx)); ++ csgs_upd_ctx_init(&upd_ctx); ++ ++ ctx->min_priority = PANTHOR_CSG_PRIORITY_COUNT; ++ for (i = 0; i < ARRAY_SIZE(ctx->groups); i++) { ++ INIT_LIST_HEAD(&ctx->groups[i]); ++ INIT_LIST_HEAD(&ctx->old_groups[i]); ++ } ++ ++ for (i = 0; i < sched->csg_slot_count; i++) { ++ struct panthor_csg_slot *csg_slot = &sched->csg_slots[i]; ++ struct panthor_group *group = csg_slot->group; ++ struct panthor_fw_csg_iface *csg_iface; ++ ++ if (!group) ++ continue; ++ ++ csg_iface = panthor_fw_get_csg_iface(ptdev, i); ++ group_get(group); ++ ++ /* If there was unhandled faults on the VM, force processing of ++ * CSG IRQs, so we can flag the faulty queue. ++ */ ++ if (panthor_vm_has_unhandled_faults(group->vm)) { ++ sched_process_csg_irq_locked(ptdev, i); ++ ++ /* No fatal fault reported, flag all queues as faulty. */ ++ if (!group->fatal_queues) ++ group->fatal_queues |= GENMASK(group->queue_count - 1, 0); ++ } ++ ++ tick_ctx_insert_old_group(sched, ctx, group, full_tick); ++ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, i, ++ csg_iface->output->ack ^ CSG_STATUS_UPDATE, ++ CSG_STATUS_UPDATE); ++ } ++ ++ ret = csgs_upd_ctx_apply_locked(ptdev, &upd_ctx); ++ if (ret) { ++ panthor_device_schedule_reset(ptdev); ++ ctx->csg_upd_failed_mask |= upd_ctx.timedout_mask; ++ } ++} ++ ++#define NUM_INSTRS_PER_SLOT 16 ++ ++static void ++group_term_post_processing(struct panthor_group *group) ++{ ++ struct panthor_job *job, *tmp; ++ LIST_HEAD(faulty_jobs); ++ bool cookie; ++ u32 i = 0; ++ ++ if (drm_WARN_ON(&group->ptdev->base, group_can_run(group))) ++ return; ++ ++ cookie = dma_fence_begin_signalling(); ++ for (i = 0; i < group->queue_count; i++) { ++ struct panthor_queue *queue = group->queues[i]; ++ struct panthor_syncobj_64b *syncobj; ++ int err; ++ ++ if (group->fatal_queues & BIT(i)) ++ err = -EINVAL; ++ else if (group->timedout) ++ err = -ETIMEDOUT; ++ else ++ err = -ECANCELED; ++ ++ if (!queue) ++ continue; ++ ++ spin_lock(&queue->fence_ctx.lock); ++ list_for_each_entry_safe(job, tmp, &queue->fence_ctx.in_flight_jobs, node) { ++ list_move_tail(&job->node, &faulty_jobs); ++ dma_fence_set_error(job->done_fence, err); ++ dma_fence_signal_locked(job->done_fence); ++ } ++ spin_unlock(&queue->fence_ctx.lock); ++ ++ /* Manually update the syncobj seqno to unblock waiters. */ ++ syncobj = group->syncobjs->kmap + (i * sizeof(*syncobj)); ++ syncobj->status = ~0; ++ syncobj->seqno = atomic64_read(&queue->fence_ctx.seqno); ++ sched_queue_work(group->ptdev->scheduler, sync_upd); ++ } ++ dma_fence_end_signalling(cookie); ++ ++ list_for_each_entry_safe(job, tmp, &faulty_jobs, node) { ++ list_del_init(&job->node); ++ panthor_job_put(&job->base); ++ } ++} ++ ++static void group_term_work(struct work_struct *work) ++{ ++ struct panthor_group *group = ++ container_of(work, struct panthor_group, term_work); ++ ++ group_term_post_processing(group); ++ group_put(group); ++} ++ ++static void ++tick_ctx_cleanup(struct panthor_scheduler *sched, ++ struct panthor_sched_tick_ctx *ctx) ++{ ++ struct panthor_group *group, *tmp; ++ u32 i; ++ ++ for (i = 0; i < ARRAY_SIZE(ctx->old_groups); i++) { ++ list_for_each_entry_safe(group, tmp, &ctx->old_groups[i], run_node) { ++ /* If everything went fine, we should only have groups ++ * to be terminated in the old_groups lists. ++ */ ++ drm_WARN_ON(&group->ptdev->base, !ctx->csg_upd_failed_mask && ++ group_can_run(group)); ++ ++ if (!group_can_run(group)) { ++ list_del_init(&group->run_node); ++ list_del_init(&group->wait_node); ++ group_queue_work(group, term); ++ } else if (group->csg_id >= 0) { ++ list_del_init(&group->run_node); ++ } else { ++ list_move(&group->run_node, ++ group_is_idle(group) ? ++ &sched->groups.idle[group->priority] : ++ &sched->groups.runnable[group->priority]); ++ } ++ group_put(group); ++ } ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(ctx->groups); i++) { ++ /* If everything went fine, the groups to schedule lists should ++ * be empty. ++ */ ++ drm_WARN_ON(&group->ptdev->base, ++ !ctx->csg_upd_failed_mask && !list_empty(&ctx->groups[i])); ++ ++ list_for_each_entry_safe(group, tmp, &ctx->groups[i], run_node) { ++ if (group->csg_id >= 0) { ++ list_del_init(&group->run_node); ++ } else { ++ list_move(&group->run_node, ++ group_is_idle(group) ? ++ &sched->groups.idle[group->priority] : ++ &sched->groups.runnable[group->priority]); ++ } ++ group_put(group); ++ } ++ } ++} ++ ++static void ++tick_ctx_apply(struct panthor_scheduler *sched, struct panthor_sched_tick_ctx *ctx) ++{ ++ struct panthor_group *group, *tmp; ++ struct panthor_device *ptdev = sched->ptdev; ++ struct panthor_csg_slot *csg_slot; ++ int prio, new_csg_prio = MAX_CSG_PRIO, i; ++ u32 csg_mod_mask = 0, free_csg_slots = 0; ++ struct panthor_csg_slots_upd_ctx upd_ctx; ++ int ret; ++ ++ csgs_upd_ctx_init(&upd_ctx); ++ ++ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { ++ /* Suspend or terminate evicted groups. */ ++ list_for_each_entry(group, &ctx->old_groups[prio], run_node) { ++ bool term = !group_can_run(group); ++ int csg_id = group->csg_id; ++ ++ if (drm_WARN_ON(&ptdev->base, csg_id < 0)) ++ continue; ++ ++ csg_slot = &sched->csg_slots[csg_id]; ++ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, ++ term ? CSG_STATE_TERMINATE : CSG_STATE_SUSPEND, ++ CSG_STATE_MASK); ++ } ++ ++ /* Update priorities on already running groups. */ ++ list_for_each_entry(group, &ctx->groups[prio], run_node) { ++ struct panthor_fw_csg_iface *csg_iface; ++ int csg_id = group->csg_id; ++ ++ if (csg_id < 0) { ++ new_csg_prio--; ++ continue; ++ } ++ ++ csg_slot = &sched->csg_slots[csg_id]; ++ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); ++ if (csg_slot->priority == new_csg_prio) { ++ new_csg_prio--; ++ continue; ++ } ++ ++ panthor_fw_update_reqs(csg_iface, endpoint_req, ++ CSG_EP_REQ_PRIORITY(new_csg_prio), ++ CSG_EP_REQ_PRIORITY_MASK); ++ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, ++ csg_iface->output->ack ^ CSG_ENDPOINT_CONFIG, ++ CSG_ENDPOINT_CONFIG); ++ new_csg_prio--; ++ } ++ } ++ ++ ret = csgs_upd_ctx_apply_locked(ptdev, &upd_ctx); ++ if (ret) { ++ panthor_device_schedule_reset(ptdev); ++ ctx->csg_upd_failed_mask |= upd_ctx.timedout_mask; ++ return; ++ } ++ ++ /* Unbind evicted groups. */ ++ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { ++ list_for_each_entry(group, &ctx->old_groups[prio], run_node) { ++ /* This group is gone. Process interrupts to clear ++ * any pending interrupts before we start the new ++ * group. ++ */ ++ if (group->csg_id >= 0) ++ sched_process_csg_irq_locked(ptdev, group->csg_id); ++ ++ group_unbind_locked(group); ++ } ++ } ++ ++ for (i = 0; i < sched->csg_slot_count; i++) { ++ if (!sched->csg_slots[i].group) ++ free_csg_slots |= BIT(i); ++ } ++ ++ csgs_upd_ctx_init(&upd_ctx); ++ new_csg_prio = MAX_CSG_PRIO; ++ ++ /* Start new groups. */ ++ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { ++ list_for_each_entry(group, &ctx->groups[prio], run_node) { ++ int csg_id = group->csg_id; ++ struct panthor_fw_csg_iface *csg_iface; ++ ++ if (csg_id >= 0) { ++ new_csg_prio--; ++ continue; ++ } ++ ++ csg_id = ffs(free_csg_slots) - 1; ++ if (drm_WARN_ON(&ptdev->base, csg_id < 0)) ++ break; ++ ++ csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id); ++ csg_slot = &sched->csg_slots[csg_id]; ++ csg_mod_mask |= BIT(csg_id); ++ group_bind_locked(group, csg_id); ++ csg_slot_prog_locked(ptdev, csg_id, new_csg_prio--); ++ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, ++ group->state == PANTHOR_CS_GROUP_SUSPENDED ? ++ CSG_STATE_RESUME : CSG_STATE_START, ++ CSG_STATE_MASK); ++ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, ++ csg_iface->output->ack ^ CSG_ENDPOINT_CONFIG, ++ CSG_ENDPOINT_CONFIG); ++ free_csg_slots &= ~BIT(csg_id); ++ } ++ } ++ ++ ret = csgs_upd_ctx_apply_locked(ptdev, &upd_ctx); ++ if (ret) { ++ panthor_device_schedule_reset(ptdev); ++ ctx->csg_upd_failed_mask |= upd_ctx.timedout_mask; ++ return; ++ } ++ ++ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { ++ list_for_each_entry_safe(group, tmp, &ctx->groups[prio], run_node) { ++ list_del_init(&group->run_node); ++ ++ /* If the group has been destroyed while we were ++ * scheduling, ask for an immediate tick to ++ * re-evaluate as soon as possible and get rid of ++ * this dangling group. ++ */ ++ if (group->destroyed) ++ ctx->immediate_tick = true; ++ group_put(group); ++ } ++ ++ /* Return evicted groups to the idle or run queues. Groups ++ * that can no longer be run (because they've been destroyed ++ * or experienced an unrecoverable error) will be scheduled ++ * for destruction in tick_ctx_cleanup(). ++ */ ++ list_for_each_entry_safe(group, tmp, &ctx->old_groups[prio], run_node) { ++ if (!group_can_run(group)) ++ continue; ++ ++ if (group_is_idle(group)) ++ list_move_tail(&group->run_node, &sched->groups.idle[prio]); ++ else ++ list_move_tail(&group->run_node, &sched->groups.runnable[prio]); ++ group_put(group); ++ } ++ } ++ ++ sched->used_csg_slot_count = ctx->group_count; ++ sched->might_have_idle_groups = ctx->idle_group_count > 0; ++} ++ ++static u64 ++tick_ctx_update_resched_target(struct panthor_scheduler *sched, ++ const struct panthor_sched_tick_ctx *ctx) ++{ ++ /* We had space left, no need to reschedule until some external event happens. */ ++ if (!tick_ctx_is_full(sched, ctx)) ++ goto no_tick; ++ ++ /* If idle groups were scheduled, no need to wake up until some external ++ * event happens (group unblocked, new job submitted, ...). ++ */ ++ if (ctx->idle_group_count) ++ goto no_tick; ++ ++ if (drm_WARN_ON(&sched->ptdev->base, ctx->min_priority >= PANTHOR_CSG_PRIORITY_COUNT)) ++ goto no_tick; ++ ++ /* If there are groups of the same priority waiting, we need to ++ * keep the scheduler ticking, otherwise, we'll just wait for ++ * new groups with higher priority to be queued. ++ */ ++ if (!list_empty(&sched->groups.runnable[ctx->min_priority])) { ++ u64 resched_target = sched->last_tick + sched->tick_period; ++ ++ if (time_before64(sched->resched_target, sched->last_tick) || ++ time_before64(resched_target, sched->resched_target)) ++ sched->resched_target = resched_target; ++ ++ return sched->resched_target - sched->last_tick; ++ } ++ ++no_tick: ++ sched->resched_target = U64_MAX; ++ return U64_MAX; ++} ++ ++static void tick_work(struct work_struct *work) ++{ ++ struct panthor_scheduler *sched = container_of(work, struct panthor_scheduler, ++ tick_work.work); ++ struct panthor_device *ptdev = sched->ptdev; ++ struct panthor_sched_tick_ctx ctx; ++ u64 remaining_jiffies = 0, resched_delay; ++ u64 now = get_jiffies_64(); ++ int prio, ret, cookie; ++ ++ if (!drm_dev_enter(&ptdev->base, &cookie)) ++ return; ++ ++ ret = pm_runtime_resume_and_get(ptdev->base.dev); ++ if (drm_WARN_ON(&ptdev->base, ret)) ++ goto out_dev_exit; ++ ++ if (time_before64(now, sched->resched_target)) ++ remaining_jiffies = sched->resched_target - now; ++ ++ mutex_lock(&sched->lock); ++ if (panthor_device_reset_is_pending(sched->ptdev)) ++ goto out_unlock; ++ ++ tick_ctx_init(sched, &ctx, remaining_jiffies != 0); ++ if (ctx.csg_upd_failed_mask) ++ goto out_cleanup_ctx; ++ ++ if (remaining_jiffies) { ++ /* Scheduling forced in the middle of a tick. Only RT groups ++ * can preempt non-RT ones. Currently running RT groups can't be ++ * preempted. ++ */ ++ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; ++ prio >= 0 && !tick_ctx_is_full(sched, &ctx); ++ prio--) { ++ tick_ctx_pick_groups_from_list(sched, &ctx, &ctx.old_groups[prio], ++ true, true); ++ if (prio == PANTHOR_CSG_PRIORITY_RT) { ++ tick_ctx_pick_groups_from_list(sched, &ctx, ++ &sched->groups.runnable[prio], ++ true, false); ++ } ++ } ++ } ++ ++ /* First pick non-idle groups */ ++ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; ++ prio >= 0 && !tick_ctx_is_full(sched, &ctx); ++ prio--) { ++ tick_ctx_pick_groups_from_list(sched, &ctx, &sched->groups.runnable[prio], ++ true, false); ++ tick_ctx_pick_groups_from_list(sched, &ctx, &ctx.old_groups[prio], true, true); ++ } ++ ++ /* If we have free CSG slots left, pick idle groups */ ++ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; ++ prio >= 0 && !tick_ctx_is_full(sched, &ctx); ++ prio--) { ++ /* Check the old_group queue first to avoid reprogramming the slots */ ++ tick_ctx_pick_groups_from_list(sched, &ctx, &ctx.old_groups[prio], false, true); ++ tick_ctx_pick_groups_from_list(sched, &ctx, &sched->groups.idle[prio], ++ false, false); ++ } ++ ++ tick_ctx_apply(sched, &ctx); ++ if (ctx.csg_upd_failed_mask) ++ goto out_cleanup_ctx; ++ ++ if (ctx.idle_group_count == ctx.group_count) { ++ panthor_devfreq_record_idle(sched->ptdev); ++ if (sched->pm.has_ref) { ++ pm_runtime_put_autosuspend(ptdev->base.dev); ++ sched->pm.has_ref = false; ++ } ++ } else { ++ panthor_devfreq_record_busy(sched->ptdev); ++ if (!sched->pm.has_ref) { ++ pm_runtime_get(ptdev->base.dev); ++ sched->pm.has_ref = true; ++ } ++ } ++ ++ sched->last_tick = now; ++ resched_delay = tick_ctx_update_resched_target(sched, &ctx); ++ if (ctx.immediate_tick) ++ resched_delay = 0; ++ ++ if (resched_delay != U64_MAX) ++ sched_queue_delayed_work(sched, tick, resched_delay); ++ ++out_cleanup_ctx: ++ tick_ctx_cleanup(sched, &ctx); ++ ++out_unlock: ++ mutex_unlock(&sched->lock); ++ pm_runtime_mark_last_busy(ptdev->base.dev); ++ pm_runtime_put_autosuspend(ptdev->base.dev); ++ ++out_dev_exit: ++ drm_dev_exit(cookie); ++} ++ ++static int panthor_queue_eval_syncwait(struct panthor_group *group, u8 queue_idx) ++{ ++ struct panthor_queue *queue = group->queues[queue_idx]; ++ union { ++ struct panthor_syncobj_64b sync64; ++ struct panthor_syncobj_32b sync32; ++ } *syncobj; ++ bool result; ++ u64 value; ++ ++ syncobj = panthor_queue_get_syncwait_obj(group, queue); ++ if (!syncobj) ++ return -EINVAL; ++ ++ value = queue->syncwait.sync64 ? ++ syncobj->sync64.seqno : ++ syncobj->sync32.seqno; ++ ++ if (queue->syncwait.gt) ++ result = value > queue->syncwait.ref; ++ else ++ result = value <= queue->syncwait.ref; ++ ++ if (result) ++ panthor_queue_put_syncwait_obj(queue); ++ ++ return result; ++} ++ ++static void sync_upd_work(struct work_struct *work) ++{ ++ struct panthor_scheduler *sched = container_of(work, ++ struct panthor_scheduler, ++ sync_upd_work); ++ struct panthor_group *group, *tmp; ++ bool immediate_tick = false; ++ ++ mutex_lock(&sched->lock); ++ list_for_each_entry_safe(group, tmp, &sched->groups.waiting, wait_node) { ++ u32 tested_queues = group->blocked_queues; ++ u32 unblocked_queues = 0; ++ ++ while (tested_queues) { ++ u32 cs_id = ffs(tested_queues) - 1; ++ int ret; ++ ++ ret = panthor_queue_eval_syncwait(group, cs_id); ++ drm_WARN_ON(&group->ptdev->base, ret < 0); ++ if (ret) ++ unblocked_queues |= BIT(cs_id); ++ ++ tested_queues &= ~BIT(cs_id); ++ } ++ ++ if (unblocked_queues) { ++ group->blocked_queues &= ~unblocked_queues; ++ ++ if (group->csg_id < 0) { ++ list_move(&group->run_node, ++ &sched->groups.runnable[group->priority]); ++ if (group->priority == PANTHOR_CSG_PRIORITY_RT) ++ immediate_tick = true; ++ } ++ } ++ ++ if (!group->blocked_queues) ++ list_del_init(&group->wait_node); ++ } ++ mutex_unlock(&sched->lock); ++ ++ if (immediate_tick) ++ sched_queue_delayed_work(sched, tick, 0); ++} ++ ++static void group_schedule_locked(struct panthor_group *group, u32 queue_mask) ++{ ++ struct panthor_device *ptdev = group->ptdev; ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct list_head *queue = &sched->groups.runnable[group->priority]; ++ u64 delay_jiffies = 0; ++ bool was_idle; ++ u64 now; ++ ++ if (!group_can_run(group)) ++ return; ++ ++ /* All updated queues are blocked, no need to wake up the scheduler. */ ++ if ((queue_mask & group->blocked_queues) == queue_mask) ++ return; ++ ++ was_idle = group_is_idle(group); ++ group->idle_queues &= ~queue_mask; ++ ++ /* Don't mess up with the lists if we're in a middle of a reset. */ ++ if (atomic_read(&sched->reset.in_progress)) ++ return; ++ ++ if (was_idle && !group_is_idle(group)) ++ list_move_tail(&group->run_node, queue); ++ ++ /* RT groups are preemptive. */ ++ if (group->priority == PANTHOR_CSG_PRIORITY_RT) { ++ sched_queue_delayed_work(sched, tick, 0); ++ return; ++ } ++ ++ /* Some groups might be idle, force an immediate tick to ++ * re-evaluate. ++ */ ++ if (sched->might_have_idle_groups) { ++ sched_queue_delayed_work(sched, tick, 0); ++ return; ++ } ++ ++ /* Scheduler is ticking, nothing to do. */ ++ if (sched->resched_target != U64_MAX) { ++ /* If there are free slots, force immediating ticking. */ ++ if (sched->used_csg_slot_count < sched->csg_slot_count) ++ sched_queue_delayed_work(sched, tick, 0); ++ ++ return; ++ } ++ ++ /* Scheduler tick was off, recalculate the resched_target based on the ++ * last tick event, and queue the scheduler work. ++ */ ++ now = get_jiffies_64(); ++ sched->resched_target = sched->last_tick + sched->tick_period; ++ if (sched->used_csg_slot_count == sched->csg_slot_count && ++ time_before64(now, sched->resched_target)) ++ delay_jiffies = min_t(unsigned long, sched->resched_target - now, ULONG_MAX); ++ ++ sched_queue_delayed_work(sched, tick, delay_jiffies); ++} ++ ++static void queue_stop(struct panthor_queue *queue, ++ struct panthor_job *bad_job) ++{ ++ drm_sched_stop(&queue->scheduler, bad_job ? &bad_job->base : NULL); ++} ++ ++static void queue_start(struct panthor_queue *queue) ++{ ++ struct panthor_job *job; ++ ++ /* Re-assign the parent fences. */ ++ list_for_each_entry(job, &queue->scheduler.pending_list, base.list) ++ job->base.s_fence->parent = dma_fence_get(job->done_fence); ++ ++ drm_sched_start(&queue->scheduler, true); ++} ++ ++static void panthor_group_stop(struct panthor_group *group) ++{ ++ struct panthor_scheduler *sched = group->ptdev->scheduler; ++ ++ lockdep_assert_held(&sched->reset.lock); ++ ++ for (u32 i = 0; i < group->queue_count; i++) ++ queue_stop(group->queues[i], NULL); ++ ++ group_get(group); ++ list_move_tail(&group->run_node, &sched->reset.stopped_groups); ++} ++ ++static void panthor_group_start(struct panthor_group *group) ++{ ++ struct panthor_scheduler *sched = group->ptdev->scheduler; ++ ++ lockdep_assert_held(&group->ptdev->scheduler->reset.lock); ++ ++ for (u32 i = 0; i < group->queue_count; i++) ++ queue_start(group->queues[i]); ++ ++ if (group_can_run(group)) { ++ list_move_tail(&group->run_node, ++ group_is_idle(group) ? ++ &sched->groups.idle[group->priority] : ++ &sched->groups.runnable[group->priority]); ++ } else { ++ list_del_init(&group->run_node); ++ list_del_init(&group->wait_node); ++ group_queue_work(group, term); ++ } ++ ++ group_put(group); ++} ++ ++static void panthor_sched_immediate_tick(struct panthor_device *ptdev) ++{ ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ ++ sched_queue_delayed_work(sched, tick, 0); ++} ++ ++/** ++ * panthor_sched_report_mmu_fault() - Report MMU faults to the scheduler. ++ */ ++void panthor_sched_report_mmu_fault(struct panthor_device *ptdev) ++{ ++ /* Force a tick to immediately kill faulty groups. */ ++ if (ptdev->scheduler) ++ panthor_sched_immediate_tick(ptdev); ++} ++ ++void panthor_sched_resume(struct panthor_device *ptdev) ++{ ++ /* Force a tick to re-evaluate after a resume. */ ++ panthor_sched_immediate_tick(ptdev); ++} ++ ++void panthor_sched_suspend(struct panthor_device *ptdev) ++{ ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_csg_slots_upd_ctx upd_ctx; ++ u64 suspended_slots, faulty_slots; ++ struct panthor_group *group; ++ u32 i; ++ ++ mutex_lock(&sched->lock); ++ csgs_upd_ctx_init(&upd_ctx); ++ for (i = 0; i < sched->csg_slot_count; i++) { ++ struct panthor_csg_slot *csg_slot = &sched->csg_slots[i]; ++ ++ if (csg_slot->group) { ++ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, i, ++ CSG_STATE_SUSPEND, ++ CSG_STATE_MASK); ++ } ++ } ++ ++ suspended_slots = upd_ctx.update_mask; ++ ++ csgs_upd_ctx_apply_locked(ptdev, &upd_ctx); ++ suspended_slots &= ~upd_ctx.timedout_mask; ++ faulty_slots = upd_ctx.timedout_mask; ++ ++ if (faulty_slots) { ++ u32 slot_mask = faulty_slots; ++ ++ drm_err(&ptdev->base, "CSG suspend failed, escalating to termination"); ++ csgs_upd_ctx_init(&upd_ctx); ++ while (slot_mask) { ++ u32 csg_id = ffs(slot_mask) - 1; ++ ++ csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, csg_id, ++ CSG_STATE_TERMINATE, ++ CSG_STATE_MASK); ++ slot_mask &= ~BIT(csg_id); ++ } ++ ++ csgs_upd_ctx_apply_locked(ptdev, &upd_ctx); ++ ++ slot_mask = upd_ctx.timedout_mask; ++ while (slot_mask) { ++ u32 csg_id = ffs(slot_mask) - 1; ++ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; ++ ++ /* Terminate command timedout, but the soft-reset will ++ * automatically terminate all active groups, so let's ++ * force the state to halted here. ++ */ ++ if (csg_slot->group->state != PANTHOR_CS_GROUP_TERMINATED) ++ csg_slot->group->state = PANTHOR_CS_GROUP_TERMINATED; ++ slot_mask &= ~BIT(csg_id); ++ } ++ } ++ ++ /* Flush L2 and LSC caches to make sure suspend state is up-to-date. ++ * If the flush fails, flag all queues for termination. ++ */ ++ if (suspended_slots) { ++ bool flush_caches_failed = false; ++ u32 slot_mask = suspended_slots; ++ ++ if (panthor_gpu_flush_caches(ptdev, CACHE_CLEAN, CACHE_CLEAN, 0)) ++ flush_caches_failed = true; ++ ++ while (slot_mask) { ++ u32 csg_id = ffs(slot_mask) - 1; ++ struct panthor_csg_slot *csg_slot = &sched->csg_slots[csg_id]; ++ ++ if (flush_caches_failed) ++ csg_slot->group->state = PANTHOR_CS_GROUP_TERMINATED; ++ else ++ csg_slot_sync_update_locked(ptdev, csg_id); ++ ++ slot_mask &= ~BIT(csg_id); ++ } ++ ++ if (flush_caches_failed) ++ faulty_slots |= suspended_slots; ++ } ++ ++ for (i = 0; i < sched->csg_slot_count; i++) { ++ struct panthor_csg_slot *csg_slot = &sched->csg_slots[i]; ++ ++ group = csg_slot->group; ++ if (!group) ++ continue; ++ ++ group_get(group); ++ ++ if (group->csg_id >= 0) ++ sched_process_csg_irq_locked(ptdev, group->csg_id); ++ ++ group_unbind_locked(group); ++ ++ drm_WARN_ON(&group->ptdev->base, !list_empty(&group->run_node)); ++ ++ if (group_can_run(group)) { ++ list_add(&group->run_node, ++ &sched->groups.idle[group->priority]); ++ } else { ++ /* We don't bother stopping the scheduler if the group is ++ * faulty, the group termination work will finish the job. ++ */ ++ list_del_init(&group->wait_node); ++ group_queue_work(group, term); ++ } ++ group_put(group); ++ } ++ mutex_unlock(&sched->lock); ++} ++ ++void panthor_sched_pre_reset(struct panthor_device *ptdev) ++{ ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_group *group, *group_tmp; ++ u32 i; ++ ++ mutex_lock(&sched->reset.lock); ++ atomic_set(&sched->reset.in_progress, true); ++ ++ /* Cancel all scheduler works. Once this is done, these works can't be ++ * scheduled again until the reset operation is complete. ++ */ ++ cancel_work_sync(&sched->sync_upd_work); ++ cancel_delayed_work_sync(&sched->tick_work); ++ ++ panthor_sched_suspend(ptdev); ++ ++ /* Stop all groups that might still accept jobs, so we don't get passed ++ * new jobs while we're resetting. ++ */ ++ for (i = 0; i < ARRAY_SIZE(sched->groups.runnable); i++) { ++ /* All groups should be in the idle lists. */ ++ drm_WARN_ON(&ptdev->base, !list_empty(&sched->groups.runnable[i])); ++ list_for_each_entry_safe(group, group_tmp, &sched->groups.runnable[i], run_node) ++ panthor_group_stop(group); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(sched->groups.idle); i++) { ++ list_for_each_entry_safe(group, group_tmp, &sched->groups.idle[i], run_node) ++ panthor_group_stop(group); ++ } ++ ++ mutex_unlock(&sched->reset.lock); ++} ++ ++void panthor_sched_post_reset(struct panthor_device *ptdev) ++{ ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_group *group, *group_tmp; ++ ++ mutex_lock(&sched->reset.lock); ++ ++ list_for_each_entry_safe(group, group_tmp, &sched->reset.stopped_groups, run_node) ++ panthor_group_start(group); ++ ++ /* We're done resetting the GPU, clear the reset.in_progress bit so we can ++ * kick the scheduler. ++ */ ++ atomic_set(&sched->reset.in_progress, false); ++ mutex_unlock(&sched->reset.lock); ++ ++ sched_queue_delayed_work(sched, tick, 0); ++ ++ sched_queue_work(sched, sync_upd); ++} ++ ++static void group_sync_upd_work(struct work_struct *work) ++{ ++ struct panthor_group *group = ++ container_of(work, struct panthor_group, sync_upd_work); ++ struct panthor_job *job, *job_tmp; ++ LIST_HEAD(done_jobs); ++ u32 queue_idx; ++ bool cookie; ++ ++ cookie = dma_fence_begin_signalling(); ++ for (queue_idx = 0; queue_idx < group->queue_count; queue_idx++) { ++ struct panthor_queue *queue = group->queues[queue_idx]; ++ struct panthor_syncobj_64b *syncobj; ++ ++ if (!queue) ++ continue; ++ ++ syncobj = group->syncobjs->kmap + (queue_idx * sizeof(*syncobj)); ++ ++ spin_lock(&queue->fence_ctx.lock); ++ list_for_each_entry_safe(job, job_tmp, &queue->fence_ctx.in_flight_jobs, node) { ++ if (!job->call_info.size) ++ continue; ++ ++ if (syncobj->seqno < job->done_fence->seqno) ++ break; ++ ++ list_move_tail(&job->node, &done_jobs); ++ dma_fence_signal_locked(job->done_fence); ++ } ++ spin_unlock(&queue->fence_ctx.lock); ++ } ++ dma_fence_end_signalling(cookie); ++ ++ list_for_each_entry_safe(job, job_tmp, &done_jobs, node) { ++ list_del_init(&job->node); ++ panthor_job_put(&job->base); ++ } ++ ++ group_put(group); ++} ++ ++static struct dma_fence * ++queue_run_job(struct drm_sched_job *sched_job) ++{ ++ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); ++ struct panthor_group *group = job->group; ++ struct panthor_queue *queue = group->queues[job->queue_idx]; ++ struct panthor_device *ptdev = group->ptdev; ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ u32 ringbuf_size = panthor_kernel_bo_size(queue->ringbuf); ++ u32 ringbuf_insert = queue->iface.input->insert & (ringbuf_size - 1); ++ u64 addr_reg = ptdev->csif_info.cs_reg_count - ++ ptdev->csif_info.unpreserved_cs_reg_count; ++ u64 val_reg = addr_reg + 2; ++ u64 sync_addr = panthor_kernel_bo_gpuva(group->syncobjs) + ++ job->queue_idx * sizeof(struct panthor_syncobj_64b); ++ u32 waitall_mask = GENMASK(sched->sb_slot_count - 1, 0); ++ struct dma_fence *done_fence; ++ int ret; ++ ++ u64 call_instrs[NUM_INSTRS_PER_SLOT] = { ++ /* MOV32 rX+2, cs.latest_flush */ ++ (2ull << 56) | (val_reg << 48) | job->call_info.latest_flush, ++ ++ /* FLUSH_CACHE2.clean_inv_all.no_wait.signal(0) rX+2 */ ++ (36ull << 56) | (0ull << 48) | (val_reg << 40) | (0 << 16) | 0x233, ++ ++ /* MOV48 rX:rX+1, cs.start */ ++ (1ull << 56) | (addr_reg << 48) | job->call_info.start, ++ ++ /* MOV32 rX+2, cs.size */ ++ (2ull << 56) | (val_reg << 48) | job->call_info.size, ++ ++ /* WAIT(0) => waits for FLUSH_CACHE2 instruction */ ++ (3ull << 56) | (1 << 16), ++ ++ /* CALL rX:rX+1, rX+2 */ ++ (32ull << 56) | (addr_reg << 40) | (val_reg << 32), ++ ++ /* MOV48 rX:rX+1, sync_addr */ ++ (1ull << 56) | (addr_reg << 48) | sync_addr, ++ ++ /* MOV48 rX+2, #1 */ ++ (1ull << 56) | (val_reg << 48) | 1, ++ ++ /* WAIT(all) */ ++ (3ull << 56) | (waitall_mask << 16), ++ ++ /* SYNC_ADD64.system_scope.propage_err.nowait rX:rX+1, rX+2*/ ++ (51ull << 56) | (0ull << 48) | (addr_reg << 40) | (val_reg << 32) | (0 << 16) | 1, ++ ++ /* ERROR_BARRIER, so we can recover from faults at job ++ * boundaries. ++ */ ++ (47ull << 56), ++ }; ++ ++ /* Need to be cacheline aligned to please the prefetcher. */ ++ static_assert(sizeof(call_instrs) % 64 == 0, ++ "call_instrs is not aligned on a cacheline"); ++ ++ /* Stream size is zero, nothing to do => return a NULL fence and let ++ * drm_sched signal the parent. ++ */ ++ if (!job->call_info.size) ++ return NULL; ++ ++ ret = pm_runtime_resume_and_get(ptdev->base.dev); ++ if (drm_WARN_ON(&ptdev->base, ret)) ++ return ERR_PTR(ret); ++ ++ mutex_lock(&sched->lock); ++ if (!group_can_run(group)) { ++ done_fence = ERR_PTR(-ECANCELED); ++ goto out_unlock; ++ } ++ ++ dma_fence_init(job->done_fence, ++ &panthor_queue_fence_ops, ++ &queue->fence_ctx.lock, ++ queue->fence_ctx.id, ++ atomic64_inc_return(&queue->fence_ctx.seqno)); ++ ++ memcpy(queue->ringbuf->kmap + ringbuf_insert, ++ call_instrs, sizeof(call_instrs)); ++ ++ panthor_job_get(&job->base); ++ spin_lock(&queue->fence_ctx.lock); ++ list_add_tail(&job->node, &queue->fence_ctx.in_flight_jobs); ++ spin_unlock(&queue->fence_ctx.lock); ++ ++ job->ringbuf.start = queue->iface.input->insert; ++ job->ringbuf.end = job->ringbuf.start + sizeof(call_instrs); ++ ++ /* Make sure the ring buffer is updated before the INSERT ++ * register. ++ */ ++ wmb(); ++ ++ queue->iface.input->extract = queue->iface.output->extract; ++ queue->iface.input->insert = job->ringbuf.end; ++ ++ if (group->csg_id < 0) { ++ /* If the queue is blocked, we want to keep the timeout running, so we ++ * can detect unbounded waits and kill the group when that happens. ++ * Otherwise, we suspend the timeout so the time we spend waiting for ++ * a CSG slot is not counted. ++ */ ++ if (!(group->blocked_queues & BIT(job->queue_idx)) && ++ !queue->timeout_suspended) { ++ queue->remaining_time = drm_sched_suspend_timeout(&queue->scheduler); ++ queue->timeout_suspended = true; ++ } ++ ++ group_schedule_locked(group, BIT(job->queue_idx)); ++ } else { ++ gpu_write(ptdev, CSF_DOORBELL(queue->doorbell_id), 1); ++ if (!sched->pm.has_ref && ++ !(group->blocked_queues & BIT(job->queue_idx))) { ++ pm_runtime_get(ptdev->base.dev); ++ sched->pm.has_ref = true; ++ } ++ } ++ ++ done_fence = dma_fence_get(job->done_fence); ++ ++out_unlock: ++ mutex_unlock(&sched->lock); ++ pm_runtime_mark_last_busy(ptdev->base.dev); ++ pm_runtime_put_autosuspend(ptdev->base.dev); ++ ++ return done_fence; ++} ++ ++static enum drm_gpu_sched_stat ++queue_timedout_job(struct drm_sched_job *sched_job) ++{ ++ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); ++ struct panthor_group *group = job->group; ++ struct panthor_device *ptdev = group->ptdev; ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_queue *queue = group->queues[job->queue_idx]; ++ ++ drm_warn(&ptdev->base, "job timeout\n"); ++ ++ drm_WARN_ON(&ptdev->base, atomic_read(&sched->reset.in_progress)); ++ ++ queue_stop(queue, job); ++ ++ mutex_lock(&sched->lock); ++ group->timedout = true; ++ if (group->csg_id >= 0) { ++ sched_queue_delayed_work(ptdev->scheduler, tick, 0); ++ } else { ++ /* Remove from the run queues, so the scheduler can't ++ * pick the group on the next tick. ++ */ ++ list_del_init(&group->run_node); ++ list_del_init(&group->wait_node); ++ ++ group_queue_work(group, term); ++ } ++ mutex_unlock(&sched->lock); ++ ++ queue_start(queue); ++ ++ return DRM_GPU_SCHED_STAT_NOMINAL; ++} ++ ++static void queue_free_job(struct drm_sched_job *sched_job) ++{ ++ drm_sched_job_cleanup(sched_job); ++ panthor_job_put(sched_job); ++} ++ ++static const struct drm_sched_backend_ops panthor_queue_sched_ops = { ++ .run_job = queue_run_job, ++ .timedout_job = queue_timedout_job, ++ .free_job = queue_free_job, ++}; ++ ++static struct panthor_queue * ++group_create_queue(struct panthor_group *group, ++ const struct drm_panthor_queue_create *args) ++{ ++ struct drm_gpu_scheduler *drm_sched; ++ struct panthor_queue *queue; ++ int ret; ++ ++ if (args->pad[0] || args->pad[1] || args->pad[2]) ++ return ERR_PTR(-EINVAL); ++ ++ if (args->ringbuf_size < SZ_4K || args->ringbuf_size > SZ_64K || ++ !is_power_of_2(args->ringbuf_size)) ++ return ERR_PTR(-EINVAL); ++ ++ if (args->priority > CSF_MAX_QUEUE_PRIO) ++ return ERR_PTR(-EINVAL); ++ ++ queue = kzalloc(sizeof(*queue), GFP_KERNEL); ++ if (!queue) ++ return ERR_PTR(-ENOMEM); ++ ++ queue->fence_ctx.id = dma_fence_context_alloc(1); ++ spin_lock_init(&queue->fence_ctx.lock); ++ INIT_LIST_HEAD(&queue->fence_ctx.in_flight_jobs); ++ ++ queue->priority = args->priority; ++ ++ queue->ringbuf = panthor_kernel_bo_create(group->ptdev, group->vm, ++ args->ringbuf_size, ++ DRM_PANTHOR_BO_NO_MMAP, ++ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | ++ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED, ++ PANTHOR_VM_KERNEL_AUTO_VA); ++ if (IS_ERR(queue->ringbuf)) { ++ ret = PTR_ERR(queue->ringbuf); ++ goto err_free_queue; ++ } ++ ++ ret = panthor_kernel_bo_vmap(queue->ringbuf); ++ if (ret) ++ goto err_free_queue; ++ ++ queue->iface.mem = panthor_fw_alloc_queue_iface_mem(group->ptdev, ++ &queue->iface.input, ++ &queue->iface.output, ++ &queue->iface.input_fw_va, ++ &queue->iface.output_fw_va); ++ if (IS_ERR(queue->iface.mem)) { ++ ret = PTR_ERR(queue->iface.mem); ++ goto err_free_queue; ++ } ++ ++ ret = drm_sched_init(&queue->scheduler, &panthor_queue_sched_ops, ++ group->ptdev->scheduler->wq, 1, ++ args->ringbuf_size / (NUM_INSTRS_PER_SLOT * sizeof(u64)), ++ 0, msecs_to_jiffies(JOB_TIMEOUT_MS), ++ group->ptdev->reset.wq, ++ NULL, "panthor-queue", group->ptdev->base.dev); ++ if (ret) ++ goto err_free_queue; ++ ++ drm_sched = &queue->scheduler; ++ ret = drm_sched_entity_init(&queue->entity, 0, &drm_sched, 1, NULL); ++ ++ return queue; ++ ++err_free_queue: ++ group_free_queue(group, queue); ++ return ERR_PTR(ret); ++} ++ ++#define MAX_GROUPS_PER_POOL 128 ++ ++int panthor_group_create(struct panthor_file *pfile, ++ const struct drm_panthor_group_create *group_args, ++ const struct drm_panthor_queue_create *queue_args) ++{ ++ struct panthor_device *ptdev = pfile->ptdev; ++ struct panthor_group_pool *gpool = pfile->groups; ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_fw_csg_iface *csg_iface = panthor_fw_get_csg_iface(ptdev, 0); ++ struct panthor_group *group = NULL; ++ u32 gid, i, suspend_size; ++ int ret; ++ ++ if (group_args->pad) ++ return -EINVAL; ++ ++ if (group_args->priority > PANTHOR_CSG_PRIORITY_HIGH) ++ return -EINVAL; ++ ++ if ((group_args->compute_core_mask & ~ptdev->gpu_info.shader_present) || ++ (group_args->fragment_core_mask & ~ptdev->gpu_info.shader_present) || ++ (group_args->tiler_core_mask & ~ptdev->gpu_info.tiler_present)) ++ return -EINVAL; ++ ++ if (hweight64(group_args->compute_core_mask) < group_args->max_compute_cores || ++ hweight64(group_args->fragment_core_mask) < group_args->max_fragment_cores || ++ hweight64(group_args->tiler_core_mask) < group_args->max_tiler_cores) ++ return -EINVAL; ++ ++ group = kzalloc(sizeof(*group), GFP_KERNEL); ++ if (!group) ++ return -ENOMEM; ++ ++ spin_lock_init(&group->fatal_lock); ++ kref_init(&group->refcount); ++ group->state = PANTHOR_CS_GROUP_CREATED; ++ group->csg_id = -1; ++ ++ group->ptdev = ptdev; ++ group->max_compute_cores = group_args->max_compute_cores; ++ group->compute_core_mask = group_args->compute_core_mask; ++ group->max_fragment_cores = group_args->max_fragment_cores; ++ group->fragment_core_mask = group_args->fragment_core_mask; ++ group->max_tiler_cores = group_args->max_tiler_cores; ++ group->tiler_core_mask = group_args->tiler_core_mask; ++ group->priority = group_args->priority; ++ ++ INIT_LIST_HEAD(&group->wait_node); ++ INIT_LIST_HEAD(&group->run_node); ++ INIT_WORK(&group->term_work, group_term_work); ++ INIT_WORK(&group->sync_upd_work, group_sync_upd_work); ++ INIT_WORK(&group->tiler_oom_work, group_tiler_oom_work); ++ INIT_WORK(&group->release_work, group_release_work); ++ ++ group->vm = panthor_vm_pool_get_vm(pfile->vms, group_args->vm_id); ++ if (!group->vm) { ++ ret = -EINVAL; ++ goto err_put_group; ++ } ++ ++ suspend_size = csg_iface->control->suspend_size; ++ group->suspend_buf = panthor_fw_alloc_suspend_buf_mem(ptdev, suspend_size); ++ if (IS_ERR(group->suspend_buf)) { ++ ret = PTR_ERR(group->suspend_buf); ++ group->suspend_buf = NULL; ++ goto err_put_group; ++ } ++ ++ suspend_size = csg_iface->control->protm_suspend_size; ++ group->protm_suspend_buf = panthor_fw_alloc_suspend_buf_mem(ptdev, suspend_size); ++ if (IS_ERR(group->protm_suspend_buf)) { ++ ret = PTR_ERR(group->protm_suspend_buf); ++ group->protm_suspend_buf = NULL; ++ goto err_put_group; ++ } ++ ++ group->syncobjs = panthor_kernel_bo_create(ptdev, group->vm, ++ group_args->queues.count * ++ sizeof(struct panthor_syncobj_64b), ++ DRM_PANTHOR_BO_NO_MMAP, ++ DRM_PANTHOR_VM_BIND_OP_MAP_NOEXEC | ++ DRM_PANTHOR_VM_BIND_OP_MAP_UNCACHED, ++ PANTHOR_VM_KERNEL_AUTO_VA); ++ if (IS_ERR(group->syncobjs)) { ++ ret = PTR_ERR(group->syncobjs); ++ goto err_put_group; ++ } ++ ++ ret = panthor_kernel_bo_vmap(group->syncobjs); ++ if (ret) ++ goto err_put_group; ++ ++ memset(group->syncobjs->kmap, 0, ++ group_args->queues.count * sizeof(struct panthor_syncobj_64b)); ++ ++ for (i = 0; i < group_args->queues.count; i++) { ++ group->queues[i] = group_create_queue(group, &queue_args[i]); ++ if (IS_ERR(group->queues[i])) { ++ ret = PTR_ERR(group->queues[i]); ++ group->queues[i] = NULL; ++ goto err_put_group; ++ } ++ ++ group->queue_count++; ++ } ++ ++ group->idle_queues = GENMASK(group->queue_count - 1, 0); ++ ++ ret = xa_alloc(&gpool->xa, &gid, group, XA_LIMIT(1, MAX_GROUPS_PER_POOL), GFP_KERNEL); ++ if (ret) ++ goto err_put_group; ++ ++ mutex_lock(&sched->reset.lock); ++ if (atomic_read(&sched->reset.in_progress)) { ++ panthor_group_stop(group); ++ } else { ++ mutex_lock(&sched->lock); ++ list_add_tail(&group->run_node, ++ &sched->groups.idle[group->priority]); ++ mutex_unlock(&sched->lock); ++ } ++ mutex_unlock(&sched->reset.lock); ++ ++ return gid; ++ ++err_put_group: ++ group_put(group); ++ return ret; ++} ++ ++int panthor_group_destroy(struct panthor_file *pfile, u32 group_handle) ++{ ++ struct panthor_group_pool *gpool = pfile->groups; ++ struct panthor_device *ptdev = pfile->ptdev; ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_group *group; ++ ++ group = xa_erase(&gpool->xa, group_handle); ++ if (!group) ++ return -EINVAL; ++ ++ for (u32 i = 0; i < group->queue_count; i++) { ++ if (group->queues[i]) ++ drm_sched_entity_destroy(&group->queues[i]->entity); ++ } ++ ++ mutex_lock(&sched->reset.lock); ++ mutex_lock(&sched->lock); ++ group->destroyed = true; ++ if (group->csg_id >= 0) { ++ sched_queue_delayed_work(sched, tick, 0); ++ } else if (!atomic_read(&sched->reset.in_progress)) { ++ /* Remove from the run queues, so the scheduler can't ++ * pick the group on the next tick. ++ */ ++ list_del_init(&group->run_node); ++ list_del_init(&group->wait_node); ++ group_queue_work(group, term); ++ } ++ mutex_unlock(&sched->lock); ++ mutex_unlock(&sched->reset.lock); ++ ++ group_put(group); ++ return 0; ++} ++ ++int panthor_group_get_state(struct panthor_file *pfile, ++ struct drm_panthor_group_get_state *get_state) ++{ ++ struct panthor_group_pool *gpool = pfile->groups; ++ struct panthor_device *ptdev = pfile->ptdev; ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ struct panthor_group *group; ++ ++ if (get_state->pad) ++ return -EINVAL; ++ ++ group = group_get(xa_load(&gpool->xa, get_state->group_handle)); ++ if (!group) ++ return -EINVAL; ++ ++ memset(get_state, 0, sizeof(*get_state)); ++ ++ mutex_lock(&sched->lock); ++ if (group->timedout) ++ get_state->state |= DRM_PANTHOR_GROUP_STATE_TIMEDOUT; ++ if (group->fatal_queues) { ++ get_state->state |= DRM_PANTHOR_GROUP_STATE_FATAL_FAULT; ++ get_state->fatal_queues = group->fatal_queues; ++ } ++ mutex_unlock(&sched->lock); ++ ++ group_put(group); ++ return 0; ++} ++ ++int panthor_group_pool_create(struct panthor_file *pfile) ++{ ++ struct panthor_group_pool *gpool; ++ ++ gpool = kzalloc(sizeof(*gpool), GFP_KERNEL); ++ if (!gpool) ++ return -ENOMEM; ++ ++ xa_init_flags(&gpool->xa, XA_FLAGS_ALLOC1); ++ pfile->groups = gpool; ++ return 0; ++} ++ ++void panthor_group_pool_destroy(struct panthor_file *pfile) ++{ ++ struct panthor_group_pool *gpool = pfile->groups; ++ struct panthor_group *group; ++ unsigned long i; ++ ++ if (IS_ERR_OR_NULL(gpool)) ++ return; ++ ++ xa_for_each(&gpool->xa, i, group) ++ panthor_group_destroy(pfile, i); ++ ++ xa_destroy(&gpool->xa); ++ kfree(gpool); ++ pfile->groups = NULL; ++} ++ ++static void job_release(struct kref *ref) ++{ ++ struct panthor_job *job = container_of(ref, struct panthor_job, refcount); ++ ++ drm_WARN_ON(&job->group->ptdev->base, !list_empty(&job->node)); ++ ++ if (job->base.s_fence) ++ drm_sched_job_cleanup(&job->base); ++ ++ if (job->done_fence && job->done_fence->ops) ++ dma_fence_put(job->done_fence); ++ else ++ dma_fence_free(job->done_fence); ++ ++ group_put(job->group); ++ ++ kfree(job); ++} ++ ++struct drm_sched_job *panthor_job_get(struct drm_sched_job *sched_job) ++{ ++ if (sched_job) { ++ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); ++ ++ kref_get(&job->refcount); ++ } ++ ++ return sched_job; ++} ++ ++void panthor_job_put(struct drm_sched_job *sched_job) ++{ ++ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); ++ ++ if (sched_job) ++ kref_put(&job->refcount, job_release); ++} ++ ++struct panthor_vm *panthor_job_vm(struct drm_sched_job *sched_job) ++{ ++ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); ++ ++ return job->group->vm; ++} ++ ++struct drm_sched_job * ++panthor_job_create(struct panthor_file *pfile, ++ u16 group_handle, ++ const struct drm_panthor_queue_submit *qsubmit) ++{ ++ struct panthor_group_pool *gpool = pfile->groups; ++ struct panthor_job *job; ++ int ret; ++ ++ if (qsubmit->pad) ++ return ERR_PTR(-EINVAL); ++ ++ /* If stream_addr is zero, so stream_size should be. */ ++ if ((qsubmit->stream_size == 0) != (qsubmit->stream_addr == 0)) ++ return ERR_PTR(-EINVAL); ++ ++ /* Make sure the address is aligned on 64-byte (cacheline) and the size is ++ * aligned on 8-byte (instruction size). ++ */ ++ if ((qsubmit->stream_addr & 63) || (qsubmit->stream_size & 7)) ++ return ERR_PTR(-EINVAL); ++ ++ /* bits 24:30 must be zero. */ ++ if (qsubmit->latest_flush & GENMASK(30, 24)) ++ return ERR_PTR(-EINVAL); ++ ++ job = kzalloc(sizeof(*job), GFP_KERNEL); ++ if (!job) ++ return ERR_PTR(-ENOMEM); ++ ++ kref_init(&job->refcount); ++ job->queue_idx = qsubmit->queue_index; ++ job->call_info.size = qsubmit->stream_size; ++ job->call_info.start = qsubmit->stream_addr; ++ job->call_info.latest_flush = qsubmit->latest_flush; ++ INIT_LIST_HEAD(&job->node); ++ ++ job->group = group_get(xa_load(&gpool->xa, group_handle)); ++ if (!job->group) { ++ ret = -EINVAL; ++ goto err_put_job; ++ } ++ ++ if (job->queue_idx >= job->group->queue_count || ++ !job->group->queues[job->queue_idx]) { ++ ret = -EINVAL; ++ goto err_put_job; ++ } ++ ++ job->done_fence = kzalloc(sizeof(*job->done_fence), GFP_KERNEL); ++ if (!job->done_fence) { ++ ret = -ENOMEM; ++ goto err_put_job; ++ } ++ ++ ret = drm_sched_job_init(&job->base, ++ &job->group->queues[job->queue_idx]->entity, ++ 1, job->group); ++ if (ret) ++ goto err_put_job; ++ ++ return &job->base; ++ ++err_put_job: ++ panthor_job_put(&job->base); ++ return ERR_PTR(ret); ++} ++ ++void panthor_job_update_resvs(struct drm_exec *exec, struct drm_sched_job *sched_job) ++{ ++ struct panthor_job *job = container_of(sched_job, struct panthor_job, base); ++ ++ /* Still not sure why we want USAGE_WRITE for external objects, since I ++ * was assuming this would be handled through explicit syncs being imported ++ * to external BOs with DMA_BUF_IOCTL_IMPORT_SYNC_FILE, but other drivers ++ * seem to pass DMA_RESV_USAGE_WRITE, so there must be a good reason. ++ */ ++ panthor_vm_update_resvs(job->group->vm, exec, &sched_job->s_fence->finished, ++ DMA_RESV_USAGE_BOOKKEEP, DMA_RESV_USAGE_WRITE); ++} ++ ++void panthor_sched_unplug(struct panthor_device *ptdev) ++{ ++ struct panthor_scheduler *sched = ptdev->scheduler; ++ ++ cancel_delayed_work_sync(&sched->tick_work); ++ ++ mutex_lock(&sched->lock); ++ if (sched->pm.has_ref) { ++ pm_runtime_put(ptdev->base.dev); ++ sched->pm.has_ref = false; ++ } ++ mutex_unlock(&sched->lock); ++} ++ ++static void panthor_sched_fini(struct drm_device *ddev, void *res) ++{ ++ struct panthor_scheduler *sched = res; ++ int prio; ++ ++ if (!sched || !sched->csg_slot_count) ++ return; ++ ++ cancel_delayed_work_sync(&sched->tick_work); ++ ++ if (sched->wq) ++ destroy_workqueue(sched->wq); ++ ++ if (sched->heap_alloc_wq) ++ destroy_workqueue(sched->heap_alloc_wq); ++ ++ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { ++ drm_WARN_ON(ddev, !list_empty(&sched->groups.runnable[prio])); ++ drm_WARN_ON(ddev, !list_empty(&sched->groups.idle[prio])); ++ } ++ ++ drm_WARN_ON(ddev, !list_empty(&sched->groups.waiting)); ++} ++ ++int panthor_sched_init(struct panthor_device *ptdev) ++{ ++ struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev); ++ struct panthor_fw_csg_iface *csg_iface = panthor_fw_get_csg_iface(ptdev, 0); ++ struct panthor_fw_cs_iface *cs_iface = panthor_fw_get_cs_iface(ptdev, 0, 0); ++ struct panthor_scheduler *sched; ++ u32 gpu_as_count, num_groups; ++ int prio, ret; ++ ++ sched = drmm_kzalloc(&ptdev->base, sizeof(*sched), GFP_KERNEL); ++ if (!sched) ++ return -ENOMEM; ++ ++ /* The highest bit in JOB_INT_* is reserved for globabl IRQs. That ++ * leaves 31 bits for CSG IRQs, hence the MAX_CSGS clamp here. ++ */ ++ num_groups = min_t(u32, MAX_CSGS, glb_iface->control->group_num); ++ ++ /* The FW-side scheduler might deadlock if two groups with the same ++ * priority try to access a set of resources that overlaps, with part ++ * of the resources being allocated to one group and the other part to ++ * the other group, both groups waiting for the remaining resources to ++ * be allocated. To avoid that, it is recommended to assign each CSG a ++ * different priority. In theory we could allow several groups to have ++ * the same CSG priority if they don't request the same resources, but ++ * that makes the scheduling logic more complicated, so let's clamp ++ * the number of CSG slots to MAX_CSG_PRIO + 1 for now. ++ */ ++ num_groups = min_t(u32, MAX_CSG_PRIO + 1, num_groups); ++ ++ /* We need at least one AS for the MCU and one for the GPU contexts. */ ++ gpu_as_count = hweight32(ptdev->gpu_info.as_present & GENMASK(31, 1)); ++ if (!gpu_as_count) { ++ drm_err(&ptdev->base, "Not enough AS (%d, expected at least 2)", ++ gpu_as_count + 1); ++ return -EINVAL; ++ } ++ ++ sched->ptdev = ptdev; ++ sched->sb_slot_count = CS_FEATURES_SCOREBOARDS(cs_iface->control->features); ++ sched->csg_slot_count = num_groups; ++ sched->cs_slot_count = csg_iface->control->stream_num; ++ sched->as_slot_count = gpu_as_count; ++ ptdev->csif_info.csg_slot_count = sched->csg_slot_count; ++ ptdev->csif_info.cs_slot_count = sched->cs_slot_count; ++ ptdev->csif_info.scoreboard_slot_count = sched->sb_slot_count; ++ ++ sched->last_tick = 0; ++ sched->resched_target = U64_MAX; ++ sched->tick_period = msecs_to_jiffies(10); ++ INIT_DELAYED_WORK(&sched->tick_work, tick_work); ++ INIT_WORK(&sched->sync_upd_work, sync_upd_work); ++ INIT_WORK(&sched->fw_events_work, process_fw_events_work); ++ ++ ret = drmm_mutex_init(&ptdev->base, &sched->lock); ++ if (ret) ++ return ret; ++ ++ for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1; prio >= 0; prio--) { ++ INIT_LIST_HEAD(&sched->groups.runnable[prio]); ++ INIT_LIST_HEAD(&sched->groups.idle[prio]); ++ } ++ INIT_LIST_HEAD(&sched->groups.waiting); ++ ++ ret = drmm_mutex_init(&ptdev->base, &sched->reset.lock); ++ if (ret) ++ return ret; ++ ++ INIT_LIST_HEAD(&sched->reset.stopped_groups); ++ ++ /* sched->heap_alloc_wq will be used for heap chunk allocation on ++ * tiler OOM events, which means we can't use the same workqueue for ++ * the scheduler because works queued by the scheduler are in ++ * the dma-signalling path. Allocate a dedicated heap_alloc_wq to ++ * work around this limitation. ++ * ++ * FIXME: Ultimately, what we need is a failable/non-blocking GEM ++ * allocation path that we can call when a heap OOM is reported. The ++ * FW is smart enough to fall back on other methods if the kernel can't ++ * allocate memory, and fail the tiling job if none of these ++ * countermeasures worked. ++ * ++ * Set WQ_MEM_RECLAIM on sched->wq to unblock the situation when the ++ * system is running out of memory. ++ */ ++ sched->heap_alloc_wq = alloc_workqueue("panthor-heap-alloc", WQ_UNBOUND, 0); ++ sched->wq = alloc_workqueue("panthor-csf-sched", WQ_MEM_RECLAIM | WQ_UNBOUND, 0); ++ if (!sched->wq || !sched->heap_alloc_wq) { ++ panthor_sched_fini(&ptdev->base, sched); ++ drm_err(&ptdev->base, "Failed to allocate the workqueues"); ++ return -ENOMEM; ++ } ++ ++ ret = drmm_add_action_or_reset(&ptdev->base, panthor_sched_fini, sched); ++ if (ret) ++ return ret; ++ ++ ptdev->scheduler = sched; ++ return 0; ++} +diff --git a/drivers/gpu/drm/panthor/panthor_sched.h b/drivers/gpu/drm/panthor/panthor_sched.h +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_sched.h +@@ -0,0 +1,50 @@ ++/* SPDX-License-Identifier: GPL-2.0 or MIT */ ++/* Copyright 2023 Collabora ltd. */ ++ ++#ifndef __PANTHOR_SCHED_H__ ++#define __PANTHOR_SCHED_H__ ++ ++struct drm_exec; ++struct dma_fence; ++struct drm_file; ++struct drm_gem_object; ++struct drm_sched_job; ++struct drm_panthor_group_create; ++struct drm_panthor_queue_create; ++struct drm_panthor_group_get_state; ++struct drm_panthor_queue_submit; ++struct panthor_device; ++struct panthor_file; ++struct panthor_group_pool; ++struct panthor_job; ++ ++int panthor_group_create(struct panthor_file *pfile, ++ const struct drm_panthor_group_create *group_args, ++ const struct drm_panthor_queue_create *queue_args); ++int panthor_group_destroy(struct panthor_file *pfile, u32 group_handle); ++int panthor_group_get_state(struct panthor_file *pfile, ++ struct drm_panthor_group_get_state *get_state); ++ ++struct drm_sched_job * ++panthor_job_create(struct panthor_file *pfile, ++ u16 group_handle, ++ const struct drm_panthor_queue_submit *qsubmit); ++struct drm_sched_job *panthor_job_get(struct drm_sched_job *job); ++struct panthor_vm *panthor_job_vm(struct drm_sched_job *sched_job); ++void panthor_job_put(struct drm_sched_job *job); ++void panthor_job_update_resvs(struct drm_exec *exec, struct drm_sched_job *job); ++ ++int panthor_group_pool_create(struct panthor_file *pfile); ++void panthor_group_pool_destroy(struct panthor_file *pfile); ++ ++int panthor_sched_init(struct panthor_device *ptdev); ++void panthor_sched_unplug(struct panthor_device *ptdev); ++void panthor_sched_pre_reset(struct panthor_device *ptdev); ++void panthor_sched_post_reset(struct panthor_device *ptdev); ++void panthor_sched_suspend(struct panthor_device *ptdev); ++void panthor_sched_resume(struct panthor_device *ptdev); ++ ++void panthor_sched_report_mmu_fault(struct panthor_device *ptdev); ++void panthor_sched_report_fw_events(struct panthor_device *ptdev, u32 events); ++ ++#endif +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:25 +0100 +Subject: drm/panthor: Add the driver frontend block + +This is the last piece missing to expose the driver to the outside +world. + +This is basically a wrapper between the ioctls and the other logical +blocks. + +v6: +- Add Maxime's and Heiko's acks +- Return a page-aligned BO size to userspace +- Keep header inclusion alphabetically ordered + +v5: +- Account for the drm_exec_init() prototype change +- Include platform_device.h + +v4: +- Add an ioctl to let the UMD query the VM state +- Fix kernel doc +- Let panthor_device_init() call panthor_device_init() +- Fix cleanup ordering in the panthor_init() error path +- Add Steve's and Liviu's R-b + +v3: +- Add acks for the MIT/GPL2 relicensing +- Fix 32-bit support +- Account for panthor_vm and panthor_sched changes +- Simplify the resv preparation/update logic +- Use a linked list rather than xarray for list of signals. +- Simplify panthor_get_uobj_array by returning the newly allocated + array. +- Drop the "DOC" for job submission helpers and move the relevant + comments to panthor_ioctl_group_submit(). +- Add helpers sync_op_is_signal()/sync_op_is_wait(). +- Simplify return type of panthor_submit_ctx_add_sync_signal() and + panthor_submit_ctx_get_sync_signal(). +- Drop WARN_ON from panthor_submit_ctx_add_job(). +- Fix typos in comments. + +Co-developed-by: Steven Price +Signed-off-by: Steven Price +Signed-off-by: Boris Brezillon +Acked-by: Steven Price # MIT+GPL2 relicensing,Arm +Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro +Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora +Reviewed-by: Steven Price +Reviewed-by: Liviu Dudau +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + drivers/gpu/drm/panthor/panthor_drv.c | 1473 ++++++++++ + 1 file changed, 1473 insertions(+) + +diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/panthor_drv.c +@@ -0,0 +1,1473 @@ ++// SPDX-License-Identifier: GPL-2.0 or MIT ++/* Copyright 2018 Marty E. Plummer */ ++/* Copyright 2019 Linaro, Ltd., Rob Herring */ ++/* Copyright 2019 Collabora ltd. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "panthor_device.h" ++#include "panthor_fw.h" ++#include "panthor_gem.h" ++#include "panthor_gpu.h" ++#include "panthor_heap.h" ++#include "panthor_mmu.h" ++#include "panthor_regs.h" ++#include "panthor_sched.h" ++ ++/** ++ * DOC: user <-> kernel object copy helpers. ++ */ ++ ++/** ++ * panthor_set_uobj() - Copy kernel object to user object. ++ * @usr_ptr: Users pointer. ++ * @usr_size: Size of the user object. ++ * @min_size: Minimum size for this object. ++ * @kern_size: Size of the kernel object. ++ * @in: Address of the kernel object to copy. ++ * ++ * Helper automating kernel -> user object copies. ++ * ++ * Don't use this function directly, use PANTHOR_UOBJ_SET() instead. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++static int ++panthor_set_uobj(u64 usr_ptr, u32 usr_size, u32 min_size, u32 kern_size, const void *in) ++{ ++ /* User size shouldn't be smaller than the minimal object size. */ ++ if (usr_size < min_size) ++ return -EINVAL; ++ ++ if (copy_to_user(u64_to_user_ptr(usr_ptr), in, min_t(u32, usr_size, kern_size))) ++ return -EFAULT; ++ ++ /* When the kernel object is smaller than the user object, we fill the gap with ++ * zeros. ++ */ ++ if (usr_size > kern_size && ++ clear_user(u64_to_user_ptr(usr_ptr + kern_size), usr_size - kern_size)) { ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++/** ++ * panthor_get_uobj_array() - Copy a user object array into a kernel accessible object array. ++ * @in: The object array to copy. ++ * @min_stride: Minimum array stride. ++ * @obj_size: Kernel object size. ++ * ++ * Helper automating user -> kernel object copies. ++ * ++ * Don't use this function directly, use PANTHOR_UOBJ_GET_ARRAY() instead. ++ * ++ * Return: newly allocated object array or an ERR_PTR on error. ++ */ ++static void * ++panthor_get_uobj_array(const struct drm_panthor_obj_array *in, u32 min_stride, ++ u32 obj_size) ++{ ++ int ret = 0; ++ void *out_alloc; ++ ++ /* User stride must be at least the minimum object size, otherwise it might ++ * lack useful information. ++ */ ++ if (in->stride < min_stride) ++ return ERR_PTR(-EINVAL); ++ ++ if (!in->count) ++ return NULL; ++ ++ out_alloc = kvmalloc_array(in->count, obj_size, GFP_KERNEL); ++ if (!out_alloc) ++ return ERR_PTR(-ENOMEM); ++ ++ if (obj_size == in->stride) { ++ /* Fast path when user/kernel have the same uAPI header version. */ ++ if (copy_from_user(out_alloc, u64_to_user_ptr(in->array), ++ (unsigned long)obj_size * in->count)) ++ ret = -EFAULT; ++ } else { ++ void __user *in_ptr = u64_to_user_ptr(in->array); ++ void *out_ptr = out_alloc; ++ ++ /* If the sizes differ, we need to copy elements one by one. */ ++ for (u32 i = 0; i < in->count; i++) { ++ ret = copy_struct_from_user(out_ptr, obj_size, in_ptr, in->stride); ++ if (ret) ++ break; ++ ++ out_ptr += obj_size; ++ in_ptr += in->stride; ++ } ++ } ++ ++ if (ret) { ++ kvfree(out_alloc); ++ return ERR_PTR(ret); ++ } ++ ++ return out_alloc; ++} ++ ++/** ++ * PANTHOR_UOBJ_MIN_SIZE_INTERNAL() - Get the minimum user object size ++ * @_typename: Object type. ++ * @_last_mandatory_field: Last mandatory field. ++ * ++ * Get the minimum user object size based on the last mandatory field name, ++ * A.K.A, the name of the last field of the structure at the time this ++ * structure was added to the uAPI. ++ * ++ * Don't use directly, use PANTHOR_UOBJ_DECL() instead. ++ */ ++#define PANTHOR_UOBJ_MIN_SIZE_INTERNAL(_typename, _last_mandatory_field) \ ++ (offsetof(_typename, _last_mandatory_field) + \ ++ sizeof(((_typename *)NULL)->_last_mandatory_field)) ++ ++/** ++ * PANTHOR_UOBJ_DECL() - Declare a new uAPI object whose subject to ++ * evolutions. ++ * @_typename: Object type. ++ * @_last_mandatory_field: Last mandatory field. ++ * ++ * Should be used to extend the PANTHOR_UOBJ_MIN_SIZE() list. ++ */ ++#define PANTHOR_UOBJ_DECL(_typename, _last_mandatory_field) \ ++ _typename : PANTHOR_UOBJ_MIN_SIZE_INTERNAL(_typename, _last_mandatory_field) ++ ++/** ++ * PANTHOR_UOBJ_MIN_SIZE() - Get the minimum size of a given uAPI object ++ * @_obj_name: Object to get the minimum size of. ++ * ++ * Don't use this macro directly, it's automatically called by ++ * PANTHOR_UOBJ_{SET,GET_ARRAY}(). ++ */ ++#define PANTHOR_UOBJ_MIN_SIZE(_obj_name) \ ++ _Generic(_obj_name, \ ++ PANTHOR_UOBJ_DECL(struct drm_panthor_gpu_info, tiler_present), \ ++ PANTHOR_UOBJ_DECL(struct drm_panthor_csif_info, pad), \ ++ PANTHOR_UOBJ_DECL(struct drm_panthor_sync_op, timeline_value), \ ++ PANTHOR_UOBJ_DECL(struct drm_panthor_queue_submit, syncs), \ ++ PANTHOR_UOBJ_DECL(struct drm_panthor_queue_create, ringbuf_size), \ ++ PANTHOR_UOBJ_DECL(struct drm_panthor_vm_bind_op, syncs)) ++ ++/** ++ * PANTHOR_UOBJ_SET() - Copy a kernel object to a user object. ++ * @_dest_usr_ptr: User pointer to copy to. ++ * @_usr_size: Size of the user object. ++ * @_src_obj: Kernel object to copy (not a pointer). ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++#define PANTHOR_UOBJ_SET(_dest_usr_ptr, _usr_size, _src_obj) \ ++ panthor_set_uobj(_dest_usr_ptr, _usr_size, \ ++ PANTHOR_UOBJ_MIN_SIZE(_src_obj), \ ++ sizeof(_src_obj), &(_src_obj)) ++ ++/** ++ * PANTHOR_UOBJ_GET_ARRAY() - Copy a user object array to a kernel accessible ++ * object array. ++ * @_dest_array: Local variable that will hold the newly allocated kernel ++ * object array. ++ * @_uobj_array: The drm_panthor_obj_array object describing the user object ++ * array. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++#define PANTHOR_UOBJ_GET_ARRAY(_dest_array, _uobj_array) \ ++ ({ \ ++ typeof(_dest_array) _tmp; \ ++ _tmp = panthor_get_uobj_array(_uobj_array, \ ++ PANTHOR_UOBJ_MIN_SIZE((_dest_array)[0]), \ ++ sizeof((_dest_array)[0])); \ ++ if (!IS_ERR(_tmp)) \ ++ _dest_array = _tmp; \ ++ PTR_ERR_OR_ZERO(_tmp); \ ++ }) ++ ++/** ++ * struct panthor_sync_signal - Represent a synchronization object point to attach ++ * our job fence to. ++ * ++ * This structure is here to keep track of fences that are currently bound to ++ * a specific syncobj point. ++ * ++ * At the beginning of a job submission, the fence ++ * is retrieved from the syncobj itself, and can be NULL if no fence was attached ++ * to this point. ++ * ++ * At the end, it points to the fence of the last job that had a ++ * %DRM_PANTHOR_SYNC_OP_SIGNAL on this syncobj. ++ * ++ * With jobs being submitted in batches, the fence might change several times during ++ * the process, allowing one job to wait on a job that's part of the same submission ++ * but appears earlier in the drm_panthor_group_submit::queue_submits array. ++ */ ++struct panthor_sync_signal { ++ /** @node: list_head to track signal ops within a submit operation */ ++ struct list_head node; ++ ++ /** @handle: The syncobj handle. */ ++ u32 handle; ++ ++ /** ++ * @point: The syncobj point. ++ * ++ * Zero for regular syncobjs, and non-zero for timeline syncobjs. ++ */ ++ u64 point; ++ ++ /** ++ * @syncobj: The sync object pointed by @handle. ++ */ ++ struct drm_syncobj *syncobj; ++ ++ /** ++ * @chain: Chain object used to link the new fence to an existing ++ * timeline syncobj. ++ * ++ * NULL for regular syncobj, non-NULL for timeline syncobjs. ++ */ ++ struct dma_fence_chain *chain; ++ ++ /** ++ * @fence: The fence to assign to the syncobj or syncobj-point. ++ */ ++ struct dma_fence *fence; ++}; ++ ++/** ++ * struct panthor_job_ctx - Job context ++ */ ++struct panthor_job_ctx { ++ /** @job: The job that is about to be submitted to drm_sched. */ ++ struct drm_sched_job *job; ++ ++ /** @syncops: Array of sync operations. */ ++ struct drm_panthor_sync_op *syncops; ++ ++ /** @syncop_count: Number of sync operations. */ ++ u32 syncop_count; ++}; ++ ++/** ++ * struct panthor_submit_ctx - Submission context ++ * ++ * Anything that's related to a submission (%DRM_IOCTL_PANTHOR_VM_BIND or ++ * %DRM_IOCTL_PANTHOR_GROUP_SUBMIT) is kept here, so we can automate the ++ * initialization and cleanup steps. ++ */ ++struct panthor_submit_ctx { ++ /** @file: DRM file this submission happens on. */ ++ struct drm_file *file; ++ ++ /** ++ * @signals: List of struct panthor_sync_signal. ++ * ++ * %DRM_PANTHOR_SYNC_OP_SIGNAL operations will be recorded here, ++ * and %DRM_PANTHOR_SYNC_OP_WAIT will first check if an entry ++ * matching the syncobj+point exists before calling ++ * drm_syncobj_find_fence(). This allows us to describe dependencies ++ * existing between jobs that are part of the same batch. ++ */ ++ struct list_head signals; ++ ++ /** @jobs: Array of jobs. */ ++ struct panthor_job_ctx *jobs; ++ ++ /** @job_count: Number of entries in the @jobs array. */ ++ u32 job_count; ++ ++ /** @exec: drm_exec context used to acquire and prepare resv objects. */ ++ struct drm_exec exec; ++}; ++ ++#define PANTHOR_SYNC_OP_FLAGS_MASK \ ++ (DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK | DRM_PANTHOR_SYNC_OP_SIGNAL) ++ ++static bool sync_op_is_signal(const struct drm_panthor_sync_op *sync_op) ++{ ++ return !!(sync_op->flags & DRM_PANTHOR_SYNC_OP_SIGNAL); ++} ++ ++static bool sync_op_is_wait(const struct drm_panthor_sync_op *sync_op) ++{ ++ /* Note that DRM_PANTHOR_SYNC_OP_WAIT == 0 */ ++ return !(sync_op->flags & DRM_PANTHOR_SYNC_OP_SIGNAL); ++} ++ ++/** ++ * panthor_check_sync_op() - Check drm_panthor_sync_op fields ++ * @sync_op: The sync operation to check. ++ * ++ * Return: 0 on success, -EINVAL otherwise. ++ */ ++static int ++panthor_check_sync_op(const struct drm_panthor_sync_op *sync_op) ++{ ++ u8 handle_type; ++ ++ if (sync_op->flags & ~PANTHOR_SYNC_OP_FLAGS_MASK) ++ return -EINVAL; ++ ++ handle_type = sync_op->flags & DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK; ++ if (handle_type != DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ && ++ handle_type != DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ) ++ return -EINVAL; ++ ++ if (handle_type == DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ && ++ sync_op->timeline_value != 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/** ++ * panthor_sync_signal_free() - Release resources and free a panthor_sync_signal object ++ * @sig_sync: Signal object to free. ++ */ ++static void ++panthor_sync_signal_free(struct panthor_sync_signal *sig_sync) ++{ ++ if (!sig_sync) ++ return; ++ ++ drm_syncobj_put(sig_sync->syncobj); ++ dma_fence_chain_free(sig_sync->chain); ++ dma_fence_put(sig_sync->fence); ++ kfree(sig_sync); ++} ++ ++/** ++ * panthor_submit_ctx_add_sync_signal() - Add a signal operation to a submit context ++ * @ctx: Context to add the signal operation to. ++ * @handle: Syncobj handle. ++ * @point: Syncobj point. ++ * ++ * Return: 0 on success, otherwise negative error value. ++ */ ++static int ++panthor_submit_ctx_add_sync_signal(struct panthor_submit_ctx *ctx, u32 handle, u64 point) ++{ ++ struct panthor_sync_signal *sig_sync; ++ struct dma_fence *cur_fence; ++ int ret; ++ ++ sig_sync = kzalloc(sizeof(*sig_sync), GFP_KERNEL); ++ if (!sig_sync) ++ return -ENOMEM; ++ ++ sig_sync->handle = handle; ++ sig_sync->point = point; ++ ++ if (point > 0) { ++ sig_sync->chain = dma_fence_chain_alloc(); ++ if (!sig_sync->chain) { ++ ret = -ENOMEM; ++ goto err_free_sig_sync; ++ } ++ } ++ ++ sig_sync->syncobj = drm_syncobj_find(ctx->file, handle); ++ if (!sig_sync->syncobj) { ++ ret = -EINVAL; ++ goto err_free_sig_sync; ++ } ++ ++ /* Retrieve the current fence attached to that point. It's ++ * perfectly fine to get a NULL fence here, it just means there's ++ * no fence attached to that point yet. ++ */ ++ if (!drm_syncobj_find_fence(ctx->file, handle, point, 0, &cur_fence)) ++ sig_sync->fence = cur_fence; ++ ++ list_add_tail(&sig_sync->node, &ctx->signals); ++ ++ return 0; ++ ++err_free_sig_sync: ++ panthor_sync_signal_free(sig_sync); ++ return ret; ++} ++ ++/** ++ * panthor_submit_ctx_search_sync_signal() - Search an existing signal operation in a ++ * submit context. ++ * @ctx: Context to search the signal operation in. ++ * @handle: Syncobj handle. ++ * @point: Syncobj point. ++ * ++ * Return: A valid panthor_sync_signal object if found, NULL otherwise. ++ */ ++static struct panthor_sync_signal * ++panthor_submit_ctx_search_sync_signal(struct panthor_submit_ctx *ctx, u32 handle, u64 point) ++{ ++ struct panthor_sync_signal *sig_sync; ++ ++ list_for_each_entry(sig_sync, &ctx->signals, node) { ++ if (handle == sig_sync->handle && point == sig_sync->point) ++ return sig_sync; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * panthor_submit_ctx_add_job() - Add a job to a submit context ++ * @ctx: Context to search the signal operation in. ++ * @idx: Index of the job in the context. ++ * @job: Job to add. ++ * @syncs: Sync operations provided by userspace. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++static int ++panthor_submit_ctx_add_job(struct panthor_submit_ctx *ctx, u32 idx, ++ struct drm_sched_job *job, ++ const struct drm_panthor_obj_array *syncs) ++{ ++ int ret; ++ ++ ctx->jobs[idx].job = job; ++ ++ ret = PANTHOR_UOBJ_GET_ARRAY(ctx->jobs[idx].syncops, syncs); ++ if (ret) ++ return ret; ++ ++ ctx->jobs[idx].syncop_count = syncs->count; ++ return 0; ++} ++ ++/** ++ * panthor_submit_ctx_get_sync_signal() - Search signal operation and add one if none was found. ++ * @ctx: Context to search the signal operation in. ++ * @handle: Syncobj handle. ++ * @point: Syncobj point. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++static int ++panthor_submit_ctx_get_sync_signal(struct panthor_submit_ctx *ctx, u32 handle, u64 point) ++{ ++ struct panthor_sync_signal *sig_sync; ++ ++ sig_sync = panthor_submit_ctx_search_sync_signal(ctx, handle, point); ++ if (sig_sync) ++ return 0; ++ ++ return panthor_submit_ctx_add_sync_signal(ctx, handle, point); ++} ++ ++/** ++ * panthor_submit_ctx_update_job_sync_signal_fences() - Update fences ++ * on the signal operations specified by a job. ++ * @ctx: Context to search the signal operation in. ++ * @job_idx: Index of the job to operate on. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++static int ++panthor_submit_ctx_update_job_sync_signal_fences(struct panthor_submit_ctx *ctx, ++ u32 job_idx) ++{ ++ struct panthor_device *ptdev = container_of(ctx->file->minor->dev, ++ struct panthor_device, ++ base); ++ struct dma_fence *done_fence = &ctx->jobs[job_idx].job->s_fence->finished; ++ const struct drm_panthor_sync_op *sync_ops = ctx->jobs[job_idx].syncops; ++ u32 sync_op_count = ctx->jobs[job_idx].syncop_count; ++ ++ for (u32 i = 0; i < sync_op_count; i++) { ++ struct dma_fence *old_fence; ++ struct panthor_sync_signal *sig_sync; ++ ++ if (!sync_op_is_signal(&sync_ops[i])) ++ continue; ++ ++ sig_sync = panthor_submit_ctx_search_sync_signal(ctx, sync_ops[i].handle, ++ sync_ops[i].timeline_value); ++ if (drm_WARN_ON(&ptdev->base, !sig_sync)) ++ return -EINVAL; ++ ++ old_fence = sig_sync->fence; ++ sig_sync->fence = dma_fence_get(done_fence); ++ dma_fence_put(old_fence); ++ ++ if (drm_WARN_ON(&ptdev->base, !sig_sync->fence)) ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * panthor_submit_ctx_collect_job_signal_ops() - Iterate over all job signal operations ++ * and add them to the context. ++ * @ctx: Context to search the signal operation in. ++ * @job_idx: Index of the job to operate on. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++static int ++panthor_submit_ctx_collect_job_signal_ops(struct panthor_submit_ctx *ctx, ++ u32 job_idx) ++{ ++ const struct drm_panthor_sync_op *sync_ops = ctx->jobs[job_idx].syncops; ++ u32 sync_op_count = ctx->jobs[job_idx].syncop_count; ++ ++ for (u32 i = 0; i < sync_op_count; i++) { ++ int ret; ++ ++ if (!sync_op_is_signal(&sync_ops[i])) ++ continue; ++ ++ ret = panthor_check_sync_op(&sync_ops[i]); ++ if (ret) ++ return ret; ++ ++ ret = panthor_submit_ctx_get_sync_signal(ctx, ++ sync_ops[i].handle, ++ sync_ops[i].timeline_value); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * panthor_submit_ctx_push_fences() - Iterate over the signal array, and for each entry, push ++ * the currently assigned fence to the associated syncobj. ++ * @ctx: Context to push fences on. ++ * ++ * This is the last step of a submission procedure, and is done once we know the submission ++ * is effective and job fences are guaranteed to be signaled in finite time. ++ */ ++static void ++panthor_submit_ctx_push_fences(struct panthor_submit_ctx *ctx) ++{ ++ struct panthor_sync_signal *sig_sync; ++ ++ list_for_each_entry(sig_sync, &ctx->signals, node) { ++ if (sig_sync->chain) { ++ drm_syncobj_add_point(sig_sync->syncobj, sig_sync->chain, ++ sig_sync->fence, sig_sync->point); ++ sig_sync->chain = NULL; ++ } else { ++ drm_syncobj_replace_fence(sig_sync->syncobj, sig_sync->fence); ++ } ++ } ++} ++ ++/** ++ * panthor_submit_ctx_add_sync_deps_to_job() - Add sync wait operations as ++ * job dependencies. ++ * @ctx: Submit context. ++ * @job_idx: Index of the job to operate on. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++static int ++panthor_submit_ctx_add_sync_deps_to_job(struct panthor_submit_ctx *ctx, ++ u32 job_idx) ++{ ++ struct panthor_device *ptdev = container_of(ctx->file->minor->dev, ++ struct panthor_device, ++ base); ++ const struct drm_panthor_sync_op *sync_ops = ctx->jobs[job_idx].syncops; ++ struct drm_sched_job *job = ctx->jobs[job_idx].job; ++ u32 sync_op_count = ctx->jobs[job_idx].syncop_count; ++ int ret = 0; ++ ++ for (u32 i = 0; i < sync_op_count; i++) { ++ struct panthor_sync_signal *sig_sync; ++ struct dma_fence *fence; ++ ++ if (!sync_op_is_wait(&sync_ops[i])) ++ continue; ++ ++ ret = panthor_check_sync_op(&sync_ops[i]); ++ if (ret) ++ return ret; ++ ++ sig_sync = panthor_submit_ctx_search_sync_signal(ctx, sync_ops[i].handle, ++ sync_ops[i].timeline_value); ++ if (sig_sync) { ++ if (drm_WARN_ON(&ptdev->base, !sig_sync->fence)) ++ return -EINVAL; ++ ++ fence = dma_fence_get(sig_sync->fence); ++ } else { ++ ret = drm_syncobj_find_fence(ctx->file, sync_ops[i].handle, ++ sync_ops[i].timeline_value, ++ 0, &fence); ++ if (ret) ++ return ret; ++ } ++ ++ ret = drm_sched_job_add_dependency(job, fence); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * panthor_submit_ctx_collect_jobs_signal_ops() - Collect all signal operations ++ * and add them to the submit context. ++ * @ctx: Submit context. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++static int ++panthor_submit_ctx_collect_jobs_signal_ops(struct panthor_submit_ctx *ctx) ++{ ++ for (u32 i = 0; i < ctx->job_count; i++) { ++ int ret; ++ ++ ret = panthor_submit_ctx_collect_job_signal_ops(ctx, i); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * panthor_submit_ctx_add_deps_and_arm_jobs() - Add jobs dependencies and arm jobs ++ * @ctx: Submit context. ++ * ++ * Must be called after the resv preparation has been taken care of. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++static int ++panthor_submit_ctx_add_deps_and_arm_jobs(struct panthor_submit_ctx *ctx) ++{ ++ for (u32 i = 0; i < ctx->job_count; i++) { ++ int ret; ++ ++ ret = panthor_submit_ctx_add_sync_deps_to_job(ctx, i); ++ if (ret) ++ return ret; ++ ++ drm_sched_job_arm(ctx->jobs[i].job); ++ ++ ret = panthor_submit_ctx_update_job_sync_signal_fences(ctx, i); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * panthor_submit_ctx_push_jobs() - Push jobs to their scheduling entities. ++ * @ctx: Submit context. ++ * @upd_resvs: Callback used to update reservation objects that were previously ++ * preapred. ++ */ ++static void ++panthor_submit_ctx_push_jobs(struct panthor_submit_ctx *ctx, ++ void (*upd_resvs)(struct drm_exec *, struct drm_sched_job *)) ++{ ++ for (u32 i = 0; i < ctx->job_count; i++) { ++ upd_resvs(&ctx->exec, ctx->jobs[i].job); ++ drm_sched_entity_push_job(ctx->jobs[i].job); ++ ++ /* Job is owned by the scheduler now. */ ++ ctx->jobs[i].job = NULL; ++ } ++ ++ panthor_submit_ctx_push_fences(ctx); ++} ++ ++/** ++ * panthor_submit_ctx_init() - Initializes a submission context ++ * @ctx: Submit context to initialize. ++ * @file: drm_file this submission happens on. ++ * @job_count: Number of jobs that will be submitted. ++ * ++ * Return: 0 on success, a negative error code otherwise. ++ */ ++static int panthor_submit_ctx_init(struct panthor_submit_ctx *ctx, ++ struct drm_file *file, u32 job_count) ++{ ++ ctx->jobs = kvmalloc_array(job_count, sizeof(*ctx->jobs), ++ GFP_KERNEL | __GFP_ZERO); ++ if (!ctx->jobs) ++ return -ENOMEM; ++ ++ ctx->file = file; ++ ctx->job_count = job_count; ++ INIT_LIST_HEAD(&ctx->signals); ++ drm_exec_init(&ctx->exec, ++ DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES, ++ 0); ++ return 0; ++} ++ ++/** ++ * panthor_submit_ctx_cleanup() - Cleanup a submission context ++ * @ctx: Submit context to cleanup. ++ * @job_put: Job put callback. ++ */ ++static void panthor_submit_ctx_cleanup(struct panthor_submit_ctx *ctx, ++ void (*job_put)(struct drm_sched_job *)) ++{ ++ struct panthor_sync_signal *sig_sync, *tmp; ++ unsigned long i; ++ ++ drm_exec_fini(&ctx->exec); ++ ++ list_for_each_entry_safe(sig_sync, tmp, &ctx->signals, node) ++ panthor_sync_signal_free(sig_sync); ++ ++ for (i = 0; i < ctx->job_count; i++) { ++ job_put(ctx->jobs[i].job); ++ kvfree(ctx->jobs[i].syncops); ++ } ++ ++ kvfree(ctx->jobs); ++} ++ ++static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct drm_file *file) ++{ ++ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); ++ struct drm_panthor_dev_query *args = data; ++ ++ if (!args->pointer) { ++ switch (args->type) { ++ case DRM_PANTHOR_DEV_QUERY_GPU_INFO: ++ args->size = sizeof(ptdev->gpu_info); ++ return 0; ++ ++ case DRM_PANTHOR_DEV_QUERY_CSIF_INFO: ++ args->size = sizeof(ptdev->csif_info); ++ return 0; ++ ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ switch (args->type) { ++ case DRM_PANTHOR_DEV_QUERY_GPU_INFO: ++ return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->gpu_info); ++ ++ case DRM_PANTHOR_DEV_QUERY_CSIF_INFO: ++ return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->csif_info); ++ ++ default: ++ return -EINVAL; ++ } ++} ++ ++#define PANTHOR_VM_CREATE_FLAGS 0 ++ ++static int panthor_ioctl_vm_create(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_vm_create *args = data; ++ int cookie, ret; ++ ++ if (!drm_dev_enter(ddev, &cookie)) ++ return -ENODEV; ++ ++ ret = panthor_vm_pool_create_vm(ptdev, pfile->vms, args); ++ if (ret >= 0) { ++ args->id = ret; ++ ret = 0; ++ } ++ ++ drm_dev_exit(cookie); ++ return ret; ++} ++ ++static int panthor_ioctl_vm_destroy(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_vm_destroy *args = data; ++ ++ if (args->pad) ++ return -EINVAL; ++ ++ return panthor_vm_pool_destroy_vm(pfile->vms, args->id); ++} ++ ++#define PANTHOR_BO_FLAGS DRM_PANTHOR_BO_NO_MMAP ++ ++static int panthor_ioctl_bo_create(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_bo_create *args = data; ++ struct panthor_vm *vm = NULL; ++ int cookie, ret; ++ ++ if (!drm_dev_enter(ddev, &cookie)) ++ return -ENODEV; ++ ++ if (!args->size || args->pad || ++ (args->flags & ~PANTHOR_BO_FLAGS)) { ++ ret = -EINVAL; ++ goto out_dev_exit; ++ } ++ ++ if (args->exclusive_vm_id) { ++ vm = panthor_vm_pool_get_vm(pfile->vms, args->exclusive_vm_id); ++ if (!vm) { ++ ret = -EINVAL; ++ goto out_dev_exit; ++ } ++ } ++ ++ ret = panthor_gem_create_with_handle(file, ddev, vm, &args->size, ++ args->flags, &args->handle); ++ ++ panthor_vm_put(vm); ++ ++out_dev_exit: ++ drm_dev_exit(cookie); ++ return ret; ++} ++ ++static int panthor_ioctl_bo_mmap_offset(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct drm_panthor_bo_mmap_offset *args = data; ++ struct drm_gem_object *obj; ++ int ret; ++ ++ if (args->pad) ++ return -EINVAL; ++ ++ obj = drm_gem_object_lookup(file, args->handle); ++ if (!obj) ++ return -ENOENT; ++ ++ ret = drm_gem_create_mmap_offset(obj); ++ if (ret) ++ goto out; ++ ++ args->offset = drm_vma_node_offset_addr(&obj->vma_node); ++ ++out: ++ drm_gem_object_put(obj); ++ return ret; ++} ++ ++static int panthor_ioctl_group_submit(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_group_submit *args = data; ++ struct drm_panthor_queue_submit *jobs_args; ++ struct panthor_submit_ctx ctx; ++ int ret = 0, cookie; ++ ++ if (args->pad) ++ return -EINVAL; ++ ++ if (!drm_dev_enter(ddev, &cookie)) ++ return -ENODEV; ++ ++ ret = PANTHOR_UOBJ_GET_ARRAY(jobs_args, &args->queue_submits); ++ if (ret) ++ goto out_dev_exit; ++ ++ ret = panthor_submit_ctx_init(&ctx, file, args->queue_submits.count); ++ if (ret) ++ goto out_free_jobs_args; ++ ++ /* Create jobs and attach sync operations */ ++ for (u32 i = 0; i < args->queue_submits.count; i++) { ++ const struct drm_panthor_queue_submit *qsubmit = &jobs_args[i]; ++ struct drm_sched_job *job; ++ ++ job = panthor_job_create(pfile, args->group_handle, qsubmit); ++ if (IS_ERR(job)) { ++ ret = PTR_ERR(job); ++ goto out_cleanup_submit_ctx; ++ } ++ ++ ret = panthor_submit_ctx_add_job(&ctx, i, job, &qsubmit->syncs); ++ if (ret) ++ goto out_cleanup_submit_ctx; ++ } ++ ++ /* ++ * Collect signal operations on all jobs, such that each job can pick ++ * from it for its dependencies and update the fence to signal when the ++ * job is submitted. ++ */ ++ ret = panthor_submit_ctx_collect_jobs_signal_ops(&ctx); ++ if (ret) ++ goto out_cleanup_submit_ctx; ++ ++ /* ++ * We acquire/prepare revs on all jobs before proceeding with the ++ * dependency registration. ++ * ++ * This is solving two problems: ++ * 1. drm_sched_job_arm() and drm_sched_entity_push_job() must be ++ * protected by a lock to make sure no concurrent access to the same ++ * entity get interleaved, which would mess up with the fence seqno ++ * ordering. Luckily, one of the resv being acquired is the VM resv, ++ * and a scheduling entity is only bound to a single VM. As soon as ++ * we acquire the VM resv, we should be safe. ++ * 2. Jobs might depend on fences that were issued by previous jobs in ++ * the same batch, so we can't add dependencies on all jobs before ++ * arming previous jobs and registering the fence to the signal ++ * array, otherwise we might miss dependencies, or point to an ++ * outdated fence. ++ */ ++ if (args->queue_submits.count > 0) { ++ /* All jobs target the same group, so they also point to the same VM. */ ++ struct panthor_vm *vm = panthor_job_vm(ctx.jobs[0].job); ++ ++ drm_exec_until_all_locked(&ctx.exec) { ++ ret = panthor_vm_prepare_mapped_bos_resvs(&ctx.exec, vm, ++ args->queue_submits.count); ++ } ++ ++ if (ret) ++ goto out_cleanup_submit_ctx; ++ } ++ ++ /* ++ * Now that resvs are locked/prepared, we can iterate over each job to ++ * add the dependencies, arm the job fence, register the job fence to ++ * the signal array. ++ */ ++ ret = panthor_submit_ctx_add_deps_and_arm_jobs(&ctx); ++ if (ret) ++ goto out_cleanup_submit_ctx; ++ ++ /* Nothing can fail after that point, so we can make our job fences ++ * visible to the outside world. Push jobs and set the job fences to ++ * the resv slots we reserved. This also pushes the fences to the ++ * syncobjs that are part of the signal array. ++ */ ++ panthor_submit_ctx_push_jobs(&ctx, panthor_job_update_resvs); ++ ++out_cleanup_submit_ctx: ++ panthor_submit_ctx_cleanup(&ctx, panthor_job_put); ++ ++out_free_jobs_args: ++ kvfree(jobs_args); ++ ++out_dev_exit: ++ drm_dev_exit(cookie); ++ return ret; ++} ++ ++static int panthor_ioctl_group_destroy(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_group_destroy *args = data; ++ ++ if (args->pad) ++ return -EINVAL; ++ ++ return panthor_group_destroy(pfile, args->group_handle); ++} ++ ++static int panthor_ioctl_group_create(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_group_create *args = data; ++ struct drm_panthor_queue_create *queue_args; ++ int ret; ++ ++ if (!args->queues.count) ++ return -EINVAL; ++ ++ ret = PANTHOR_UOBJ_GET_ARRAY(queue_args, &args->queues); ++ if (ret) ++ return ret; ++ ++ ret = panthor_group_create(pfile, args, queue_args); ++ if (ret >= 0) { ++ args->group_handle = ret; ++ ret = 0; ++ } ++ ++ kvfree(queue_args); ++ return ret; ++} ++ ++static int panthor_ioctl_group_get_state(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_group_get_state *args = data; ++ ++ return panthor_group_get_state(pfile, args); ++} ++ ++static int panthor_ioctl_tiler_heap_create(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_tiler_heap_create *args = data; ++ struct panthor_heap_pool *pool; ++ struct panthor_vm *vm; ++ int ret; ++ ++ vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); ++ if (!vm) ++ return -EINVAL; ++ ++ pool = panthor_vm_get_heap_pool(vm, true); ++ if (IS_ERR(pool)) { ++ ret = PTR_ERR(pool); ++ goto out_put_vm; ++ } ++ ++ ret = panthor_heap_create(pool, ++ args->initial_chunk_count, ++ args->chunk_size, ++ args->max_chunks, ++ args->target_in_flight, ++ &args->tiler_heap_ctx_gpu_va, ++ &args->first_heap_chunk_gpu_va); ++ if (ret < 0) ++ goto out_put_heap_pool; ++ ++ /* Heap pools are per-VM. We combine the VM and HEAP id to make ++ * a unique heap handle. ++ */ ++ args->handle = (args->vm_id << 16) | ret; ++ ret = 0; ++ ++out_put_heap_pool: ++ panthor_heap_pool_put(pool); ++ ++out_put_vm: ++ panthor_vm_put(vm); ++ return ret; ++} ++ ++static int panthor_ioctl_tiler_heap_destroy(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_tiler_heap_destroy *args = data; ++ struct panthor_heap_pool *pool; ++ struct panthor_vm *vm; ++ int ret; ++ ++ if (args->pad) ++ return -EINVAL; ++ ++ vm = panthor_vm_pool_get_vm(pfile->vms, args->handle >> 16); ++ if (!vm) ++ return -EINVAL; ++ ++ pool = panthor_vm_get_heap_pool(vm, false); ++ if (!pool) { ++ ret = -EINVAL; ++ goto out_put_vm; ++ } ++ ++ ret = panthor_heap_destroy(pool, args->handle & GENMASK(15, 0)); ++ panthor_heap_pool_put(pool); ++ ++out_put_vm: ++ panthor_vm_put(vm); ++ return ret; ++} ++ ++static int panthor_ioctl_vm_bind_async(struct drm_device *ddev, ++ struct drm_panthor_vm_bind *args, ++ struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_vm_bind_op *jobs_args; ++ struct panthor_submit_ctx ctx; ++ struct panthor_vm *vm; ++ int ret = 0; ++ ++ vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); ++ if (!vm) ++ return -EINVAL; ++ ++ ret = PANTHOR_UOBJ_GET_ARRAY(jobs_args, &args->ops); ++ if (ret) ++ goto out_put_vm; ++ ++ ret = panthor_submit_ctx_init(&ctx, file, args->ops.count); ++ if (ret) ++ goto out_free_jobs_args; ++ ++ for (u32 i = 0; i < args->ops.count; i++) { ++ struct drm_panthor_vm_bind_op *op = &jobs_args[i]; ++ struct drm_sched_job *job; ++ ++ job = panthor_vm_bind_job_create(file, vm, op); ++ if (IS_ERR(job)) { ++ ret = PTR_ERR(job); ++ goto out_cleanup_submit_ctx; ++ } ++ ++ ret = panthor_submit_ctx_add_job(&ctx, i, job, &op->syncs); ++ if (ret) ++ goto out_cleanup_submit_ctx; ++ } ++ ++ ret = panthor_submit_ctx_collect_jobs_signal_ops(&ctx); ++ if (ret) ++ goto out_cleanup_submit_ctx; ++ ++ /* Prepare reservation objects for each VM_BIND job. */ ++ drm_exec_until_all_locked(&ctx.exec) { ++ for (u32 i = 0; i < ctx.job_count; i++) { ++ ret = panthor_vm_bind_job_prepare_resvs(&ctx.exec, ctx.jobs[i].job); ++ drm_exec_retry_on_contention(&ctx.exec); ++ if (ret) ++ goto out_cleanup_submit_ctx; ++ } ++ } ++ ++ ret = panthor_submit_ctx_add_deps_and_arm_jobs(&ctx); ++ if (ret) ++ goto out_cleanup_submit_ctx; ++ ++ /* Nothing can fail after that point. */ ++ panthor_submit_ctx_push_jobs(&ctx, panthor_vm_bind_job_update_resvs); ++ ++out_cleanup_submit_ctx: ++ panthor_submit_ctx_cleanup(&ctx, panthor_vm_bind_job_put); ++ ++out_free_jobs_args: ++ kvfree(jobs_args); ++ ++out_put_vm: ++ panthor_vm_put(vm); ++ return ret; ++} ++ ++static int panthor_ioctl_vm_bind_sync(struct drm_device *ddev, ++ struct drm_panthor_vm_bind *args, ++ struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_vm_bind_op *jobs_args; ++ struct panthor_vm *vm; ++ int ret; ++ ++ vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); ++ if (!vm) ++ return -EINVAL; ++ ++ ret = PANTHOR_UOBJ_GET_ARRAY(jobs_args, &args->ops); ++ if (ret) ++ goto out_put_vm; ++ ++ for (u32 i = 0; i < args->ops.count; i++) { ++ ret = panthor_vm_bind_exec_sync_op(file, vm, &jobs_args[i]); ++ if (ret) { ++ /* Update ops.count so the user knows where things failed. */ ++ args->ops.count = i; ++ break; ++ } ++ } ++ ++ kvfree(jobs_args); ++ ++out_put_vm: ++ panthor_vm_put(vm); ++ return ret; ++} ++ ++#define PANTHOR_VM_BIND_FLAGS DRM_PANTHOR_VM_BIND_ASYNC ++ ++static int panthor_ioctl_vm_bind(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct drm_panthor_vm_bind *args = data; ++ int cookie, ret; ++ ++ if (!drm_dev_enter(ddev, &cookie)) ++ return -ENODEV; ++ ++ if (args->flags & DRM_PANTHOR_VM_BIND_ASYNC) ++ ret = panthor_ioctl_vm_bind_async(ddev, args, file); ++ else ++ ret = panthor_ioctl_vm_bind_sync(ddev, args, file); ++ ++ drm_dev_exit(cookie); ++ return ret; ++} ++ ++static int panthor_ioctl_vm_get_state(struct drm_device *ddev, void *data, ++ struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ struct drm_panthor_vm_get_state *args = data; ++ struct panthor_vm *vm; ++ ++ vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); ++ if (!vm) ++ return -EINVAL; ++ ++ if (panthor_vm_is_unusable(vm)) ++ args->state = DRM_PANTHOR_VM_STATE_UNUSABLE; ++ else ++ args->state = DRM_PANTHOR_VM_STATE_USABLE; ++ ++ panthor_vm_put(vm); ++ return 0; ++} ++ ++static int ++panthor_open(struct drm_device *ddev, struct drm_file *file) ++{ ++ struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); ++ struct panthor_file *pfile; ++ int ret; ++ ++ if (!try_module_get(THIS_MODULE)) ++ return -EINVAL; ++ ++ pfile = kzalloc(sizeof(*pfile), GFP_KERNEL); ++ if (!pfile) { ++ ret = -ENOMEM; ++ goto err_put_mod; ++ } ++ ++ pfile->ptdev = ptdev; ++ ++ ret = panthor_vm_pool_create(pfile); ++ if (ret) ++ goto err_free_file; ++ ++ ret = panthor_group_pool_create(pfile); ++ if (ret) ++ goto err_destroy_vm_pool; ++ ++ file->driver_priv = pfile; ++ return 0; ++ ++err_destroy_vm_pool: ++ panthor_vm_pool_destroy(pfile); ++ ++err_free_file: ++ kfree(pfile); ++ ++err_put_mod: ++ module_put(THIS_MODULE); ++ return ret; ++} ++ ++static void ++panthor_postclose(struct drm_device *ddev, struct drm_file *file) ++{ ++ struct panthor_file *pfile = file->driver_priv; ++ ++ panthor_group_pool_destroy(pfile); ++ panthor_vm_pool_destroy(pfile); ++ ++ kfree(pfile); ++ module_put(THIS_MODULE); ++} ++ ++static const struct drm_ioctl_desc panthor_drm_driver_ioctls[] = { ++#define PANTHOR_IOCTL(n, func, flags) \ ++ DRM_IOCTL_DEF_DRV(PANTHOR_##n, panthor_ioctl_##func, flags) ++ ++ PANTHOR_IOCTL(DEV_QUERY, dev_query, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(VM_CREATE, vm_create, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(VM_DESTROY, vm_destroy, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(VM_BIND, vm_bind, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(VM_GET_STATE, vm_get_state, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(BO_CREATE, bo_create, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(BO_MMAP_OFFSET, bo_mmap_offset, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(GROUP_CREATE, group_create, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(GROUP_DESTROY, group_destroy, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(GROUP_GET_STATE, group_get_state, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(TILER_HEAP_CREATE, tiler_heap_create, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(TILER_HEAP_DESTROY, tiler_heap_destroy, DRM_RENDER_ALLOW), ++ PANTHOR_IOCTL(GROUP_SUBMIT, group_submit, DRM_RENDER_ALLOW), ++}; ++ ++static int panthor_mmap(struct file *filp, struct vm_area_struct *vma) ++{ ++ struct drm_file *file = filp->private_data; ++ struct panthor_file *pfile = file->driver_priv; ++ struct panthor_device *ptdev = pfile->ptdev; ++ u64 offset = (u64)vma->vm_pgoff << PAGE_SHIFT; ++ int ret, cookie; ++ ++ if (!drm_dev_enter(file->minor->dev, &cookie)) ++ return -ENODEV; ++ ++ if (panthor_device_mmio_offset(offset) >= DRM_PANTHOR_USER_MMIO_OFFSET) ++ ret = panthor_device_mmap_io(ptdev, vma); ++ else ++ ret = drm_gem_mmap(filp, vma); ++ ++ drm_dev_exit(cookie); ++ return ret; ++} ++ ++static const struct file_operations panthor_drm_driver_fops = { ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .compat_ioctl = drm_compat_ioctl, ++ .poll = drm_poll, ++ .read = drm_read, ++ .llseek = noop_llseek, ++ .mmap = panthor_mmap, ++}; ++ ++#ifdef CONFIG_DEBUG_FS ++static void panthor_debugfs_init(struct drm_minor *minor) ++{ ++ panthor_mmu_debugfs_init(minor); ++} ++#endif ++ ++/* ++ * PanCSF driver version: ++ * - 1.0 - initial interface ++ */ ++static const struct drm_driver panthor_drm_driver = { ++ .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ | ++ DRIVER_SYNCOBJ_TIMELINE | DRIVER_GEM_GPUVA, ++ .open = panthor_open, ++ .postclose = panthor_postclose, ++ .ioctls = panthor_drm_driver_ioctls, ++ .num_ioctls = ARRAY_SIZE(panthor_drm_driver_ioctls), ++ .fops = &panthor_drm_driver_fops, ++ .name = "panthor", ++ .desc = "Panthor DRM driver", ++ .date = "20230801", ++ .major = 1, ++ .minor = 0, ++ ++ .gem_create_object = panthor_gem_create_object, ++ .gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table, ++#ifdef CONFIG_DEBUG_FS ++ .debugfs_init = panthor_debugfs_init, ++#endif ++}; ++ ++static int panthor_probe(struct platform_device *pdev) ++{ ++ struct panthor_device *ptdev; ++ ++ ptdev = devm_drm_dev_alloc(&pdev->dev, &panthor_drm_driver, ++ struct panthor_device, base); ++ if (!ptdev) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, ptdev); ++ ++ return panthor_device_init(ptdev); ++} ++ ++static void panthor_remove(struct platform_device *pdev) ++{ ++ struct panthor_device *ptdev = platform_get_drvdata(pdev); ++ ++ panthor_device_unplug(ptdev); ++} ++ ++static const struct of_device_id dt_match[] = { ++ { .compatible = "rockchip,rk3588-mali" }, ++ { .compatible = "arm,mali-valhall-csf" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, dt_match); ++ ++static DEFINE_RUNTIME_DEV_PM_OPS(panthor_pm_ops, ++ panthor_device_suspend, ++ panthor_device_resume, ++ NULL); ++ ++static struct platform_driver panthor_driver = { ++ .probe = panthor_probe, ++ .remove_new = panthor_remove, ++ .driver = { ++ .name = "panthor", ++ .pm = &panthor_pm_ops, ++ .of_match_table = dt_match, ++ }, ++}; ++ ++/* ++ * Workqueue used to cleanup stuff. ++ * ++ * We create a dedicated workqueue so we can drain on unplug and ++ * make sure all resources are freed before the module is unloaded. ++ */ ++struct workqueue_struct *panthor_cleanup_wq; ++ ++static int __init panthor_init(void) ++{ ++ int ret; ++ ++ ret = panthor_mmu_pt_cache_init(); ++ if (ret) ++ return ret; ++ ++ panthor_cleanup_wq = alloc_workqueue("panthor-cleanup", WQ_UNBOUND, 0); ++ if (!panthor_cleanup_wq) { ++ pr_err("panthor: Failed to allocate the workqueues"); ++ ret = -ENOMEM; ++ goto err_mmu_pt_cache_fini; ++ } ++ ++ ret = platform_driver_register(&panthor_driver); ++ if (ret) ++ goto err_destroy_cleanup_wq; ++ ++ return 0; ++ ++err_destroy_cleanup_wq: ++ destroy_workqueue(panthor_cleanup_wq); ++ ++err_mmu_pt_cache_fini: ++ panthor_mmu_pt_cache_fini(); ++ return ret; ++} ++module_init(panthor_init); ++ ++static void __exit panthor_exit(void) ++{ ++ platform_driver_unregister(&panthor_driver); ++ destroy_workqueue(panthor_cleanup_wq); ++ panthor_mmu_pt_cache_fini(); ++} ++module_exit(panthor_exit); ++ ++MODULE_AUTHOR("Panthor Project Developers"); ++MODULE_DESCRIPTION("Panthor DRM Driver"); ++MODULE_LICENSE("Dual MIT/GPL"); +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Thu, 29 Feb 2024 17:22:26 +0100 +Subject: drm/panthor: Allow driver compilation + +Now that all blocks are available, we can add/update Kconfig/Makefile +files to allow compilation. + +v6: +- Add Maxime's and Heiko's acks +- Keep source files alphabetically ordered in the Makefile + +v4: +- Add Steve's R-b + +v3: +- Add a dep on DRM_GPUVM +- Fix dependencies in Kconfig +- Expand help text to (hopefully) describe which GPUs are to be + supported by this driver and which are for panfrost. + +Co-developed-by: Steven Price +Signed-off-by: Steven Price +Signed-off-by: Boris Brezillon +Acked-by: Steven Price # MIT+GPL2 relicensing,Arm +Acked-by: Grant Likely # MIT+GPL2 relicensing,Linaro +Acked-by: Boris Brezillon # MIT+GPL2 relicensing,Collabora +Reviewed-by: Steven Price +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + drivers/gpu/drm/Kconfig | 2 + + drivers/gpu/drm/Makefile | 1 + + drivers/gpu/drm/panthor/Kconfig | 23 ++++++++++ + drivers/gpu/drm/panthor/Makefile | 14 ++++++ + 4 files changed, 40 insertions(+) + +diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/Kconfig ++++ b/drivers/gpu/drm/Kconfig +@@ -384,6 +384,8 @@ source "drivers/gpu/drm/lima/Kconfig" + + source "drivers/gpu/drm/panfrost/Kconfig" + ++source "drivers/gpu/drm/panthor/Kconfig" ++ + source "drivers/gpu/drm/aspeed/Kconfig" + + source "drivers/gpu/drm/mcde/Kconfig" +diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/Makefile ++++ b/drivers/gpu/drm/Makefile +@@ -179,6 +179,7 @@ obj-$(CONFIG_DRM_XEN) += xen/ + obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/ + obj-$(CONFIG_DRM_LIMA) += lima/ + obj-$(CONFIG_DRM_PANFROST) += panfrost/ ++obj-$(CONFIG_DRM_PANTHOR) += panthor/ + obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/ + obj-$(CONFIG_DRM_MCDE) += mcde/ + obj-$(CONFIG_DRM_TIDSS) += tidss/ +diff --git a/drivers/gpu/drm/panthor/Kconfig b/drivers/gpu/drm/panthor/Kconfig +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/Kconfig +@@ -0,0 +1,23 @@ ++# SPDX-License-Identifier: GPL-2.0 or MIT ++ ++config DRM_PANTHOR ++ tristate "Panthor (DRM support for ARM Mali CSF-based GPUs)" ++ depends on DRM ++ depends on ARM || ARM64 || COMPILE_TEST ++ depends on !GENERIC_ATOMIC64 # for IOMMU_IO_PGTABLE_LPAE ++ depends on MMU ++ select DEVFREQ_GOV_SIMPLE_ONDEMAND ++ select DRM_EXEC ++ select DRM_GEM_SHMEM_HELPER ++ select DRM_GPUVM ++ select DRM_SCHED ++ select IOMMU_IO_PGTABLE_LPAE ++ select IOMMU_SUPPORT ++ select PM_DEVFREQ ++ help ++ DRM driver for ARM Mali CSF-based GPUs. ++ ++ This driver is for Mali (or Immortalis) Valhall Gxxx GPUs. ++ ++ Note that the Mali-G68 and Mali-G78, while Valhall architecture, will ++ be supported with the panfrost driver as they are not CSF GPUs. +diff --git a/drivers/gpu/drm/panthor/Makefile b/drivers/gpu/drm/panthor/Makefile +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/drivers/gpu/drm/panthor/Makefile +@@ -0,0 +1,14 @@ ++# SPDX-License-Identifier: GPL-2.0 or MIT ++ ++panthor-y := \ ++ panthor_devfreq.o \ ++ panthor_device.o \ ++ panthor_drv.o \ ++ panthor_fw.o \ ++ panthor_gem.o \ ++ panthor_gpu.o \ ++ panthor_heap.o \ ++ panthor_mmu.o \ ++ panthor_sched.o ++ ++obj-$(CONFIG_DRM_PANTHOR) += panthor.o +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Liviu Dudau +Date: Thu, 29 Feb 2024 17:22:27 +0100 +Subject: dt-bindings: gpu: mali-valhall-csf: Add support for Arm Mali CSF GPUs + +Arm has introduced a new v10 GPU architecture that replaces the Job Manager +interface with a new Command Stream Frontend. It adds firmware driven +command stream queues that can be used by kernel and user space to submit +jobs to the GPU. + +Add the initial schema for the device tree that is based on support for +RK3588 SoC. The minimum number of clocks is one for the IP, but on Rockchip +platforms they will tend to expose the semi-independent clocks for better +power management. + +v6: +- Add Maxime's and Heiko's acks + +v5: +- Move the opp-table node under the gpu node + +v4: +- Fix formatting issue + +v3: +- Cleanup commit message to remove redundant text +- Added opp-table property and re-ordered entries +- Clarified power-domains and power-domain-names requirements for RK3588. +- Cleaned up example + +Note: power-domains and power-domain-names requirements for other platforms +are still work in progress, hence the bindings are left incomplete here. + +v2: +- New commit + +Signed-off-by: Liviu Dudau +Cc: Krzysztof Kozlowski +Cc: Rob Herring +Cc: Conor Dooley +Cc: devicetree@vger.kernel.org +Signed-off-by: Boris Brezillon +Reviewed-by: Rob Herring +Acked-by: Maxime Ripard +Acked-by: Heiko Stuebner +--- + Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml | 147 ++++++++++ + 1 file changed, 147 insertions(+) + +diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml +new file mode 100644 +index 000000000000..111111111111 +--- /dev/null ++++ b/Documentation/devicetree/bindings/gpu/arm,mali-valhall-csf.yaml +@@ -0,0 +1,147 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/gpu/arm,mali-valhall-csf.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: ARM Mali Valhall GPU ++ ++maintainers: ++ - Liviu Dudau ++ - Boris Brezillon ++ ++properties: ++ $nodename: ++ pattern: '^gpu@[a-f0-9]+$' ++ ++ compatible: ++ oneOf: ++ - items: ++ - enum: ++ - rockchip,rk3588-mali ++ - const: arm,mali-valhall-csf # Mali Valhall GPU model/revision is fully discoverable ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ items: ++ - description: Job interrupt ++ - description: MMU interrupt ++ - description: GPU interrupt ++ ++ interrupt-names: ++ items: ++ - const: job ++ - const: mmu ++ - const: gpu ++ ++ clocks: ++ minItems: 1 ++ maxItems: 3 ++ ++ clock-names: ++ minItems: 1 ++ items: ++ - const: core ++ - const: coregroup ++ - const: stacks ++ ++ mali-supply: true ++ ++ operating-points-v2: true ++ opp-table: ++ type: object ++ ++ power-domains: ++ minItems: 1 ++ maxItems: 5 ++ ++ power-domain-names: ++ minItems: 1 ++ maxItems: 5 ++ ++ sram-supply: true ++ ++ "#cooling-cells": ++ const: 2 ++ ++ dynamic-power-coefficient: ++ $ref: /schemas/types.yaml#/definitions/uint32 ++ description: ++ A u32 value that represents the running time dynamic ++ power coefficient in units of uW/MHz/V^2. The ++ coefficient can either be calculated from power ++ measurements or derived by analysis. ++ ++ The dynamic power consumption of the GPU is ++ proportional to the square of the Voltage (V) and ++ the clock frequency (f). The coefficient is used to ++ calculate the dynamic power as below - ++ ++ Pdyn = dynamic-power-coefficient * V^2 * f ++ ++ where voltage is in V, frequency is in MHz. ++ ++ dma-coherent: true ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - interrupt-names ++ - clocks ++ - mali-supply ++ ++additionalProperties: false ++ ++allOf: ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: rockchip,rk3588-mali ++ then: ++ properties: ++ clocks: ++ minItems: 3 ++ power-domains: ++ maxItems: 1 ++ power-domain-names: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ #include ++ ++ gpu: gpu@fb000000 { ++ compatible = "rockchip,rk3588-mali", "arm,mali-valhall-csf"; ++ reg = <0xfb000000 0x200000>; ++ interrupts = , ++ , ++ ; ++ interrupt-names = "job", "mmu", "gpu"; ++ clock-names = "core", "coregroup", "stacks"; ++ clocks = <&cru CLK_GPU>, <&cru CLK_GPU_COREGROUP>, ++ <&cru CLK_GPU_STACKS>; ++ power-domains = <&power RK3588_PD_GPU>; ++ operating-points-v2 = <&gpu_opp_table>; ++ mali-supply = <&vdd_gpu_s0>; ++ sram-supply = <&vdd_gpu_mem_s0>; ++ ++ gpu_opp_table: opp-table { ++ compatible = "operating-points-v2"; ++ opp-300000000 { ++ opp-hz = /bits/ 64 <300000000>; ++ opp-microvolt = <675000 675000 850000>; ++ }; ++ opp-400000000 { ++ opp-hz = /bits/ 64 <400000000>; ++ opp-microvolt = <675000 675000 850000>; ++ }; ++ }; ++ }; ++ ++... +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0142-arm64-dts-rockchip-rk3588-Add-GPU-nodes.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0142-arm64-dts-rockchip-rk3588-Add-GPU-nodes.patch new file mode 100644 index 000000000000..254db5782d60 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0142-arm64-dts-rockchip-rk3588-Add-GPU-nodes.patch @@ -0,0 +1,151 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Mon, 7 Aug 2023 17:30:58 +0200 +Subject: arm64: dts: rockchip: rk3588: Add GPU nodes + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 120 ++++++++++ + 1 file changed, 120 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -733,6 +733,121 @@ usb_host2_xhci: usb@fcd00000 { + status = "disabled"; + }; + ++ gpu_opp_table: gpu-opp-table { ++ compatible = "operating-points-v2"; ++ ++ nvmem-cells = <&gpu_leakage>; ++ nvmem-cell-names = "leakage"; ++ ++ rockchip,pvtm-voltage-sel = < ++ 0 815 0 ++ 816 835 1 ++ 836 860 2 ++ 861 885 3 ++ 886 910 4 ++ 911 9999 5 ++ >; ++ rockchip,pvtm-pvtpll; ++ rockchip,pvtm-offset = <0x1c>; ++ rockchip,pvtm-sample-time = <1100>; ++ rockchip,pvtm-freq = <800000>; ++ rockchip,pvtm-volt = <750000>; ++ rockchip,pvtm-ref-temp = <25>; ++ rockchip,pvtm-temp-prop = <(-135) (-135)>; ++ rockchip,pvtm-thermal-zone = "gpu-thermal"; ++ ++ clocks = <&cru CLK_GPU>; ++ clock-names = "clk"; ++ rockchip,grf = <&gpu_grf>; ++ volt-mem-read-margin = < ++ 855000 1 ++ 765000 2 ++ 675000 3 ++ 495000 4 ++ >; ++ low-volt-mem-read-margin = <4>; ++ intermediate-threshold-freq = <400000>; /* KHz */ ++ ++ rockchip,temp-hysteresis = <5000>; ++ rockchip,low-temp = <10000>; ++ rockchip,low-temp-min-volt = <750000>; ++ rockchip,high-temp = <85000>; ++ rockchip,high-temp-max-freq = <800000>; ++ ++ opp-300000000 { ++ opp-hz = /bits/ 64 <300000000>; ++ opp-microvolt = <675000 675000 850000>; ++ }; ++ opp-400000000 { ++ opp-hz = /bits/ 64 <400000000>; ++ opp-microvolt = <675000 675000 850000>; ++ }; ++ opp-500000000 { ++ opp-hz = /bits/ 64 <500000000>; ++ opp-microvolt = <675000 675000 850000>; ++ }; ++ opp-600000000 { ++ opp-hz = /bits/ 64 <600000000>; ++ opp-microvolt = <675000 675000 850000>; ++ }; ++ opp-700000000 { ++ opp-hz = /bits/ 64 <700000000>; ++ opp-microvolt = <700000 700000 850000>; ++ opp-microvolt-L2 = <687500 687500 850000>; ++ opp-microvolt-L3 = <675000 675000 850000>; ++ opp-microvolt-L4 = <675000 675000 850000>; ++ opp-microvolt-L5 = <675000 675000 850000>; ++ }; ++ opp-800000000 { ++ opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <750000 750000 850000>; ++ opp-microvolt-L1 = <737500 737500 850000>; ++ opp-microvolt-L2 = <725000 725000 850000>; ++ opp-microvolt-L3 = <712500 712500 850000>; ++ opp-microvolt-L4 = <700000 700000 850000>; ++ opp-microvolt-L5 = <700000 700000 850000>; ++ }; ++ opp-900000000 { ++ opp-hz = /bits/ 64 <900000000>; ++ opp-microvolt = <800000 800000 850000>; ++ opp-microvolt-L1 = <787500 787500 850000>; ++ opp-microvolt-L2 = <775000 775000 850000>; ++ opp-microvolt-L3 = <762500 762500 850000>; ++ opp-microvolt-L4 = <750000 750000 850000>; ++ opp-microvolt-L5 = <737500 737500 850000>; ++ }; ++ opp-1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <850000 850000 850000>; ++ opp-microvolt-L1 = <837500 837500 850000>; ++ opp-microvolt-L2 = <825000 825000 850000>; ++ opp-microvolt-L3 = <812500 812500 850000>; ++ opp-microvolt-L4 = <800000 800000 850000>; ++ opp-microvolt-L5 = <787500 787500 850000>; ++ }; ++ }; ++ ++ gpu: gpu@fb000000 { ++ compatible = "rockchip,rk3588-mali", "arm,mali-valhall-csf"; ++ reg = <0x0 0xfb000000 0x0 0x200000>; ++ interrupts = , ++ , ++ ; ++ interrupt-names = "job", "mmu", "gpu"; ++ ++ clock-names = "core", "coregroup", "stacks"; ++ clocks = <&cru CLK_GPU>, <&cru CLK_GPU_COREGROUP>, ++ <&cru CLK_GPU_STACKS>; ++ assigned-clocks = <&scmi_clk SCMI_CLK_GPU>; ++ assigned-clock-rates = <200000000>; ++ power-domains = <&power RK3588_PD_GPU>; ++ operating-points-v2 = <&gpu_opp_table>; ++ #cooling-cells = <2>; ++ dynamic-power-coefficient = <2982>; ++ ++ status = "disabled"; ++ }; ++ + pmu1grf: syscon@fd58a000 { + compatible = "rockchip,rk3588-pmugrf", "syscon", "simple-mfd"; + reg = <0x0 0xfd58a000 0x0 0x10000>; +@@ -3033,6 +3148,11 @@ gpio4: gpio@fec50000 { + }; + }; + ++ gpu_grf: syscon@fd5a0000 { ++ compatible = "rockchip,rk3588-gpu-grf", "syscon"; ++ reg = <0x0 0xfd5a0000 0x0 0x100>; ++ }; ++ + av1d: video-codec@fdc70000 { + compatible = "rockchip,rk3588-av1-vpu"; + reg = <0x0 0xfdc70000 0x0 0x800>; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch new file mode 100644 index 000000000000..edcf535b204f --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch @@ -0,0 +1,549 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Mon, 5 Feb 2024 01:38:48 +0200 +Subject: phy: phy-rockchip-samsung-hdptx: Add FRL & EARC support + +For upstreaming, this requires extending the standard PHY API to support +HDMI configuration options [1]. + +Currently, the bus_width PHY attribute is used to pass clock rate and +flags for 10-bit color depth, FRL and EARC. This is done by the HDMI +bridge driver via phy_set_bus_width(). + +[1]: https://lore.kernel.org/all/59d5595a24bbcca897e814440179fa2caf3dff38.1707040881.git.Sandor.yu@nxp.com/ + +Signed-off-by: Cristian Ciocaltea +--- + drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 434 +++++++++- + 1 file changed, 431 insertions(+), 3 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +index 111111111111..222222222222 100644 +--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c ++++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +@@ -190,6 +190,12 @@ + #define LN3_TX_SER_RATE_SEL_HBR2 BIT(3) + #define LN3_TX_SER_RATE_SEL_HBR3 BIT(2) + ++#define HDMI20_MAX_RATE 600000000 ++#define DATA_RATE_MASK 0xFFFFFFF ++#define COLOR_DEPTH_MASK BIT(31) ++#define HDMI_MODE_MASK BIT(30) ++#define HDMI_EARC_MASK BIT(29) ++ + struct lcpll_config { + u32 bit_rate; + u8 lcvco_mode_en; +@@ -272,6 +278,25 @@ struct rk_hdptx_phy { + struct clk_bulk_data *clks; + int nr_clks; + struct reset_control_bulk_data rsts[RST_MAX]; ++ bool earc_en; ++}; ++ ++static const struct lcpll_config lcpll_cfg[] = { ++ { 48000000, 1, 0, 0, 0x7d, 0x7d, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, ++ 0, 0x13, 0x18, 1, 0, 0x20, 0x0c, 1, 0, }, ++ { 40000000, 1, 1, 0, 0x68, 0x68, 1, 1, 0, 0, 0, 1, 1, 1, 1, 9, 0, 1, 1, ++ 0, 2, 3, 1, 0, 0x20, 0x0c, 1, 0, }, ++ { 32000000, 1, 1, 1, 0x6b, 0x6b, 1, 1, 0, 1, 2, 1, 1, 1, 1, 9, 1, 2, 1, ++ 0, 0x0d, 0x18, 1, 0, 0x20, 0x0c, 1, 1, }, ++}; ++ ++static const struct ropll_config ropll_frl_cfg[] = { ++ { 24000000, 0x19, 0x19, 1, 1, 0, 1, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, ++ 0, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 18000000, 0x7d, 0x7d, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, ++ 0, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, ++ { 9000000, 0x7d, 0x7d, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, ++ 0, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, }, + }; + + static const struct ropll_config ropll_tmds_cfg[] = { +@@ -449,6 +474,73 @@ static const struct reg_sequence rk_hdtpx_tmds_cmn_init_seq[] = { + REG_SEQ0(CMN_REG(009b), 0x00), + }; + ++static const struct reg_sequence rk_hdtpx_frl_cmn_init_seq[] = { ++ REG_SEQ0(CMN_REG(0011), 0x00), ++ REG_SEQ0(CMN_REG(0017), 0x00), ++ REG_SEQ0(CMN_REG(0026), 0x53), ++ REG_SEQ0(CMN_REG(0030), 0x00), ++ REG_SEQ0(CMN_REG(0031), 0x20), ++ REG_SEQ0(CMN_REG(0032), 0x30), ++ REG_SEQ0(CMN_REG(0033), 0x0b), ++ REG_SEQ0(CMN_REG(0034), 0x23), ++ REG_SEQ0(CMN_REG(0042), 0xb8), ++ REG_SEQ0(CMN_REG(004e), 0x14), ++ REG_SEQ0(CMN_REG(0074), 0x00), ++ REG_SEQ0(CMN_REG(0081), 0x09), ++ REG_SEQ0(CMN_REG(0086), 0x01), ++ REG_SEQ0(CMN_REG(0087), 0x0c), ++ REG_SEQ0(CMN_REG(009b), 0x10), ++}; ++ ++static const struct reg_sequence rk_hdtpx_frl_ropll_cmn_init_seq[] = { ++ REG_SEQ0(CMN_REG(0008), 0x00), ++ REG_SEQ0(CMN_REG(001e), 0x14), ++ REG_SEQ0(CMN_REG(0020), 0x00), ++ REG_SEQ0(CMN_REG(0021), 0x00), ++ REG_SEQ0(CMN_REG(0022), 0x11), ++ REG_SEQ0(CMN_REG(0023), 0x00), ++ REG_SEQ0(CMN_REG(0025), 0x00), ++ REG_SEQ0(CMN_REG(0027), 0x00), ++ REG_SEQ0(CMN_REG(0028), 0x00), ++ REG_SEQ0(CMN_REG(002a), 0x01), ++ REG_SEQ0(CMN_REG(002b), 0x00), ++ REG_SEQ0(CMN_REG(002c), 0x00), ++ REG_SEQ0(CMN_REG(002d), 0x00), ++ REG_SEQ0(CMN_REG(002e), 0x00), ++ REG_SEQ0(CMN_REG(002f), 0x04), ++ REG_SEQ0(CMN_REG(003d), 0x40), ++ REG_SEQ0(CMN_REG(005c), 0x25), ++ REG_SEQ0(CMN_REG(0089), 0x00), ++ REG_SEQ0(CMN_REG(0094), 0x00), ++ REG_SEQ0(CMN_REG(0097), 0x02), ++ REG_SEQ0(CMN_REG(0099), 0x04), ++}; ++ ++static const struct reg_sequence rk_hdtpx_frl_lcpll_cmn_init_seq[] = { ++ REG_SEQ0(CMN_REG(0025), 0x10), ++ REG_SEQ0(CMN_REG(0027), 0x01), ++ REG_SEQ0(CMN_REG(0028), 0x0d), ++ REG_SEQ0(CMN_REG(002e), 0x02), ++ REG_SEQ0(CMN_REG(002f), 0x0d), ++ REG_SEQ0(CMN_REG(003d), 0x00), ++ REG_SEQ0(CMN_REG(0051), 0x00), ++ REG_SEQ0(CMN_REG(0055), 0x00), ++ REG_SEQ0(CMN_REG(0059), 0x11), ++ REG_SEQ0(CMN_REG(005a), 0x03), ++ REG_SEQ0(CMN_REG(005c), 0x05), ++ REG_SEQ0(CMN_REG(005e), 0x07), ++ REG_SEQ0(CMN_REG(0060), 0x01), ++ REG_SEQ0(CMN_REG(0064), 0x07), ++ REG_SEQ0(CMN_REG(0065), 0x00), ++ REG_SEQ0(CMN_REG(0069), 0x00), ++ REG_SEQ0(CMN_REG(006c), 0x00), ++ REG_SEQ0(CMN_REG(0070), 0x01), ++ REG_SEQ0(CMN_REG(0089), 0x02), ++ REG_SEQ0(CMN_REG(0095), 0x00), ++ REG_SEQ0(CMN_REG(0097), 0x00), ++ REG_SEQ0(CMN_REG(0099), 0x00), ++}; ++ + static const struct reg_sequence rk_hdtpx_common_sb_init_seq[] = { + REG_SEQ0(SB_REG(0114), 0x00), + REG_SEQ0(SB_REG(0115), 0x00), +@@ -472,6 +564,17 @@ static const struct reg_sequence rk_hdtpx_tmds_lntop_lowbr_seq[] = { + REG_SEQ0(LNTOP_REG(0205), 0x1f), + }; + ++static const struct reg_sequence rk_hdtpx_frl_lntop_init_seq[] = { ++ REG_SEQ0(LNTOP_REG(0200), 0x04), ++ REG_SEQ0(LNTOP_REG(0201), 0x00), ++ REG_SEQ0(LNTOP_REG(0202), 0x00), ++ REG_SEQ0(LNTOP_REG(0203), 0xf0), ++ REG_SEQ0(LNTOP_REG(0204), 0xff), ++ REG_SEQ0(LNTOP_REG(0205), 0xff), ++ REG_SEQ0(LNTOP_REG(0206), 0x05), ++ REG_SEQ0(LNTOP_REG(0207), 0x0f), ++}; ++ + static const struct reg_sequence rk_hdtpx_common_lane_init_seq[] = { + REG_SEQ0(LANE_REG(0303), 0x0c), + REG_SEQ0(LANE_REG(0307), 0x20), +@@ -550,6 +653,40 @@ static const struct reg_sequence rk_hdtpx_tmds_lane_init_seq[] = { + REG_SEQ0(LANE_REG(0606), 0x1c), + }; + ++static const struct reg_sequence rk_hdtpx_frl_ropll_lane_init_seq[] = { ++ REG_SEQ0(LANE_REG(0312), 0x3c), ++ REG_SEQ0(LANE_REG(0412), 0x3c), ++ REG_SEQ0(LANE_REG(0512), 0x3c), ++ REG_SEQ0(LANE_REG(0612), 0x3c), ++}; ++ ++static const struct reg_sequence rk_hdtpx_frl_lcpll_lane_init_seq[] = { ++ REG_SEQ0(LANE_REG(0312), 0x3c), ++ REG_SEQ0(LANE_REG(0412), 0x3c), ++ REG_SEQ0(LANE_REG(0512), 0x3c), ++ REG_SEQ0(LANE_REG(0612), 0x3c), ++ REG_SEQ0(LANE_REG(0303), 0x2f), ++ REG_SEQ0(LANE_REG(0403), 0x2f), ++ REG_SEQ0(LANE_REG(0503), 0x2f), ++ REG_SEQ0(LANE_REG(0603), 0x2f), ++ REG_SEQ0(LANE_REG(0305), 0x03), ++ REG_SEQ0(LANE_REG(0405), 0x03), ++ REG_SEQ0(LANE_REG(0505), 0x03), ++ REG_SEQ0(LANE_REG(0605), 0x03), ++ REG_SEQ0(LANE_REG(0306), 0xfc), ++ REG_SEQ0(LANE_REG(0406), 0xfc), ++ REG_SEQ0(LANE_REG(0506), 0xfc), ++ REG_SEQ0(LANE_REG(0606), 0xfc), ++ REG_SEQ0(LANE_REG(0305), 0x4f), ++ REG_SEQ0(LANE_REG(0405), 0x4f), ++ REG_SEQ0(LANE_REG(0505), 0x4f), ++ REG_SEQ0(LANE_REG(0605), 0x4f), ++ REG_SEQ0(LANE_REG(0304), 0x14), ++ REG_SEQ0(LANE_REG(0404), 0x14), ++ REG_SEQ0(LANE_REG(0504), 0x14), ++ REG_SEQ0(LANE_REG(0604), 0x14), ++}; ++ + static bool rk_hdptx_phy_is_rw_reg(struct device *dev, unsigned int reg) + { + switch (reg) { +@@ -651,6 +788,47 @@ static int rk_hdptx_post_enable_pll(struct rk_hdptx_phy *hdptx) + return 0; + } + ++static int rk_hdptx_post_power_up(struct rk_hdptx_phy *hdptx) ++{ ++ u32 val; ++ int ret; ++ ++ val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 | ++ HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN; ++ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); ++ ++ usleep_range(10, 15); ++ reset_control_deassert(hdptx->rsts[RST_INIT].rstc); ++ ++ usleep_range(10, 15); ++ val = HDPTX_I_PLL_EN << 16 | HDPTX_I_PLL_EN; ++ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); ++ ++ usleep_range(10, 15); ++ reset_control_deassert(hdptx->rsts[RST_CMN].rstc); ++ ++ ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val, ++ val & HDPTX_O_PLL_LOCK_DONE, 20, 400); ++ if (ret) { ++ dev_err(hdptx->dev, "Failed to get PHY PLL lock: %d\n", ret); ++ return ret; ++ } ++ ++ usleep_range(20, 30); ++ reset_control_deassert(hdptx->rsts[RST_LANE].rstc); ++ ++ ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val, ++ val & HDPTX_O_PHY_RDY, 100, 5000); ++ if (ret) { ++ dev_err(hdptx->dev, "Failed to get PHY ready: %d\n", ret); ++ return ret; ++ } ++ ++ dev_dbg(hdptx->dev, "PHY ready\n"); ++ ++ return 0; ++} ++ + static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx) + { + u32 val; +@@ -680,6 +858,99 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx) + regmap_write(hdptx->grf, GRF_HDPTX_CON0, val); + } + ++static void rk_hdptx_earc_config(struct rk_hdptx_phy *hdptx) ++{ ++ regmap_update_bits(hdptx->regmap, SB_REG(0113), SB_RX_RCAL_OPT_CODE_MASK, ++ FIELD_PREP(SB_RX_RCAL_OPT_CODE_MASK, 1)); ++ regmap_write(hdptx->regmap, SB_REG(011c), 0x04); ++ regmap_update_bits(hdptx->regmap, SB_REG(011b), SB_AFC_TOL_MASK, ++ FIELD_PREP(SB_AFC_TOL_MASK, 3)); ++ regmap_write(hdptx->regmap, SB_REG(0109), 0x05); ++ ++ regmap_update_bits(hdptx->regmap, SB_REG(0120), ++ SB_EARC_EN_MASK | SB_EARC_AFC_EN_MASK, ++ FIELD_PREP(SB_EARC_EN_MASK, 1) | ++ FIELD_PREP(SB_EARC_AFC_EN_MASK, 1)); ++ regmap_update_bits(hdptx->regmap, SB_REG(011b), SB_EARC_SIG_DET_BYPASS_MASK, ++ FIELD_PREP(SB_EARC_SIG_DET_BYPASS_MASK, 1)); ++ regmap_update_bits(hdptx->regmap, SB_REG(011f), ++ SB_PWM_AFC_CTRL_MASK | SB_RCAL_RSTN_MASK, ++ FIELD_PREP(SB_PWM_AFC_CTRL_MASK, 0xc) | ++ FIELD_PREP(SB_RCAL_RSTN_MASK, 1)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0115), SB_READY_DELAY_TIME_MASK, ++ FIELD_PREP(SB_READY_DELAY_TIME_MASK, 2)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0113), SB_RX_RTERM_CTRL_MASK, ++ FIELD_PREP(SB_RX_RTERM_CTRL_MASK, 3)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0102), ANA_SB_RXTERM_OFFSP_MASK, ++ FIELD_PREP(ANA_SB_RXTERM_OFFSP_MASK, 3)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0103), ANA_SB_RXTERM_OFFSN_MASK, ++ FIELD_PREP(ANA_SB_RXTERM_OFFSN_MASK, 3)); ++ ++ regmap_write(hdptx->regmap, SB_REG(011a), 0x03); ++ regmap_write(hdptx->regmap, SB_REG(0118), 0x0a); ++ regmap_write(hdptx->regmap, SB_REG(011e), 0x6a); ++ regmap_write(hdptx->regmap, SB_REG(011d), 0x67); ++ ++ regmap_update_bits(hdptx->regmap, SB_REG(0117), FAST_PULSE_TIME_MASK, ++ FIELD_PREP(FAST_PULSE_TIME_MASK, 4)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0114), ++ SB_TG_SB_EN_DELAY_TIME_MASK | SB_TG_RXTERM_EN_DELAY_TIME_MASK, ++ FIELD_PREP(SB_TG_SB_EN_DELAY_TIME_MASK, 2) | ++ FIELD_PREP(SB_TG_RXTERM_EN_DELAY_TIME_MASK, 2)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0105), ANA_SB_TX_HLVL_PROG_MASK, ++ FIELD_PREP(ANA_SB_TX_HLVL_PROG_MASK, 7)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0106), ANA_SB_TX_LLVL_PROG_MASK, ++ FIELD_PREP(ANA_SB_TX_LLVL_PROG_MASK, 7)); ++ regmap_update_bits(hdptx->regmap, SB_REG(010f), ANA_SB_VREG_GAIN_CTRL_MASK, ++ FIELD_PREP(ANA_SB_VREG_GAIN_CTRL_MASK, 0)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0110), ANA_SB_VREG_REF_SEL_MASK, ++ FIELD_PREP(ANA_SB_VREG_REF_SEL_MASK, 1)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0115), SB_TG_OSC_EN_DELAY_TIME_MASK, ++ FIELD_PREP(SB_TG_OSC_EN_DELAY_TIME_MASK, 2)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0116), AFC_RSTN_DELAY_TIME_MASK, ++ FIELD_PREP(AFC_RSTN_DELAY_TIME_MASK, 2)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0109), ANA_SB_DMRX_AFC_DIV_RATIO_MASK, ++ FIELD_PREP(ANA_SB_DMRX_AFC_DIV_RATIO_MASK, 5)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0103), OVRD_SB_RX_RESCAL_DONE_MASK, ++ FIELD_PREP(OVRD_SB_RX_RESCAL_DONE_MASK, 1)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0104), OVRD_SB_EN_MASK, ++ FIELD_PREP(OVRD_SB_EN_MASK, 1)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0102), OVRD_SB_RXTERM_EN_MASK, ++ FIELD_PREP(OVRD_SB_RXTERM_EN_MASK, 1)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0105), OVRD_SB_EARC_CMDC_EN_MASK, ++ FIELD_PREP(OVRD_SB_EARC_CMDC_EN_MASK, 1)); ++ regmap_update_bits(hdptx->regmap, SB_REG(010f), ++ OVRD_SB_VREG_EN_MASK | OVRD_SB_VREG_LPF_BYPASS_MASK, ++ FIELD_PREP(OVRD_SB_VREG_EN_MASK, 1) | ++ FIELD_PREP(OVRD_SB_VREG_LPF_BYPASS_MASK, 1)); ++ regmap_update_bits(hdptx->regmap, SB_REG(0123), OVRD_SB_READY_MASK, ++ FIELD_PREP(OVRD_SB_READY_MASK, 1)); ++ ++ usleep_range(1000, 1100); ++ regmap_update_bits(hdptx->regmap, SB_REG(0103), SB_RX_RESCAL_DONE_MASK, ++ FIELD_PREP(SB_RX_RESCAL_DONE_MASK, 1)); ++ usleep_range(50, 60); ++ regmap_update_bits(hdptx->regmap, SB_REG(0104), SB_EN_MASK, ++ FIELD_PREP(SB_EN_MASK, 1)); ++ usleep_range(50, 60); ++ regmap_update_bits(hdptx->regmap, SB_REG(0102), SB_RXTERM_EN_MASK, ++ FIELD_PREP(SB_RXTERM_EN_MASK, 1)); ++ usleep_range(50, 60); ++ regmap_update_bits(hdptx->regmap, SB_REG(0105), SB_EARC_CMDC_EN_MASK, ++ FIELD_PREP(SB_EARC_CMDC_EN_MASK, 1)); ++ regmap_update_bits(hdptx->regmap, SB_REG(010f), SB_VREG_EN_MASK, ++ FIELD_PREP(SB_VREG_EN_MASK, 1)); ++ usleep_range(50, 60); ++ regmap_update_bits(hdptx->regmap, SB_REG(010f), OVRD_SB_VREG_LPF_BYPASS_MASK, ++ FIELD_PREP(OVRD_SB_VREG_LPF_BYPASS_MASK, 1)); ++ usleep_range(250, 300); ++ regmap_update_bits(hdptx->regmap, SB_REG(010f), OVRD_SB_VREG_LPF_BYPASS_MASK, ++ FIELD_PREP(OVRD_SB_VREG_LPF_BYPASS_MASK, 0)); ++ usleep_range(100, 120); ++ regmap_update_bits(hdptx->regmap, SB_REG(0123), SB_READY_MASK, ++ FIELD_PREP(SB_READY_MASK, 1)); ++} ++ + static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate, + struct ropll_config *cfg) + { +@@ -755,9 +1026,13 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate, + static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, + unsigned int rate) + { ++ int i, bus_width = phy_get_bus_width(hdptx->phy); ++ u8 color_depth = (bus_width & COLOR_DEPTH_MASK) ? 1 : 0; + const struct ropll_config *cfg = NULL; + struct ropll_config rc = {0}; +- int i; ++ ++ if (color_depth) ++ rate = rate * 10 / 8; + + for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) + if (rate == ropll_tmds_cfg[i].bit_rate) { +@@ -813,6 +1088,9 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, + regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK, + FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv)); + ++ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_SEL_MASK, ++ FIELD_PREP(PLL_PCG_CLK_SEL_MASK, color_depth)); ++ + regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN, + PLL_PCG_CLK_EN); + +@@ -853,9 +1131,146 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx, + rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_lane_init_seq); + rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lane_init_seq); + ++ if (hdptx->earc_en) ++ rk_hdptx_earc_config(hdptx); ++ + return rk_hdptx_post_enable_lane(hdptx); + } + ++static int rk_hdptx_ropll_frl_mode_config(struct rk_hdptx_phy *hdptx, ++ u32 bus_width) ++{ ++ u32 bit_rate = bus_width & DATA_RATE_MASK; ++ u8 color_depth = (bus_width & COLOR_DEPTH_MASK) ? 1 : 0; ++ const struct ropll_config *cfg = NULL; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ropll_frl_cfg); i++) ++ if (bit_rate == ropll_frl_cfg[i].bit_rate) { ++ cfg = &ropll_frl_cfg[i]; ++ break; ++ } ++ ++ if (!cfg) { ++ dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__); ++ return -EINVAL; ++ } ++ ++ rk_hdptx_pre_power_up(hdptx); ++ ++ reset_control_assert(hdptx->rsts[RST_ROPLL].rstc); ++ usleep_range(10, 20); ++ reset_control_deassert(hdptx->rsts[RST_ROPLL].rstc); ++ ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_cmn_init_seq); ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_cmn_init_seq); ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_ropll_cmn_init_seq); ++ ++ regmap_write(hdptx->regmap, CMN_REG(0051), cfg->pms_mdiv); ++ regmap_write(hdptx->regmap, CMN_REG(0055), cfg->pms_mdiv_afc); ++ regmap_write(hdptx->regmap, CMN_REG(0059), ++ (cfg->pms_pdiv << 4) | cfg->pms_refdiv); ++ regmap_write(hdptx->regmap, CMN_REG(005a), cfg->pms_sdiv << 4); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDM_EN_MASK, ++ FIELD_PREP(ROPLL_SDM_EN_MASK, cfg->sdm_en)); ++ if (!cfg->sdm_en) ++ regmap_update_bits(hdptx->regmap, CMN_REG(005e), 0xf, 0); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(0064), ROPLL_SDM_NUM_SIGN_RBR_MASK, ++ FIELD_PREP(ROPLL_SDM_NUM_SIGN_RBR_MASK, cfg->sdm_num_sign)); ++ ++ regmap_write(hdptx->regmap, CMN_REG(0060), cfg->sdm_deno); ++ regmap_write(hdptx->regmap, CMN_REG(0065), cfg->sdm_num); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(0069), ROPLL_SDC_N_RBR_MASK, ++ FIELD_PREP(ROPLL_SDC_N_RBR_MASK, cfg->sdc_n)); ++ ++ regmap_write(hdptx->regmap, CMN_REG(006c), cfg->sdc_num); ++ regmap_write(hdptx->regmap, CMN_REG(0070), cfg->sdc_deno); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK, ++ FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv)); ++ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_SEL_MASK, ++ FIELD_PREP(PLL_PCG_CLK_SEL_MASK, color_depth)); ++ ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq); ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_lntop_init_seq); ++ ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_lane_init_seq); ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_ropll_lane_init_seq); ++ ++ if (hdptx->earc_en) ++ rk_hdptx_earc_config(hdptx); ++ ++ return rk_hdptx_post_power_up(hdptx); ++} ++ ++static int rk_hdptx_lcpll_frl_mode_config(struct rk_hdptx_phy *hdptx, ++ u32 bus_width) ++{ ++ u32 bit_rate = bus_width & DATA_RATE_MASK; ++ u8 color_depth = (bus_width & COLOR_DEPTH_MASK) ? 1 : 0; ++ const struct lcpll_config *cfg = NULL; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(lcpll_cfg); i++) ++ if (bit_rate == lcpll_cfg[i].bit_rate) { ++ cfg = &lcpll_cfg[i]; ++ break; ++ } ++ ++ if (!cfg) { ++ dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__); ++ return -EINVAL; ++ } ++ ++ rk_hdptx_pre_power_up(hdptx); ++ ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_cmn_init_seq); ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_cmn_init_seq); ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_lcpll_cmn_init_seq); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(0008), ++ LCPLL_EN_MASK | LCPLL_LCVCO_MODE_EN_MASK, ++ FIELD_PREP(LCPLL_EN_MASK, 1) | ++ FIELD_PREP(LCPLL_LCVCO_MODE_EN_MASK, cfg->lcvco_mode_en)); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(001e), ++ LCPLL_PI_EN_MASK | LCPLL_100M_CLK_EN_MASK, ++ FIELD_PREP(LCPLL_PI_EN_MASK, cfg->pi_en) | ++ FIELD_PREP(LCPLL_100M_CLK_EN_MASK, cfg->clk_en_100m)); ++ ++ regmap_write(hdptx->regmap, CMN_REG(0020), cfg->pms_mdiv); ++ regmap_write(hdptx->regmap, CMN_REG(0021), cfg->pms_mdiv_afc); ++ regmap_write(hdptx->regmap, CMN_REG(0022), ++ (cfg->pms_pdiv << 4) | cfg->pms_refdiv); ++ regmap_write(hdptx->regmap, CMN_REG(0023), ++ (cfg->pms_sdiv << 4) | cfg->pms_sdiv); ++ regmap_write(hdptx->regmap, CMN_REG(002a), cfg->sdm_deno); ++ regmap_write(hdptx->regmap, CMN_REG(002b), cfg->sdm_num_sign); ++ regmap_write(hdptx->regmap, CMN_REG(002c), cfg->sdm_num); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(002d), LCPLL_SDC_N_MASK, ++ FIELD_PREP(LCPLL_SDC_N_MASK, cfg->sdc_n)); ++ ++ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK, ++ FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv)); ++ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_SEL_MASK, ++ FIELD_PREP(PLL_PCG_CLK_SEL_MASK, color_depth)); ++ ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq); ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_lntop_init_seq); ++ ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_lane_init_seq); ++ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_frl_lcpll_lane_init_seq); ++ ++ if (hdptx->earc_en) ++ rk_hdptx_earc_config(hdptx); ++ ++ return rk_hdptx_post_power_up(hdptx); ++} ++ + static int rk_hdptx_phy_power_on(struct phy *phy) + { + struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); +@@ -865,7 +1280,7 @@ static int rk_hdptx_phy_power_on(struct phy *phy) + * from the HDMI bridge driver until phy_configure_opts_hdmi + * becomes available in the PHY API. + */ +- unsigned int rate = bus_width & 0xfffffff; ++ unsigned int rate = bus_width & DATA_RATE_MASK; + + dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n", + __func__, bus_width, rate); +@@ -876,7 +1291,20 @@ static int rk_hdptx_phy_power_on(struct phy *phy) + return ret; + } + +- ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate); ++ if (bus_width & HDMI_EARC_MASK) ++ hdptx->earc_en = true; ++ else ++ hdptx->earc_en = false; ++ ++ if (bus_width & HDMI_MODE_MASK) { ++ if (rate > 24000000) ++ ret = rk_hdptx_lcpll_frl_mode_config(hdptx, bus_width); ++ else ++ ret = rk_hdptx_ropll_frl_mode_config(hdptx, bus_width); ++ } else { ++ ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate); ++ } ++ + if (ret) + pm_runtime_put(hdptx->dev); + +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch new file mode 100644 index 000000000000..43173de65136 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch @@ -0,0 +1,222 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Tue, 16 Jan 2024 19:27:40 +0200 +Subject: phy: phy-rockchip-samsung-hdptx: Add clock provider + +The HDMI PHY PLL can be used as an alternative dclk source to SoC CRU. +It provides more accurate clock rates required to properly support +various display modes, e.g. those relying on non-integer refresh rates. + +Also note this only works for HDMI 2.0 or bellow, e.g. cannot be used to +support HDMI 2.1 4K@120Hz mode. + +Signed-off-by: Cristian Ciocaltea +--- + drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 148 +++++++++- + 1 file changed, 143 insertions(+), 5 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +index 111111111111..222222222222 100644 +--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c ++++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +@@ -8,6 +8,7 @@ + */ + #include + #include ++#include + #include + #include + #include +@@ -279,6 +280,12 @@ struct rk_hdptx_phy { + int nr_clks; + struct reset_control_bulk_data rsts[RST_MAX]; + bool earc_en; ++ ++ /* clk provider */ ++ struct clk_hw hw; ++ unsigned long rate; ++ int id; ++ int count; + }; + + static const struct lcpll_config lcpll_cfg[] = { +@@ -1031,6 +1038,8 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx, + const struct ropll_config *cfg = NULL; + struct ropll_config rc = {0}; + ++ hdptx->rate = rate * 100; ++ + if (color_depth) + rate = rate * 10 / 8; + +@@ -1315,11 +1324,13 @@ static int rk_hdptx_phy_power_off(struct phy *phy) + { + struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy); + u32 val; +- int ret; ++ int ret = 0; + +- ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); +- if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) +- rk_hdptx_phy_disable(hdptx); ++ if (hdptx->count == 0) { ++ ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); ++ if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) ++ rk_hdptx_phy_disable(hdptx); ++ } + + pm_runtime_put(hdptx->dev); + +@@ -1332,6 +1343,129 @@ static const struct phy_ops rk_hdptx_phy_ops = { + .owner = THIS_MODULE, + }; + ++static struct rk_hdptx_phy *to_rk_hdptx_phy(struct clk_hw *hw) ++{ ++ return container_of(hw, struct rk_hdptx_phy, hw); ++} ++ ++static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw) ++{ ++ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(hdptx->dev); ++ if (ret) { ++ dev_err(hdptx->dev, "Failed to resume phy clk: %d\n", ret); ++ return ret; ++ } ++ ++ if (!hdptx->count && hdptx->rate) { ++ ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, hdptx->rate / 100); ++ if (ret < 0) { ++ dev_err(hdptx->dev, "Failed to init PHY PLL: %d\n", ret); ++ pm_runtime_put(hdptx->dev); ++ return ret; ++ } ++ } ++ ++ hdptx->count++; ++ ++ return 0; ++} ++ ++static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw) ++{ ++ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); ++ ++ if (hdptx->count == 1) { ++ u32 val; ++ int ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); ++ if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) ++ rk_hdptx_phy_disable(hdptx); ++ } ++ ++ hdptx->count--; ++ pm_runtime_put(hdptx->dev); ++} ++ ++static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); ++ ++ return hdptx->rate; ++} ++ ++static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ const struct ropll_config *cfg = NULL; ++ u32 bit_rate = rate / 100; ++ int i; ++ ++ if (rate > HDMI20_MAX_RATE) ++ return rate; ++ ++ for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++) ++ if (bit_rate == ropll_tmds_cfg[i].bit_rate) { ++ cfg = &ropll_tmds_cfg[i]; ++ break; ++ } ++ ++ if (!cfg && !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL)) ++ return -EINVAL; ++ ++ return rate; ++} ++ ++static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw); ++ u32 val; ++ int ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &val); ++ if (ret == 0 && (val & HDPTX_O_PLL_LOCK_DONE)) ++ rk_hdptx_phy_disable(hdptx); ++ ++ return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100); ++} ++ ++static const struct clk_ops hdptx_phy_clk_ops = { ++ .prepare = rk_hdptx_phy_clk_prepare, ++ .unprepare = rk_hdptx_phy_clk_unprepare, ++ .recalc_rate = rk_hdptx_phy_clk_recalc_rate, ++ .round_rate = rk_hdptx_phy_clk_round_rate, ++ .set_rate = rk_hdptx_phy_clk_set_rate, ++}; ++ ++static int rk_hdptx_phy_clk_register(struct rk_hdptx_phy *hdptx) ++{ ++ struct device *dev = hdptx->dev; ++ const char *name, *pname; ++ struct clk *refclk; ++ int ret; ++ ++ refclk = devm_clk_get(dev, "ref"); ++ if (IS_ERR(refclk)) ++ return dev_err_probe(dev, PTR_ERR(refclk), ++ "Failed to get ref clock\n"); ++ ++ pname = __clk_get_name(refclk); ++ name = hdptx->id ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0"; ++ hdptx->hw.init = CLK_HW_INIT(name, pname, &hdptx_phy_clk_ops, ++ CLK_GET_RATE_NOCACHE); ++ ++ ret = devm_clk_hw_register(dev, &hdptx->hw); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to register clock\n"); ++ ++ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &hdptx->hw); ++ if (ret) ++ return dev_err_probe(dev, ret, ++ "Failed to register clk provider\n"); ++ return 0; ++} ++ + static int rk_hdptx_phy_runtime_suspend(struct device *dev) + { + struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev); +@@ -1367,6 +1501,10 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) + + hdptx->dev = dev; + ++ hdptx->id = of_alias_get_id(dev->of_node, "hdptxphy"); ++ if (hdptx->id < 0) ++ hdptx->id = 0; ++ + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return dev_err_probe(dev, PTR_ERR(regs), +@@ -1426,7 +1564,7 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev) + reset_control_deassert(hdptx->rsts[RST_CMN].rstc); + reset_control_deassert(hdptx->rsts[RST_INIT].rstc); + +- return 0; ++ return rk_hdptx_phy_clk_register(hdptx); + } + + static const struct dev_pm_ops rk_hdptx_phy_pm_ops = { +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch new file mode 100644 index 000000000000..ca6f5d4b6ffc --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch @@ -0,0 +1,679 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Fri, 3 Nov 2023 19:58:02 +0200 +Subject: drm/rockchip: vop2: Improve display modes handling on rk3588 + +The initial vop2 support for rk3588 in mainline is not able to handle +all display modes supported by connected displays, e.g. +2560x1440-75.00Hz, 2048x1152-60.00Hz, 1024x768-60.00Hz. + +Additionally, it doesn't cope with non-integer refresh rates like 59.94, +29.97, 23.98, etc. + +Improve HDMI0 clocking in order to support the additional display modes. + +Fixes: 5a028e8f062f ("drm/rockchip: vop2: Add support for rk3588") +Signed-off-by: Cristian Ciocaltea +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 553 +++++++++- + 1 file changed, 552 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +@@ -5,6 +5,8 @@ + */ + #include + #include ++#include ++#include + #include + #include + #include +@@ -212,6 +214,10 @@ struct vop2 { + struct clk *hclk; + struct clk *aclk; + struct clk *pclk; ++ // [CC:] hack to support additional display modes ++ struct clk *hdmi0_phy_pll; ++ /* list_head of internal clk */ ++ struct list_head clk_list_head; + + /* optional internal rgb encoder */ + struct rockchip_rgb *rgb; +@@ -220,6 +226,19 @@ struct vop2 { + struct vop2_win win[]; + }; + ++struct vop2_clk { ++ struct vop2 *vop2; ++ struct list_head list; ++ unsigned long rate; ++ struct clk_hw hw; ++ struct clk_divider div; ++ int div_val; ++ u8 parent_index; ++}; ++ ++#define to_vop2_clk(_hw) container_of(_hw, struct vop2_clk, hw) ++#define VOP2_MAX_DCLK_RATE 600000 /* kHz */ ++ + #define vop2_output_if_is_hdmi(x) ((x) == ROCKCHIP_VOP2_EP_HDMI0 || \ + (x) == ROCKCHIP_VOP2_EP_HDMI1) + +@@ -1476,9 +1495,30 @@ static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adj_mode) + { ++ struct vop2_video_port *vp = to_vop2_video_port(crtc); ++ struct drm_connector *connector; ++ struct drm_connector_list_iter conn_iter; ++ struct drm_crtc_state *new_crtc_state = container_of(mode, struct drm_crtc_state, mode); + drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V | + CRTC_STEREO_DOUBLE); + ++ if (mode->flags & DRM_MODE_FLAG_DBLCLK) ++ adj_mode->crtc_clock *= 2; ++ ++ drm_connector_list_iter_begin(crtc->dev, &conn_iter); ++ drm_for_each_connector_iter(connector, &conn_iter) { ++ if ((new_crtc_state->connector_mask & drm_connector_mask(connector)) && ++ ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) || ++ (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA))) { ++ drm_connector_list_iter_end(&conn_iter); ++ return true; ++ } ++ } ++ drm_connector_list_iter_end(&conn_iter); ++ ++ if (adj_mode->crtc_clock <= VOP2_MAX_DCLK_RATE) ++ adj_mode->crtc_clock = DIV_ROUND_UP(clk_round_rate(vp->dclk, ++ adj_mode->crtc_clock * 1000), 1000); + return true; + } + +@@ -1663,6 +1703,31 @@ static unsigned long rk3588_calc_dclk(unsigned long child_clk, unsigned long max + return 0; + } + ++static struct vop2_clk *vop2_clk_get(struct vop2 *vop2, const char *name); ++ ++static int vop2_cru_set_rate(struct vop2_clk *if_pixclk, struct vop2_clk *if_dclk) ++{ ++ int ret = 0; ++ ++ if (if_pixclk) { ++ ret = clk_set_rate(if_pixclk->hw.clk, if_pixclk->rate); ++ if (ret < 0) { ++ DRM_DEV_ERROR(if_pixclk->vop2->dev, "set %s to %ld failed: %d\n", ++ clk_hw_get_name(&if_pixclk->hw), if_pixclk->rate, ret); ++ return ret; ++ } ++ } ++ ++ if (if_dclk) { ++ ret = clk_set_rate(if_dclk->hw.clk, if_dclk->rate); ++ if (ret < 0) ++ DRM_DEV_ERROR(if_dclk->vop2->dev, "set %s to %ld failed %d\n", ++ clk_hw_get_name(&if_dclk->hw), if_dclk->rate, ret); ++ } ++ ++ return ret; ++} ++ + /* + * 4 pixclk/cycle on rk3588 + * RGB/eDP/HDMI: if_pixclk >= dclk_core +@@ -1686,6 +1751,72 @@ static unsigned long rk3588_calc_cru_cfg(struct vop2_video_port *vp, int id, + int K = 1; + + if (vop2_output_if_is_hdmi(id)) { ++ if (vop2->data->soc_id == 3588 && id == ROCKCHIP_VOP2_EP_HDMI0 && ++ vop2->hdmi0_phy_pll) { ++ const char *clk_src_name = "hdmi_edp0_clk_src"; ++ const char *clk_parent_name = "dclk"; ++ const char *pixclk_name = "hdmi_edp0_pixclk"; ++ const char *dclk_name = "hdmi_edp0_dclk"; ++ struct vop2_clk *if_clk_src, *if_clk_parent, *if_pixclk, *if_dclk, *dclk, *dclk_core, *dclk_out; ++ char clk_name[32]; ++ int ret; ++ ++ if_clk_src = vop2_clk_get(vop2, clk_src_name); ++ snprintf(clk_name, sizeof(clk_name), "%s%d", clk_parent_name, vp->id); ++ if_clk_parent = vop2_clk_get(vop2, clk_name); ++ if_pixclk = vop2_clk_get(vop2, pixclk_name); ++ if_dclk = vop2_clk_get(vop2, dclk_name); ++ if (!if_pixclk || !if_clk_parent) { ++ DRM_DEV_ERROR(vop2->dev, "failed to get connector interface clk\n"); ++ return -ENODEV; ++ } ++ ++ ret = clk_set_parent(if_clk_src->hw.clk, if_clk_parent->hw.clk); ++ if (ret < 0) { ++ DRM_DEV_ERROR(vop2->dev, "failed to set parent(%s) for %s: %d\n", ++ __clk_get_name(if_clk_parent->hw.clk), ++ __clk_get_name(if_clk_src->hw.clk), ret); ++ return ret; ++ } ++ ++ if (output_mode == ROCKCHIP_OUT_MODE_YUV420) ++ K = 2; ++ ++ if_pixclk->rate = (dclk_core_rate << 1) / K; ++ if_dclk->rate = dclk_core_rate / K; ++ ++ snprintf(clk_name, sizeof(clk_name), "dclk_core%d", vp->id); ++ dclk_core = vop2_clk_get(vop2, clk_name); ++ ++ snprintf(clk_name, sizeof(clk_name), "dclk_out%d", vp->id); ++ dclk_out = vop2_clk_get(vop2, clk_name); ++ ++ snprintf(clk_name, sizeof(clk_name), "dclk%d", vp->id); ++ dclk = vop2_clk_get(vop2, clk_name); ++ if (v_pixclk <= (VOP2_MAX_DCLK_RATE * 1000)) { ++ if (output_mode == ROCKCHIP_OUT_MODE_YUV420) ++ v_pixclk = v_pixclk >> 1; ++ } else { ++ v_pixclk = v_pixclk >> 2; ++ } ++ clk_set_rate(dclk->hw.clk, v_pixclk); ++ ++ if (dclk_core_rate > if_pixclk->rate) { ++ clk_set_rate(dclk_core->hw.clk, dclk_core_rate); ++ ret = vop2_cru_set_rate(if_pixclk, if_dclk); ++ } else { ++ ret = vop2_cru_set_rate(if_pixclk, if_dclk); ++ clk_set_rate(dclk_core->hw.clk, dclk_core_rate); ++ } ++ ++ *dclk_core_div = dclk_core->div_val; ++ *dclk_out_div = dclk_out->div_val; ++ *if_pixclk_div = if_pixclk->div_val; ++ *if_dclk_div = if_dclk->div_val; ++ ++ return dclk->rate; ++ } ++ + /* + * K = 2: dclk_core = if_pixclk_rate > if_dclk_rate + * K = 1: dclk_core = hdmie_edp_dclk > if_pixclk_rate +@@ -1917,6 +2048,22 @@ static int us_to_vertical_line(struct drm_display_mode *mode, int us) + return us * mode->clock / mode->htotal / 1000; + } + ++// [CC:] rework virtual clock ++static struct vop2_clk *vop2_clk_get(struct vop2 *vop2, const char *name) ++{ ++ struct vop2_clk *clk, *n; ++ ++ if (!name) ++ return NULL; ++ ++ list_for_each_entry_safe(clk, n, &vop2->clk_list_head, list) { ++ if (!strcmp(clk_hw_get_name(&clk->hw), name)) ++ return clk; ++ } ++ ++ return NULL; ++} ++ + static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *state) + { +@@ -1944,6 +2091,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, + u32 val, polflags; + int ret; + struct drm_encoder *encoder; ++ char clk_name[32]; ++ struct vop2_clk *dclk; + + drm_dbg(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d\n", + hdisplay, vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", +@@ -2044,11 +2193,38 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, + + if (mode->flags & DRM_MODE_FLAG_DBLCLK) { + dsp_ctrl |= RK3568_VP_DSP_CTRL__CORE_DCLK_DIV; +- clock *= 2; ++ // [CC:] done via mode_fixup ++ // clock *= 2; + } + + vop2_vp_write(vp, RK3568_VP_MIPI_CTRL, 0); + ++ snprintf(clk_name, sizeof(clk_name), "dclk%d", vp->id); ++ dclk = vop2_clk_get(vop2, clk_name); ++ if (dclk) { ++ /* ++ * use HDMI_PHY_PLL as dclk source under 4K@60 if it is available, ++ * otherwise use system cru as dclk source. ++ */ ++ drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { ++ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); ++ ++ // [CC:] Using PHY PLL to handle all display modes ++ if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) { ++ clk_get_rate(vop2->hdmi0_phy_pll); ++ ++ if (mode->crtc_clock <= VOP2_MAX_DCLK_RATE) { ++ ret = clk_set_parent(vp->dclk, vop2->hdmi0_phy_pll); ++ if (ret < 0) ++ DRM_WARN("failed to set clock parent for %s\n", ++ __clk_get_name(vp->dclk)); ++ } ++ ++ clock = dclk->rate; ++ } ++ } ++ } ++ + clk_set_rate(vp->dclk, clock); + + vop2_post_config(crtc); +@@ -2504,7 +2680,43 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, + spin_unlock_irq(&crtc->dev->event_lock); + } + ++static enum drm_mode_status ++vop2_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) ++{ ++ struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); ++ struct vop2_video_port *vp = to_vop2_video_port(crtc); ++ struct vop2 *vop2 = vp->vop2; ++ const struct vop2_data *vop2_data = vop2->data; ++ const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; ++ int request_clock = mode->clock; ++ int clock; ++ ++ if (mode->hdisplay > vp_data->max_output.width) ++ return MODE_BAD_HVALUE; ++ ++ if (mode->flags & DRM_MODE_FLAG_DBLCLK) ++ request_clock *= 2; ++ ++ if (request_clock <= VOP2_MAX_DCLK_RATE) { ++ clock = request_clock; ++ } else { ++ request_clock = request_clock >> 2; ++ clock = clk_round_rate(vp->dclk, request_clock * 1000) / 1000; ++ } ++ ++ /* ++ * Hdmi or DisplayPort request a Accurate clock. ++ */ ++ if (vcstate->output_type == DRM_MODE_CONNECTOR_HDMIA || ++ vcstate->output_type == DRM_MODE_CONNECTOR_DisplayPort) ++ if (clock != request_clock) ++ return MODE_CLOCK_RANGE; ++ ++ return MODE_OK; ++} ++ + static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = { ++ .mode_valid = vop2_crtc_mode_valid, + .mode_fixup = vop2_crtc_mode_fixup, + .atomic_check = vop2_crtc_atomic_check, + .atomic_begin = vop2_crtc_atomic_begin, +@@ -3074,6 +3286,336 @@ static const struct regmap_config vop2_regmap_config = { + .cache_type = REGCACHE_MAPLE, + }; + ++/* ++ * BEGIN virtual clock ++ */ ++#define PLL_RATE_MIN 30000000 ++ ++#define cru_dbg(format, ...) do { \ ++ if (cru_debug) \ ++ pr_info("%s: " format, __func__, ## __VA_ARGS__); \ ++ } while (0) ++ ++#define PNAME(x) static const char *const x[] ++ ++enum vop_clk_branch_type { ++ branch_mux, ++ branch_divider, ++ branch_factor, ++ branch_virtual, ++}; ++ ++#define VIR(cname) \ ++ { \ ++ .branch_type = branch_virtual, \ ++ .name = cname, \ ++ } ++ ++ ++#define MUX(cname, pnames, f) \ ++ { \ ++ .branch_type = branch_mux, \ ++ .name = cname, \ ++ .parent_names = pnames, \ ++ .num_parents = ARRAY_SIZE(pnames), \ ++ .flags = f, \ ++ } ++ ++#define FACTOR(cname, pname, f) \ ++ { \ ++ .branch_type = branch_factor, \ ++ .name = cname, \ ++ .parent_names = (const char *[]){ pname }, \ ++ .num_parents = 1, \ ++ .flags = f, \ ++ } ++ ++#define DIV(cname, pname, f, w) \ ++ { \ ++ .branch_type = branch_divider, \ ++ .name = cname, \ ++ .parent_names = (const char *[]){ pname }, \ ++ .num_parents = 1, \ ++ .flags = f, \ ++ .div_width = w, \ ++ } ++ ++struct vop2_clk_branch { ++ enum vop_clk_branch_type branch_type; ++ const char *name; ++ const char *const *parent_names; ++ u8 num_parents; ++ unsigned long flags; ++ u8 div_shift; ++ u8 div_width; ++ u8 div_flags; ++}; ++ ++PNAME(mux_port0_dclk_src_p) = { "dclk0", "dclk1" }; ++PNAME(mux_port2_dclk_src_p) = { "dclk2", "dclk1" }; ++PNAME(mux_dp_pixclk_p) = { "dclk_out0", "dclk_out1", "dclk_out2" }; ++PNAME(mux_hdmi_edp_clk_src_p) = { "dclk0", "dclk1", "dclk2" }; ++PNAME(mux_mipi_clk_src_p) = { "dclk_out1", "dclk_out2", "dclk_out3" }; ++PNAME(mux_dsc_8k_clk_src_p) = { "dclk0", "dclk1", "dclk2", "dclk3" }; ++PNAME(mux_dsc_4k_clk_src_p) = { "dclk0", "dclk1", "dclk2", "dclk3" }; ++ ++/* ++ * We only use this clk driver calculate the div ++ * of dclk_core/dclk_out/if_pixclk/if_dclk and ++ * the rate of the dclk from the soc. ++ * ++ * We don't touch the cru in the vop here, as ++ * these registers has special read andy write ++ * limits. ++ */ ++static struct vop2_clk_branch rk3588_vop_clk_branches[] = { ++ VIR("dclk0"), ++ VIR("dclk1"), ++ VIR("dclk2"), ++ VIR("dclk3"), ++ ++ MUX("port0_dclk_src", mux_port0_dclk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), ++ DIV("dclk_core0", "port0_dclk_src", CLK_SET_RATE_PARENT, 2), ++ DIV("dclk_out0", "port0_dclk_src", CLK_SET_RATE_PARENT, 2), ++ ++ FACTOR("port1_dclk_src", "dclk1", CLK_SET_RATE_PARENT), ++ DIV("dclk_core1", "port1_dclk_src", CLK_SET_RATE_PARENT, 2), ++ DIV("dclk_out1", "port1_dclk_src", CLK_SET_RATE_PARENT, 2), ++ ++ MUX("port2_dclk_src", mux_port2_dclk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), ++ DIV("dclk_core2", "port2_dclk_src", CLK_SET_RATE_PARENT, 2), ++ DIV("dclk_out2", "port2_dclk_src", CLK_SET_RATE_PARENT, 2), ++ ++ FACTOR("port3_dclk_src", "dclk3", CLK_SET_RATE_PARENT), ++ DIV("dclk_core3", "port3_dclk_src", CLK_SET_RATE_PARENT, 2), ++ DIV("dclk_out3", "port3_dclk_src", CLK_SET_RATE_PARENT, 2), ++ ++ MUX("dp0_pixclk", mux_dp_pixclk_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), ++ MUX("dp1_pixclk", mux_dp_pixclk_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), ++ ++ MUX("hdmi_edp0_clk_src", mux_hdmi_edp_clk_src_p, ++ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), ++ DIV("hdmi_edp0_dclk", "hdmi_edp0_clk_src", 0, 2), ++ DIV("hdmi_edp0_pixclk", "hdmi_edp0_clk_src", CLK_SET_RATE_PARENT, 1), ++ ++ MUX("hdmi_edp1_clk_src", mux_hdmi_edp_clk_src_p, ++ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), ++ DIV("hdmi_edp1_dclk", "hdmi_edp1_clk_src", 0, 2), ++ DIV("hdmi_edp1_pixclk", "hdmi_edp1_clk_src", CLK_SET_RATE_PARENT, 1), ++ ++ MUX("mipi0_clk_src", mux_mipi_clk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), ++ DIV("mipi0_pixclk", "mipi0_clk_src", CLK_SET_RATE_PARENT, 2), ++ ++ MUX("mipi1_clk_src", mux_mipi_clk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), ++ DIV("mipi1_pixclk", "mipi1_clk_src", CLK_SET_RATE_PARENT, 2), ++ ++ FACTOR("rgb_pixclk", "port3_dclk_src", CLK_SET_RATE_PARENT), ++ ++ MUX("dsc_8k_txp_clk_src", mux_dsc_8k_clk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), ++ DIV("dsc_8k_txp_clk", "dsc_8k_txp_clk_src", 0, 2), ++ DIV("dsc_8k_pxl_clk", "dsc_8k_txp_clk_src", 0, 2), ++ DIV("dsc_8k_cds_clk", "dsc_8k_txp_clk_src", 0, 2), ++ ++ MUX("dsc_4k_txp_clk_src", mux_dsc_4k_clk_src_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), ++ DIV("dsc_4k_txp_clk", "dsc_4k_txp_clk_src", 0, 2), ++ DIV("dsc_4k_pxl_clk", "dsc_4k_txp_clk_src", 0, 2), ++ DIV("dsc_4k_cds_clk", "dsc_4k_txp_clk_src", 0, 2), ++}; ++ ++static unsigned long clk_virtual_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct vop2_clk *vop2_clk = to_vop2_clk(hw); ++ ++ return (unsigned long)vop2_clk->rate; ++} ++ ++static long clk_virtual_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *prate) ++{ ++ struct vop2_clk *vop2_clk = to_vop2_clk(hw); ++ ++ vop2_clk->rate = rate; ++ ++ return rate; ++} ++ ++static int clk_virtual_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ return 0; ++} ++ ++const struct clk_ops clk_virtual_ops = { ++ .round_rate = clk_virtual_round_rate, ++ .set_rate = clk_virtual_set_rate, ++ .recalc_rate = clk_virtual_recalc_rate, ++}; ++ ++static u8 vop2_mux_get_parent(struct clk_hw *hw) ++{ ++ struct vop2_clk *vop2_clk = to_vop2_clk(hw); ++ ++ // cru_dbg("%s index: %d\n", clk_hw_get_name(hw), vop2_clk->parent_index); ++ return vop2_clk->parent_index; ++} ++ ++static int vop2_mux_set_parent(struct clk_hw *hw, u8 index) ++{ ++ struct vop2_clk *vop2_clk = to_vop2_clk(hw); ++ ++ vop2_clk->parent_index = index; ++ ++ // cru_dbg("%s index: %d\n", clk_hw_get_name(hw), index); ++ return 0; ++} ++ ++static int vop2_clk_mux_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ // cru_dbg("%s %ld(min: %ld max: %ld)\n", ++ // clk_hw_get_name(hw), req->rate, req->min_rate, req->max_rate); ++ return __clk_mux_determine_rate(hw, req); ++} ++ ++static const struct clk_ops vop2_mux_clk_ops = { ++ .get_parent = vop2_mux_get_parent, ++ .set_parent = vop2_mux_set_parent, ++ .determine_rate = vop2_clk_mux_determine_rate, ++}; ++ ++#define div_mask(width) ((1 << (width)) - 1) ++ ++static int vop2_div_get_val(unsigned long rate, unsigned long parent_rate) ++{ ++ unsigned int div, value; ++ ++ div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); ++ ++ value = ilog2(div); ++ ++ return value; ++} ++ ++static unsigned long vop2_clk_div_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct vop2_clk *vop2_clk = to_vop2_clk(hw); ++ unsigned long rate; ++ unsigned int div; ++ ++ div = 1 << vop2_clk->div_val; ++ rate = parent_rate / div; ++ ++ // cru_dbg("%s rate: %ld(prate: %ld)\n", clk_hw_get_name(hw), rate, parent_rate); ++ return rate; ++} ++ ++static long vop2_clk_div_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *prate) ++{ ++ struct vop2_clk *vop2_clk = to_vop2_clk(hw); ++ ++ if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { ++ if (*prate < rate) ++ *prate = rate; ++ if ((*prate >> vop2_clk->div.width) > rate) ++ *prate = rate; ++ ++ if ((*prate % rate)) ++ *prate = rate; ++ ++ /* SOC PLL can't output a too low pll freq */ ++ if (*prate < PLL_RATE_MIN) ++ *prate = rate << vop2_clk->div.width; ++ } ++ ++ // cru_dbg("%s rate: %ld(prate: %ld)\n", clk_hw_get_name(hw), rate, *prate); ++ return rate; ++} ++ ++static int vop2_clk_div_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) ++{ ++ struct vop2_clk *vop2_clk = to_vop2_clk(hw); ++ int div_val; ++ ++ div_val = vop2_div_get_val(rate, parent_rate); ++ vop2_clk->div_val = div_val; ++ ++ // cru_dbg("%s prate: %ld rate: %ld div_val: %d\n", ++ // clk_hw_get_name(hw), parent_rate, rate, div_val); ++ return 0; ++} ++ ++static const struct clk_ops vop2_div_clk_ops = { ++ .recalc_rate = vop2_clk_div_recalc_rate, ++ .round_rate = vop2_clk_div_round_rate, ++ .set_rate = vop2_clk_div_set_rate, ++}; ++ ++static struct clk *vop2_clk_register(struct vop2 *vop2, struct vop2_clk_branch *branch) ++{ ++ struct clk_init_data init = {}; ++ struct vop2_clk *vop2_clk; ++ struct clk *clk; ++ ++ vop2_clk = devm_kzalloc(vop2->dev, sizeof(*vop2_clk), GFP_KERNEL); ++ if (!vop2_clk) ++ return ERR_PTR(-ENOMEM); ++ ++ vop2_clk->vop2 = vop2; ++ vop2_clk->hw.init = &init; ++ vop2_clk->div.shift = branch->div_shift; ++ vop2_clk->div.width = branch->div_width; ++ ++ init.name = branch->name; ++ init.flags = branch->flags; ++ init.num_parents = branch->num_parents; ++ init.parent_names = branch->parent_names; ++ if (branch->branch_type == branch_divider) { ++ init.ops = &vop2_div_clk_ops; ++ } else if (branch->branch_type == branch_virtual) { ++ init.ops = &clk_virtual_ops; ++ init.num_parents = 0; ++ init.parent_names = NULL; ++ } else { ++ init.ops = &vop2_mux_clk_ops; ++ } ++ ++ clk = devm_clk_register(vop2->dev, &vop2_clk->hw); ++ if (!IS_ERR(clk)) ++ list_add_tail(&vop2_clk->list, &vop2->clk_list_head); ++ else ++ DRM_DEV_ERROR(vop2->dev, "Register %s failed\n", branch->name); ++ ++ return clk; ++} ++ ++static int vop2_clk_init(struct vop2 *vop2) ++{ ++ struct vop2_clk_branch *branch = rk3588_vop_clk_branches; ++ unsigned int nr_clk = ARRAY_SIZE(rk3588_vop_clk_branches); ++ unsigned int idx; ++ struct vop2_clk *clk, *n; ++ ++ INIT_LIST_HEAD(&vop2->clk_list_head); ++ ++ if (vop2->data->soc_id < 3588 || vop2->hdmi0_phy_pll == NULL) ++ return 0; ++ ++ list_for_each_entry_safe(clk, n, &vop2->clk_list_head, list) { ++ list_del(&clk->list); ++ } ++ ++ for (idx = 0; idx < nr_clk; idx++, branch++) ++ vop2_clk_register(vop2, branch); ++ ++ return 0; ++} ++/* ++ * END virtual clock ++ */ ++ + static int vop2_bind(struct device *dev, struct device *master, void *data) + { + struct platform_device *pdev = to_platform_device(dev); +@@ -3167,6 +3709,12 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) + return PTR_ERR(vop2->pclk); + } + ++ vop2->hdmi0_phy_pll = devm_clk_get_optional(vop2->drm->dev, "hdmi0_phy_pll"); ++ if (IS_ERR(vop2->hdmi0_phy_pll)) { ++ DRM_DEV_ERROR(vop2->dev, "failed to get hdmi0_phy_pll source\n"); ++ return PTR_ERR(vop2->hdmi0_phy_pll); ++ } ++ + vop2->irq = platform_get_irq(pdev, 0); + if (vop2->irq < 0) { + drm_err(vop2->drm, "cannot find irq for vop2\n"); +@@ -3183,6 +3731,9 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) + if (ret) + return ret; + ++ // [CC:] rework virtual clock ++ vop2_clk_init(vop2); ++ + ret = vop2_find_rgb_encoder(vop2); + if (ret >= 0) { + vop2->rgb = rockchip_rgb_init(dev, &vop2->vps[ret].crtc, +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch new file mode 100644 index 000000000000..5e9c266dc49f --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch @@ -0,0 +1,55 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Mon, 13 May 2024 20:29:49 +0300 +Subject: arm64: dts: rockchip: rk3588: add VDPU and RGA2 nodes + +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 32 ++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -848,6 +848,38 @@ gpu: gpu@fb000000 { + status = "disabled"; + }; + ++ vpu: video-codec@fdb50000 { ++ compatible = "rockchip,rk3568-vpu"; ++ reg = <0x0 0xfdb50000 0x0 0x800>; ++ interrupts = ; ++ interrupt-names = "vdpu"; ++ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vdpu_mmu>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ ++ vdpu_mmu: iommu@fdb50800 { ++ compatible = "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfdb50800 0x0 0x40>; ++ interrupts = ; ++ clock-names = "aclk", "iface"; ++ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ #iommu-cells = <0>; ++ }; ++ ++ rga: rga@fdb80000 { ++ compatible = "rockchip,rk3568-rga", "rockchip,rk3288-rga"; ++ reg = <0x0 0xfdb80000 0x0 0x1000>; ++ interrupts = ; ++ clocks = <&cru ACLK_RGA2>, <&cru HCLK_RGA2>, <&cru CLK_RGA2_CORE>; ++ clock-names = "aclk", "hclk", "sclk"; ++ resets = <&cru SRST_RGA2_CORE>, <&cru SRST_A_RGA2>, <&cru SRST_H_RGA2>; ++ reset-names = "core", "axi", "ahb"; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ + pmu1grf: syscon@fd58a000 { + compatible = "rockchip,rk3588-pmugrf", "syscon", "simple-mfd"; + reg = <0x0 0xfd58a000 0x0 0x10000>; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0801-wireless-add-bcm43752.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0801-wireless-add-bcm43752.patch new file mode 100644 index 000000000000..0085fdff2805 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0801-wireless-add-bcm43752.patch @@ -0,0 +1,74 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Wed, 28 Feb 2024 20:59:15 +0100 +Subject: net: wireless: brcmfmac: Add support for AP6275P + +This module features BCM43752A2 chipset. The firmware requires +randomness seeding, so enabled it. + +Signed-off-by: Ondrej Jirman +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 5 ++++- + drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 ++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 111111111111..222222222222 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -70,6 +70,7 @@ BRCMF_FW_CLM_DEF(4377B3, "brcmfmac4377b3-pcie"); + BRCMF_FW_CLM_DEF(4378B1, "brcmfmac4378b1-pcie"); + BRCMF_FW_CLM_DEF(4378B3, "brcmfmac4378b3-pcie"); + BRCMF_FW_CLM_DEF(4387C2, "brcmfmac4387c2-pcie"); ++BRCMF_FW_CLM_DEF(43752, "brcmfmac43752-pcie"); + + /* firmware config files */ + MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH "brcmfmac*-pcie.txt"); +@@ -104,6 +105,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { + BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C), + BRCMF_FW_ENTRY(BRCM_CC_43666_CHIP_ID, 0xFFFFFFF0, 4366C), + BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371), ++ BRCMF_FW_ENTRY(BRCM_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752), + BRCMF_FW_ENTRY(BRCM_CC_4377_CHIP_ID, 0xFFFFFFFF, 4377B3), /* revision ID 4 */ + BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0x0000000F, 4378B1), /* revision ID 3 */ + BRCMF_FW_ENTRY(BRCM_CC_4378_CHIP_ID, 0xFFFFFFE0, 4378B3), /* revision ID 5 */ +@@ -1720,7 +1722,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, + memcpy_toio(devinfo->tcm + address, nvram, nvram_len); + brcmf_fw_nvram_free(nvram); + +- if (devinfo->otp.valid) { ++ if (devinfo->otp.valid || devinfo->ci->chip == BRCM_CC_43752_CHIP_ID) { + size_t rand_len = BRCMF_RANDOM_SEED_LENGTH; + struct brcmf_random_seed_footer footer = { + .length = cpu_to_le32(rand_len), +@@ -2700,6 +2702,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { + BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID, BCA), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID, WCC), + BRCMF_PCIE_DEVICE(BRCM_PCIE_43596_DEVICE_ID, CYW), ++ BRCMF_PCIE_DEVICE(BRCM_PCIE_43752_DEVICE_ID, WCC), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4377_DEVICE_ID, WCC), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4378_DEVICE_ID, WCC), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4387_DEVICE_ID, WCC), +diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +index 111111111111..222222222222 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +@@ -52,6 +52,7 @@ + #define BRCM_CC_43664_CHIP_ID 43664 + #define BRCM_CC_43666_CHIP_ID 43666 + #define BRCM_CC_4371_CHIP_ID 0x4371 ++#define BRCM_CC_43752_CHIP_ID 43752 + #define BRCM_CC_4377_CHIP_ID 0x4377 + #define BRCM_CC_4378_CHIP_ID 0x4378 + #define BRCM_CC_4387_CHIP_ID 0x4387 +@@ -94,6 +95,7 @@ + #define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5 + #define BRCM_PCIE_4371_DEVICE_ID 0x440d + #define BRCM_PCIE_43596_DEVICE_ID 0x4415 ++#define BRCM_PCIE_43752_DEVICE_ID 0x449d + #define BRCM_PCIE_4377_DEVICE_ID 0x4488 + #define BRCM_PCIE_4378_DEVICE_ID 0x4425 + #define BRCM_PCIE_4387_DEVICE_ID 0x4433 +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/0802-wireless-add-clk-property.patch b/patch/kernel/archive/rockchip-rk3588-6.8/0802-wireless-add-clk-property.patch new file mode 100644 index 000000000000..193f9892bbe2 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/0802-wireless-add-clk-property.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Wed, 28 Feb 2024 21:09:51 +0100 +Subject: net: wireless: brcmfmac: Add optional 32k clock enable support + +WiFi modules often require 32kHz clock to function. Add support to +enable the clock to pcie driver. + +Signed-off-by: Ondrej Jirman +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 111111111111..222222222222 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -3,6 +3,7 @@ + * Copyright (c) 2014 Broadcom Corporation + */ + ++#include + #include + #include + #include +@@ -2413,6 +2414,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) + struct brcmf_pciedev *pcie_bus_dev; + struct brcmf_core *core; + struct brcmf_bus *bus; ++ struct clk *clk; + + if (!id) { + id = pci_match_id(brcmf_pcie_devid_table, pdev); +@@ -2424,6 +2426,14 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device); + ++ clk = devm_clk_get_optional_enabled(&pdev->dev, "32k"); ++ if (IS_ERR(clk)) ++ return PTR_ERR(clk); ++ if (clk) { ++ dev_info(&pdev->dev, "enabling 32kHz clock\n"); ++ clk_set_rate(clk, 32768); ++ } ++ + ret = -ENOMEM; + devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); + if (devinfo == NULL) +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch new file mode 100644 index 000000000000..5949900e1ab4 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Wed, 27 Dec 2023 15:03:57 +0800 +Subject: arm64: dts: rock-5b: Slow down emmc to hs200 and add tsadc node + +--- + arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -359,8 +359,7 @@ &sdhci { + no-sdio; + no-sd; + non-removable; +- mmc-hs400-1_8v; +- mmc-hs400-enhanced-strobe; ++ mmc-hs200-1_8v; + status = "okay"; + }; + +@@ -400,6 +399,10 @@ &sdio { + status = "okay"; + }; + ++&tsadc { ++ status = "okay"; ++}; ++ + &uart6 { + pinctrl-names = "default"; + pinctrl-0 = <&uart6m1_xfer &uart6m1_ctsn &uart6m1_rtsn>; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch new file mode 100644 index 000000000000..8367fbca0260 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lanefu +Date: Sat, 20 Jan 2024 17:16:20 +0000 +Subject: rock-5b enable SPI flash in device tree + arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts + +Signed-off-by: lanefu +--- + arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 27 ++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -409,6 +409,33 @@ &uart6 { + status = "okay"; + }; + ++&sfc { ++ status = "okay"; ++ ++ spi_flash: spi-flash@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "jedec,spi-nor"; ++ reg = <0x0>; ++ spi-max-frequency = <50000000>; ++ spi-tx-bus-width = <1>; ++ spi-rx-bus-width = <4>; ++ status = "okay"; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ loader@0 { ++ label = "loader"; ++ reg = <0x0 0x1000000>; ++ }; ++ }; ++ }; ++ ++}; ++ + &spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch new file mode 100644 index 000000000000..d1d252c94318 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Mon, 15 Jan 2024 22:51:17 +0200 +Subject: arm64: dts: rockchip: Enable HDMI0 on rock-5b + +Add the necessary DT changes to enable HDMI0 on Rock 5B. + +Signed-off-by: Cristian Ciocaltea +--- + arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 30 ++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -4,6 +4,7 @@ + + #include + #include ++#include + #include "rk3588.dtsi" + + / { +@@ -173,6 +174,20 @@ &cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; + }; + ++&hdmi0 { ++ status = "okay"; ++}; ++ ++&hdmi0_in { ++ hdmi0_in_vp0: endpoint { ++ remote-endpoint = <&vp0_out_hdmi0>; ++ }; ++}; ++ ++&hdptxphy_hdmi0 { ++ status = "okay"; ++}; ++ + &i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; +@@ -821,3 +836,18 @@ &usb_host1_xhci { + &usb_host2_xhci { + status = "okay"; + }; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vp0 { ++ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { ++ reg = ; ++ remote-endpoint = <&hdmi0_in_vp0>; ++ }; ++}; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1013-arm64-dts-rockchip-rk3588-rock5b-Add-GPU-node.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1013-arm64-dts-rockchip-rk3588-rock5b-Add-GPU-node.patch new file mode 100644 index 000000000000..bb90a1131c5f --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1013-arm64-dts-rockchip-rk3588-rock5b-Add-GPU-node.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Tue, 8 Aug 2023 12:05:22 +0200 +Subject: arm64: dts: rockchip: rk3588-rock5b: Add GPU node + +Signed-off-by: Boris Brezillon +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -174,6 +174,11 @@ &cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; + }; + ++&gpu { ++ mali-supply = <&vdd_gpu_s0>; ++ status = "okay"; ++}; ++ + &hdmi0 { + status = "okay"; + }; +@@ -509,6 +514,7 @@ rk806_dvs3_null: dvs3-null-pins { + + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { ++ regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch new file mode 100644 index 000000000000..a7445b5d2495 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Fri, 3 Nov 2023 20:05:05 +0200 +Subject: arm64: dts: rockchip: Make use of HDMI0 PHY PLL on rock-5b + +The initial vop2 support for rk3588 in mainline is not able to handle +all display modes supported by connected displays, e.g. +2560x1440-75.00Hz, 2048x1152-60.00Hz, 1024x768-60.00Hz. + +Additionally, it doesn't cope with non-integer refresh rates like 59.94, +29.97, 23.98, etc. + +Make use of the HDMI0 PHY PLL to support the additional display modes. + +Note this requires commit "drm/rockchip: vop2: Improve display modes +handling on rk3588", which needs a rework to be upstreamable. + +Signed-off-by: Cristian Ciocaltea +--- + arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -179,6 +179,11 @@ &gpu { + status = "okay"; + }; + ++&display_subsystem { ++ clocks = <&hdptxphy_hdmi0>; ++ clock-names = "hdmi0_phy_pll"; ++}; ++ + &hdmi0 { + status = "okay"; + }; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch new file mode 100644 index 000000000000..77742afb837d --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Tue, 27 Feb 2024 16:04:42 +0300 +Subject: Add HDMI and VOP2 to Rock 5A + +--- + arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 30 ++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include "rk3588s.dtsi" + + / { +@@ -760,3 +761,32 @@ &usb_host1_ohci { + &usb_host2_xhci { + status = "okay"; + }; ++ ++&hdmi0 { ++ status = "okay"; ++}; ++ ++&hdptxphy_hdmi0 { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&hdmi0_in { ++ hdmi0_in_vp0: endpoint { ++ remote-endpoint = <&vp0_out_hdmi0>; ++ }; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vp0 { ++ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { ++ reg = ; ++ remote-endpoint = <&hdmi0_in_vp0>; ++ }; ++}; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch new file mode 100644 index 000000000000..f82a3ba3b125 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Thu, 28 Mar 2024 00:41:34 +0800 +Subject: arch: arm64: dts: enable gpu node for rock-5a + +--- + arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +@@ -281,6 +281,11 @@ &gmac1_rgmii_clk + status = "okay"; + }; + ++&gpu { ++ mali-supply = <&vdd_gpu_s0>; ++ status = "okay"; ++}; ++ + &mdio1 { + rgmii_phy1: ethernet-phy@1 { + /* RTL8211F */ +@@ -433,6 +438,7 @@ rk806_dvs3_null: dvs3-null-pins { + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { + regulator-name = "vdd_gpu_s0"; ++ regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch new file mode 100644 index 000000000000..32653f4a1564 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch @@ -0,0 +1,265 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Thu, 16 Nov 2023 18:15:09 +0300 +Subject: arm64: dts: Add missing nodes to Orange Pi 5 Plus + +--- + arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts | 182 +++++++++- + 1 file changed, 181 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include "rk3588.dtsi" + + / { +@@ -158,6 +159,20 @@ daicodec: simple-audio-card,codec { + }; + }; + ++ wlan-rfkill { ++ compatible = "rfkill-gpio"; ++ label = "rfkill-wlan"; ++ radio-type = "wlan"; ++ shutdown-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ bluetooth-rfkill { ++ compatible = "rfkill-gpio"; ++ label = "rfkill-bluetooth"; ++ radio-type = "bluetooth"; ++ shutdown-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; ++ }; ++ + vcc3v3_pcie30: vcc3v3-pcie30-regulator { + compatible = "regulator-fixed"; + enable-active-high; +@@ -199,6 +214,18 @@ vcc5v0_sys: vcc5v0-sys-regulator { + regulator-max-microvolt = <5000000>; + }; + ++ vbus5v0_typec: vbus5v0-typec-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; ++ regulator-name = "vbus5v0_typec"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&typec5v_pwren>; ++ vin-supply = <&vcc5v0_sys>; ++ }; ++ + vcc5v0_usb20: vcc5v0-usb20-regulator { + compatible = "regulator-fixed"; + enable-active-high; +@@ -311,6 +338,53 @@ hym8563: rtc@51 { + pinctrl-0 = <&hym8563_int>; + wakeup-source; + }; ++ ++ usbc0: usb-typec@22 { ++ compatible = "fcs,fusb302"; ++ reg = <0x22>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usbc0_int>; ++ vbus-supply = <&vbus5v0_typec>; ++ ++ usb_con: connector { ++ compatible = "usb-c-connector"; ++ label = "USB-C"; ++ data-role = "dual"; ++ power-role = "dual"; ++ try-power-role = "source"; ++ op-sink-microwatt = <1000000>; ++ sink-pdos = ; ++ source-pdos = ; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ usbc0_hs: endpoint { ++ remote-endpoint = <&usb_host0_xhci_drd_sw>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ usbc0_ss: endpoint { ++ remote-endpoint = <&usbdp_phy0_typec_ss>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ usbc0_sbu: endpoint { ++ remote-endpoint = <&usbdp_phy0_typec_sbu>; ++ }; ++ }; ++ }; ++ }; ++ }; + }; + + &i2c7 { +@@ -385,7 +459,7 @@ &pcie3x4 { + &pinctrl { + hym8563 { + hym8563_int: hym8563-int { +- rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; ++ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + +@@ -408,6 +482,14 @@ hp_detect: hp-detect { + }; + + usb { ++ typec5v_pwren: typec5v-pwren { ++ rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ usbc0_int: usbc0-int { ++ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ + vcc5v0_usb20_en: vcc5v0-usb20-en { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; +@@ -803,6 +885,22 @@ &tsadc { + status = "okay"; + }; + ++&u2phy0 { ++ status = "okay"; ++}; ++ ++&u2phy0_otg { ++ status = "okay"; ++}; ++ ++&u2phy1 { ++ status = "okay"; ++}; ++ ++&u2phy1_otg { ++ status = "okay"; ++}; ++ + &u2phy2 { + status = "okay"; + }; +@@ -831,6 +929,35 @@ &uart9 { + status = "okay"; + }; + ++&usbdp_phy0 { ++ orientation-switch; ++ mode-switch; ++ sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>; ++ sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ svid = <0xff01>; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ usbdp_phy0_typec_ss: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&usbc0_ss>; ++ }; ++ ++ usbdp_phy0_typec_sbu: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&usbc0_sbu>; ++ }; ++ }; ++}; ++ ++&usbdp_phy1 { ++ rockchip,dp-lane-mux = <2 3>; ++ status = "okay"; ++}; ++ + &usb_host0_ehci { + status = "okay"; + }; +@@ -839,6 +966,20 @@ &usb_host0_ohci { + status = "okay"; + }; + ++&usb_host0_xhci { ++ dr_mode = "otg"; ++ usb-role-switch; ++ status = "okay"; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ usb_host0_xhci_drd_sw: endpoint { ++ remote-endpoint = <&usbc0_hs>; ++ }; ++ }; ++}; ++ + &usb_host1_ehci { + status = "okay"; + }; +@@ -846,3 +987,42 @@ &usb_host1_ehci { + &usb_host1_ohci { + status = "okay"; + }; ++ ++&usb_host1_xhci { ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&gpu { ++ mali-supply = <&vdd_gpu_s0>; ++ status = "okay"; ++}; ++ ++&hdmi0 { ++ status = "okay"; ++}; ++ ++&hdptxphy_hdmi0 { ++ status = "okay"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&hdmi0_in { ++ hdmi0_in_vp0: endpoint { ++ remote-endpoint = <&vp0_out_hdmi0>; ++ }; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vp0 { ++ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { ++ reg = ; ++ remote-endpoint = <&hdmi0_in_vp0>; ++ }; ++}; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch new file mode 100644 index 000000000000..95347d9d3af9 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Thu, 28 Mar 2024 10:59:29 +0800 +Subject: arm64: dts: rockchip: support poweroff on rock-5a + +--- + arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +@@ -401,6 +401,8 @@ pmic@0 { + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + spi-max-frequency = <1000000>; + ++ system-power-controller; ++ + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch new file mode 100644 index 000000000000..bd33b5976c41 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: amazingfate +Date: Thu, 28 Mar 2024 16:07:18 +0800 +Subject: arm64: dts: rockchip: add PCIe for M.2 E-Key to rock-5a + +--- + arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +@@ -115,6 +115,10 @@ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + }; + }; + ++&combphy0_ps { ++ status = "okay"; ++}; ++ + &combphy2_psu { + status = "okay"; + }; +@@ -299,6 +303,11 @@ rgmii_phy1: ethernet-phy@1 { + }; + }; + ++&pcie2x1l2 { ++ status = "okay"; ++ reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; ++}; ++ + &pinctrl { + leds { + io_led: io-led { +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1031-Add-missing-nodes-to-Orange-Pi-5.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1031-Add-missing-nodes-to-Orange-Pi-5.patch new file mode 100644 index 000000000000..d3249d816e38 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1031-Add-missing-nodes-to-Orange-Pi-5.patch @@ -0,0 +1,318 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Thu, 16 Nov 2023 18:09:07 +0300 +Subject: arm64: dts: Add missing nodes to Orange Pi 5 + +--- + arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts | 203 +++++++++- + 1 file changed, 201 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dts +@@ -6,6 +6,8 @@ + #include + #include + #include ++#include ++#include + #include "rk3588s.dtsi" + + / { +@@ -47,6 +49,40 @@ led-1 { + }; + }; + ++ analog-sound { ++ compatible = "simple-audio-card"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hp_detect>; ++ simple-audio-card,name = "Orange Pi 5 Audio"; ++ simple-audio-card,bitclock-master = <&masterdai>; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,frame-master = <&masterdai>; ++ simple-audio-card,hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>; ++ simple-audio-card,mclk-fs = <256>; ++ simple-audio-card,pin-switches = "Headphones", "Speaker"; ++ simple-audio-card,routing = ++ "Headphones", "LOUT1", ++ "Headphones", "ROUT1", ++ "LINPUT1", "Onboard Microphone", ++ "RINPUT1", "Onboard Microphone", ++ "LINPUT2", "Microphone Jack", ++ "RINPUT2", "Microphone Jack"; ++ simple-audio-card,widgets = ++ "Microphone", "Microphone Jack", ++ "Microphone", "Onboard Microphone", ++ "Headphone", "Headphones", ++ "Speaker", "Speaker"; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s1_8ch>; ++ }; ++ ++ masterdai: simple-audio-card,codec { ++ sound-dai = <&es8388>; ++ system-clock-frequency = <12288000>; ++ }; ++ }; ++ + vbus_typec: vbus-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; +@@ -102,34 +138,42 @@ &combphy2_psu { + + &cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; ++ mem-supply = <&vdd_cpu_big0_s0>; + }; + + &cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; ++ mem-supply = <&vdd_cpu_big0_s0>; + }; + + &cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; ++ mem-supply = <&vdd_cpu_big1_s0>; + }; + + &cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; ++ mem-supply = <&vdd_cpu_big1_s0>; + }; + + &cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; ++ mem-supply = <&vdd_cpu_lit_mem_s0>; + }; + + &cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; ++ mem-supply = <&vdd_cpu_lit_mem_s0>; + }; + + &cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; ++ mem-supply = <&vdd_cpu_lit_mem_s0>; + }; + + &cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; ++ mem-supply = <&vdd_cpu_lit_mem_s0>; + }; + + &gmac1 { +@@ -223,6 +267,80 @@ hym8563: rtc@51 { + interrupts = ; + wakeup-source; + }; ++ ++ es8388: audio-codec@10 { ++ compatible = "everest,es8388"; ++ reg = <0x10>; ++ clocks = <&cru I2S1_8CH_MCLKOUT>; ++ assigned-clocks = <&cru I2S1_8CH_MCLKOUT>; ++ assigned-clock-rates = <12288000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s1m0_mclk>; ++ #sound-dai-cells = <0>; ++ }; ++ ++ usbc0: usb-typec@22 { ++ compatible = "fcs,fusb302"; ++ reg = <0x22>; ++ interrupt-parent = <&gpio0>; ++ interrupts = ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usbc0_int>; ++ vbus-supply = <&vbus_typec>; ++ ++ usb_con: connector { ++ compatible = "usb-c-connector"; ++ label = "USB-C"; ++ data-role = "dual"; ++ power-role = "dual"; ++ try-power-role = "source"; ++ op-sink-microwatt = <1000000>; ++ sink-pdos = ; ++ source-pdos = ; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ usbc0_hs: endpoint { ++ remote-endpoint = <&usb_host0_xhci_drd_sw>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ usbc0_ss: endpoint { ++ remote-endpoint = <&usbdp_phy0_typec_ss>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ usbc0_sbu: endpoint { ++ remote-endpoint = <&usbdp_phy0_typec_sbu>; ++ }; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2s1_8ch { ++ rockchip,i2s-tx-route = <3 2 1 0>; ++ rockchip,i2s-rx-route = <1 3 2 0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s1m0_sclk ++ &i2s1m0_lrck ++ &i2s1m0_sdi1 ++ &i2s1m0_sdo3>; ++ status = "okay"; ++}; ++ ++&gpu { ++ mali-supply = <&vdd_gpu_s0>; ++ status = "okay"; + }; + + &mdio1 { +@@ -263,6 +381,12 @@ typec5v_pwren: typec5v-pwren { + rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; ++ ++ sound { ++ hp_detect: hp-detect { ++ rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; + }; + + &saradc { +@@ -336,7 +460,7 @@ pmic@0 { + #gpio-cells = <2>; + + rk806_dvs1_null: dvs1-null-pins { +- pins = "gpio_pwrctrl2"; ++ pins = "gpio_pwrctrl1"; + function = "pin_fun0"; + }; + +@@ -364,7 +488,7 @@ regulator-state-mem { + }; + }; + +- vdd_cpu_lit_s0: dcdc-reg2 { ++ vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { + regulator-name = "vdd_cpu_lit_s0"; + regulator-always-on; + regulator-boot-on; +@@ -625,6 +749,14 @@ &tsadc { + status = "okay"; + }; + ++&u2phy0 { ++ status = "okay"; ++}; ++ ++&u2phy0_otg { ++ status = "okay"; ++}; ++ + &u2phy2 { + status = "okay"; + }; +@@ -650,10 +782,48 @@ &usb_host0_ehci { + status = "okay"; + }; + ++&usbdp_phy0 { ++ orientation-switch; ++ mode-switch; ++ sbu1-dc-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; ++ sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ usbdp_phy0_typec_ss: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&usbc0_ss>; ++ }; ++ ++ usbdp_phy0_typec_sbu: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&usbc0_sbu>; ++ }; ++ }; ++}; ++ + &usb_host0_ohci { + status = "okay"; + }; + ++&usb_host0_xhci { ++ usb-role-switch; ++ role-switch-default-mode = "host"; ++ status = "okay"; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ usb_host0_xhci_drd_sw: endpoint { ++ remote-endpoint = <&usbc0_hs>; ++ }; ++ }; ++}; ++ + &usb_host1_ehci { + status = "okay"; + }; +@@ -665,3 +835,32 @@ &usb_host1_ohci { + &usb_host2_xhci { + status = "okay"; + }; ++ ++&hdptxphy_hdmi0 { ++ status = "okay"; ++}; ++ ++&hdmi0 { ++ status = "okay"; ++}; ++ ++&hdmi0_in { ++ hdmi0_in_vp0: endpoint { ++ remote-endpoint = <&vp0_out_hdmi0>; ++ }; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vp0 { ++ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { ++ reg = ; ++ remote-endpoint = <&hdmi0_in_vp0>; ++ }; ++}; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1040-board-khadas-edge2-add-nodes.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1040-board-khadas-edge2-add-nodes.patch new file mode 100644 index 000000000000..1b74d40d1dce --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1040-board-khadas-edge2-add-nodes.patch @@ -0,0 +1,1464 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 10 Feb 2024 16:42:04 +0300 +Subject: arm64: dts: rockchip: Add cpu regulators and vcc5v0_sys to Khadas + Edge 2 + +This commit adds 5V fixed power regulator and CPU regulators to Khadas +Edge 2. + +Signed-off-by: Muhammed Efe Cetin +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 81 ++++++++++ + 1 file changed, 81 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -17,6 +17,87 @@ aliases { + chosen { + stdout-path = "serial2:1500000n8"; + }; ++ ++ vcc5v0_sys: vcc5v0-sys-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++}; ++ ++&cpu_b0 { ++ cpu-supply = <&vdd_cpu_big0_s0>; ++}; ++ ++&cpu_b1 { ++ cpu-supply = <&vdd_cpu_big0_s0>; ++}; ++ ++&cpu_b2 { ++ cpu-supply = <&vdd_cpu_big1_s0>; ++}; ++ ++&cpu_b3 { ++ cpu-supply = <&vdd_cpu_big1_s0>; ++}; ++ ++&cpu_l0 { ++ cpu-supply = <&vdd_cpu_lit_s0>; ++}; ++ ++&cpu_l1 { ++ cpu-supply = <&vdd_cpu_lit_s0>; ++}; ++ ++&cpu_l2 { ++ cpu-supply = <&vdd_cpu_lit_s0>; ++}; ++ ++&cpu_l3 { ++ cpu-supply = <&vdd_cpu_lit_s0>; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0m2_xfer>; ++ status = "okay"; ++ ++ vdd_cpu_big0_s0: regulator@42 { ++ compatible = "rockchip,rk8602"; ++ reg = <0x42>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu_big0_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-ramp-delay = <2300>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_big1_s0: regulator@43 { ++ compatible = "rockchip,rk8603", "rockchip,rk8602"; ++ reg = <0x43>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu_big1_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-ramp-delay = <2300>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; + }; + + &sdhci { +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 10 Feb 2024 17:04:20 +0300 +Subject: arm64: dts: rockchip: Add PMIC to Khadas Edge 2 + +This commit adds PMIC to Khadas Edge 2 board. + +Signed-off-by: Muhammed Efe Cetin +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 335 ++++++++++ + 1 file changed, 335 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -26,6 +26,16 @@ vcc5v0_sys: vcc5v0-sys-regulator { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; ++ ++ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_1v1_nldo_s3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ vin-supply = <&vcc5v0_sys>; ++ }; + }; + + &cpu_b0 { +@@ -110,6 +120,331 @@ &sdhci { + status = "okay"; + }; + ++&spi2 { ++ status = "okay"; ++ assigned-clocks = <&cru CLK_SPI2>; ++ assigned-clock-rates = <200000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; ++ num-cs = <1>; ++ ++ pmic@0 { ++ compatible = "rockchip,rk806"; ++ spi-max-frequency = <1000000>; ++ reg = <0x0>; ++ ++ interrupt-parent = <&gpio0>; ++ interrupts = <7 IRQ_TYPE_LEVEL_LOW>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, ++ <&rk806_dvs2_null>, <&rk806_dvs3_null>; ++ ++ system-power-controller; ++ ++ vcc1-supply = <&vcc5v0_sys>; ++ vcc2-supply = <&vcc5v0_sys>; ++ vcc3-supply = <&vcc5v0_sys>; ++ vcc4-supply = <&vcc5v0_sys>; ++ vcc5-supply = <&vcc5v0_sys>; ++ vcc6-supply = <&vcc5v0_sys>; ++ vcc7-supply = <&vcc5v0_sys>; ++ vcc8-supply = <&vcc5v0_sys>; ++ vcc9-supply = <&vcc5v0_sys>; ++ vcc10-supply = <&vcc5v0_sys>; ++ vcc11-supply = <&vcc_2v0_pldo_s3>; ++ vcc12-supply = <&vcc5v0_sys>; ++ vcc13-supply = <&vcc_1v1_nldo_s3>; ++ vcc14-supply = <&vcc_1v1_nldo_s3>; ++ vcca-supply = <&vcc5v0_sys>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ rk806_dvs1_null: dvs1-null-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs2_null: dvs2-null-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs3_null: dvs3-null-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun0"; ++ }; ++ ++ regulators { ++ vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_gpu_s0"; ++ regulator-enable-ramp-delay = <400>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_cpu_lit_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_log_s0: dcdc-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <750000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_log_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <750000>; ++ }; ++ }; ++ ++ vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_vdenc_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_ddr_s0: dcdc-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <900000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_ddr_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <850000>; ++ }; ++ }; ++ ++ vdd2_ddr_s3: dcdc-reg6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vdd2_ddr_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_2v0_pldo_s3: dcdc-reg7 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <2000000>; ++ regulator-max-microvolt = <2000000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_2v0_pldo_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <2000000>; ++ }; ++ }; ++ ++ vcc_3v3_s3: dcdc-reg8 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc_3v3_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vddq_ddr_s0: dcdc-reg9 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vddq_ddr_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8_s3: dcdc-reg10 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc_1v8_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ avcc_1v8_s0: pldo-reg1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "avcc_1v8_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8_s0: pldo-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc_1v8_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ avdd_1v2_s0: pldo-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-name = "avdd_1v2_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3_s0: pldo-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vcc_3v3_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vccio_sd_s0: pldo-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vccio_sd_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ pldo6_s3: pldo-reg6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "pldo6_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_0v75_s3: nldo-reg1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-name = "vdd_0v75_s3"; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <750000>; ++ }; ++ }; ++ ++ vdd_ddr_pll_s0: nldo-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-name = "vdd_ddr_pll_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <850000>; ++ }; ++ }; ++ ++ avdd_0v75_s0: nldo-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-name = "avdd_0v75_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_0v85_s0: nldo-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-name = "vdd_0v85_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_0v75_s0: nldo-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-name = "vdd_0v75_s0"; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ + &uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 10 Feb 2024 17:17:29 +0300 +Subject: arm64: dts: rockchip: Add TF card to Khadas Edge 2 + +Add TF card support to Khadas Edge 2. +The board exposes sdmmc pins via EXTIO. TF card can be used with IO +module. + +Signed-off-by: Muhammed Efe Cetin +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 34 ++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -12,6 +12,7 @@ / { + + aliases { + mmc0 = &sdhci; ++ mmc1 = &sdmmc; + }; + + chosen { +@@ -36,6 +37,19 @@ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; ++ ++ vdd_3v3_sd: vdd-3v3-sd-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd_3v3_sd"; ++ gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>; ++ regulator-boot-on; ++ enable-active-high; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_3v3_s3>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vdd_sd_en>; ++ }; + }; + + &cpu_b0 { +@@ -110,6 +124,14 @@ regulator-state-mem { + }; + }; + ++&pinctrl { ++ vdd_sd { ++ vdd_sd_en: vdd-sd-en { ++ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; ++ + &sdhci { + bus-width = <8>; + no-sdio; +@@ -120,6 +142,18 @@ &sdhci { + status = "okay"; + }; + ++&sdmmc { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ disable-wp; ++ no-mmc; ++ no-sdio; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vdd_3v3_sd>; ++ vqmmc-supply = <&vccio_sd_s0>; ++ status = "okay"; ++}; ++ + &spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 10 Feb 2024 17:34:15 +0300 +Subject: arm64: dts: rockchip: USB2, USB3 Host, PCIe2 to Khadas Edge 2 + +Khadas Edge 2 has 1x USB2 with hub, 1x USB3 Host and 1x USB-C. +This commit adds support for PCIe2, USB3 Host and USB2. + +Signed-off-by: Muhammed Efe Cetin +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 97 ++++++++++ + 1 file changed, 97 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -38,6 +38,33 @@ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + vin-supply = <&vcc5v0_sys>; + }; + ++ vcc5v0_host: vcc5v0-host-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_host"; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_host_en>; ++ vin-supply = <&vcc5v0_sys>; ++ }; ++ ++ vcc3v3_pcie_wl: vcc3v3-pcie-wl-regulator { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie2_2_vcc3v3_en>; ++ regulator-name = "vcc3v3_pcie_wl"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ startup-delay-us = <5000>; ++ vin-supply = <&vcc5v0_sys>; ++ }; ++ + vdd_3v3_sd: vdd-3v3-sd-regulator { + compatible = "regulator-fixed"; + regulator-name = "vdd_3v3_sd"; +@@ -84,6 +111,14 @@ &cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; + }; + ++&combphy0_ps { ++ status = "okay"; ++}; ++ ++&combphy2_psu { ++ status = "okay"; ++}; ++ + &i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; +@@ -130,6 +165,30 @@ vdd_sd_en: vdd-sd-en { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; ++ ++ pcie2 { ++ pcie2_2_rst: pcie2-2-rst { ++ rockchip,pins = <3 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ pcie2_2_vcc3v3_en: pcie2-2-vcc-en { ++ rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ usb { ++ vcc5v0_host_en: vcc5v0-host-en { ++ rockchip,pins = <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&pcie2x1l2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pcie2_2_rst>; ++ reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; ++ vpcie3v3-supply = <&vcc3v3_pcie_wl>; ++ status = "okay"; + }; + + &sdhci { +@@ -483,3 +542,41 @@ &uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; + }; ++ ++&u2phy2 { ++ status = "okay"; ++}; ++ ++&u2phy2_host { ++ phy-supply = <&vcc5v0_host>; ++ status = "okay"; ++}; ++ ++&u2phy3 { ++ status = "okay"; ++}; ++ ++&u2phy3_host { ++ phy-supply = <&vcc5v0_host>; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&usb_host2_xhci { ++ status = "okay"; ++}; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 10 Feb 2024 18:13:56 +0300 +Subject: arm64: dts: rockchip: Add ir receiver and leds to Khadas Edge 2 + +Khadas Edge 2 exposes IR receiver pins as same as TF card via EXTIO. The +IR receiver is connected to MCU and SoC. + +The board also has 2 PWM RGB leds. One is controlled by MCU and the +other is controlled by SoC. This commit adds support for the led +controlled by SoC using pwm-leds. + +Signed-off-by: Muhammed Efe Cetin +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 66 ++++++++++ + 1 file changed, 66 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -4,6 +4,7 @@ + + #include + #include ++#include + #include "rk3588s.dtsi" + + / { +@@ -19,6 +20,47 @@ chosen { + stdout-path = "serial2:1500000n8"; + }; + ++ ir-receiver { ++ compatible = "gpio-ir-receiver"; ++ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ir_receiver_pin>; ++ }; ++ ++ leds { ++ compatible = "pwm-leds"; ++ ++ red_led: led-0 { ++ label = "red_led"; ++ linux,default-trigger = "none"; ++ default-state = "off"; ++ function = LED_FUNCTION_INDICATOR; ++ color = ; ++ max-brightness = <255>; ++ pwms = <&pwm11 0 25000 0>; ++ }; ++ ++ green_led: led-1 { ++ label = "green_led"; ++ linux,default-trigger = "default-on"; ++ default-state = "on"; ++ function = LED_FUNCTION_POWER; ++ color = ; ++ max-brightness = <255>; ++ pwms = <&pwm14 0 25000 0>; ++ }; ++ ++ blue_led: led-2 { ++ label = "blue_led"; ++ linux,default-trigger = "none"; ++ default-state = "off"; ++ function = LED_FUNCTION_INDICATOR; ++ color = ; ++ max-brightness = <255>; ++ pwms = <&pwm15 0 25000 0>; ++ }; ++ }; ++ + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; +@@ -181,6 +223,12 @@ vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; ++ ++ ir-receiver { ++ ir_receiver_pin: ir-receiver-pin { ++ rockchip,pins = <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; + }; + + &pcie2x1l2 { +@@ -191,6 +239,24 @@ &pcie2x1l2 { + status = "okay"; + }; + ++&pwm11 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm11m1_pins>; ++ status = "okay"; ++}; ++ ++&pwm14 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm14m1_pins>; ++ status = "okay"; ++}; ++ ++&pwm15 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwm15m1_pins>; ++ status = "okay"; ++}; ++ + &sdhci { + bus-width = <8>; + no-sdio; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 10 Feb 2024 18:15:44 +0300 +Subject: arm64: dts: rockchip: Add saradc and adc buttons to Khadas Edge 2 and + enable tsadc + +This commit enables tsadc, saradc and the +function button on saradc line for Khadas Edge 2. + +Signed-off-by: Muhammed Efe Cetin +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 24 ++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -3,6 +3,7 @@ + /dts-v1/; + + #include ++#include + #include + #include + #include "rk3588s.dtsi" +@@ -20,6 +21,20 @@ chosen { + stdout-path = "serial2:1500000n8"; + }; + ++ adc-keys { ++ compatible = "adc-keys"; ++ io-channels = <&saradc 1>; ++ io-channel-names = "buttons"; ++ keyup-threshold-microvolt = <1800000>; ++ poll-interval = <100>; ++ ++ button-function { ++ label = "Function"; ++ linux,code = ; ++ press-threshold-microvolt = <17000>; ++ }; ++ }; ++ + ir-receiver { + compatible = "gpio-ir-receiver"; + gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>; +@@ -257,6 +272,11 @@ &pwm15 { + status = "okay"; + }; + ++&saradc { ++ vref-supply = <&avcc_1v8_s0>; ++ status = "okay"; ++}; ++ + &sdhci { + bus-width = <8>; + no-sdio; +@@ -604,6 +624,10 @@ regulator-state-mem { + }; + }; + ++&tsadc { ++ status = "okay"; ++}; ++ + &uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 10 Feb 2024 18:17:54 +0300 +Subject: arm64: dts: rockchip: Add SFC to Khadas Edge 2 + +This commit adds SPI flash support for Khadas Edge 2. + +Signed-off-by: Muhammed Efe Cetin +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 14 ++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -299,6 +299,20 @@ &sdmmc { + status = "okay"; + }; + ++&sfc { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&fspim2_pins>; ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0x0>; ++ spi-max-frequency = <100000000>; ++ spi-rx-bus-width = <4>; ++ spi-tx-bus-width = <1>; ++ }; ++}; ++ + &spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 10 Feb 2024 18:23:14 +0300 +Subject: arm64: dts: rockchip: Add UART9 (bluetooth) to Khadas Edge 2 + +Khadas Edge 2 has onboard AP6275P Wi-Fi6 (PCIe2) and BT5 (UART9) module. +This commit enables UART9. + +Signed-off-by: Muhammed Efe Cetin +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 20 ++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -244,6 +244,20 @@ ir_receiver_pin: ir-receiver-pin { + rockchip,pins = <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; ++ ++ wireless-bluetooth { ++ bt_reset_pin: bt-reset-pin { ++ rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ ++ bt_wake_pin: bt-wake-pin { ++ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ bt_wake_host_irq: bt-wake-host-irq { ++ rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ }; + }; + + &pcie2x1l2 { +@@ -647,6 +661,12 @@ &uart2 { + status = "okay"; + }; + ++&uart9 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart9m2_xfer &uart9m2_ctsn>; ++ status = "okay"; ++}; ++ + &u2phy2 { + status = "okay"; + }; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sun, 11 Feb 2024 16:16:11 +0300 +Subject: arm64: dts: rockchip: Add RTC to Khadas Edge 2 + +Khadas Edge 2 has PT7C4363 RTC that compatible with HYM8563. +The RTC pinctrl is also connected to MCU. + +Signed-off-by: Muhammed Efe Cetin +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 12 ++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -216,6 +216,18 @@ regulator-state-mem { + }; + }; + ++&i2c2 { ++ status = "okay"; ++ ++ hym8563: rtc@51 { ++ compatible = "haoyu,hym8563"; ++ reg = <0x51>; ++ #clock-cells = <0>; ++ clock-output-names = "hym8563"; ++ wakeup-source; ++ }; ++}; ++ + &pinctrl { + vdd_sd { + vdd_sd_en: vdd-sd-en { +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Mon, 12 Feb 2024 17:35:13 +0300 +Subject: arm64: dts: rockchip: Add USB-C to Khadas Edge 2 + +Khadas Edge 2 has 2x Type-C port. One just supports PD and +controlled by MCU. The other one supports PD, DP Alt mode and DRD. This +commit adds support for DRD. + +Signed-off-by: Muhammed Efe Cetin +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 120 ++++++++++ + 1 file changed, 120 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include "rk3588s.dtsi" + + / { +@@ -109,6 +110,18 @@ vcc5v0_host: vcc5v0-host-regulator { + vin-supply = <&vcc5v0_sys>; + }; + ++ vbus5v0_typec: vbus5v0-typec-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vbus5v0_typec"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&vcc5v0_sys>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&typec5v_pwren>; ++ }; ++ + vcc3v3_pcie_wl: vcc3v3-pcie-wl-regulator { + compatible = "regulator-fixed"; + enable-active-high; +@@ -219,6 +232,56 @@ regulator-state-mem { + &i2c2 { + status = "okay"; + ++ usbc0: usb-typec@22 { ++ compatible = "fcs,fusb302"; ++ reg = <0x22>; ++ interrupt-parent = <&gpio1>; ++ interrupts = ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usbc0_int>; ++ vbus-supply = <&vbus5v0_typec>; ++ status = "okay"; ++ ++ usb_con: connector { ++ compatible = "usb-c-connector"; ++ label = "USB-C"; ++ data-role = "dual"; ++ power-role = "dual"; ++ try-power-role = "source"; ++ op-sink-microwatt = <1000000>; ++ sink-pdos = ; ++ source-pdos = ; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ usbc0_orien_sw: endpoint { ++ remote-endpoint = <&usbdp_phy0_orientation_switch>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ usbc0_role_sw: endpoint { ++ remote-endpoint = <&dwc3_0_role_switch>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ dp_altmode_mux: endpoint { ++ remote-endpoint = <&usbdp_phy0_dp_altmode_mux>; ++ }; ++ }; ++ }; ++ }; ++ }; ++ + hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; +@@ -251,6 +314,16 @@ vcc5v0_host_en: vcc5v0-host-en { + }; + }; + ++ usb-typec { ++ usbc0_int: usbc0-int { ++ rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ typec5v_pwren: typec5v-pwren { ++ rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ + ir-receiver { + ir_receiver_pin: ir-receiver-pin { + rockchip,pins = <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; +@@ -679,6 +752,15 @@ &uart9 { + status = "okay"; + }; + ++&u2phy0 { ++ status = "okay"; ++}; ++ ++&u2phy0_otg { ++ status = "okay"; ++}; ++ ++ + &u2phy2 { + status = "okay"; + }; +@@ -705,6 +787,44 @@ &usb_host0_ohci { + status = "okay"; + }; + ++&usbdp_phy0 { ++ orientation-switch; ++ mode-switch; ++ svid = <0xff01>; ++ sbu1-dc-gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_HIGH>; ++ sbu2-dc-gpios = <&gpio4 RK_PA1 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ usbdp_phy0_orientation_switch: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&usbc0_orien_sw>; ++ }; ++ ++ usbdp_phy0_dp_altmode_mux: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&dp_altmode_mux>; ++ }; ++ }; ++}; ++ ++&usb_host0_xhci { ++ usb-role-switch; ++ status = "okay"; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ dwc3_0_role_switch: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&usbc0_role_sw>; ++ }; ++ }; ++}; ++ + &usb_host1_ehci { + status = "okay"; + }; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Mon, 12 Feb 2024 17:35:13 +0300 +Subject: arm64: dts: rockchip: Add bluetooth rfkill to Khadas Edge 2 + +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -77,6 +77,15 @@ blue_led: led-2 { + }; + }; + ++ bluetooth-rfkill { ++ compatible = "rfkill-gpio"; ++ label = "rfkill-bluetooth"; ++ radio-type = "bluetooth"; ++ shutdown-gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bt_reset_pin>; ++ }; ++ + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Mon, 19 Feb 2024 23:32:11 +0300 +Subject: arm64: dts: rockchip: Add HDMI & VOP2 to Khadas Edge 2 + +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 36 ++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include "rk3588s.dtsi" + + / { +@@ -821,6 +822,7 @@ usbdp_phy0_dp_altmode_mux: endpoint@1 { + }; + + &usb_host0_xhci { ++ dr-mode = "otg"; + usb-role-switch; + status = "okay"; + +@@ -845,3 +847,37 @@ &usb_host1_ohci { + &usb_host2_xhci { + status = "okay"; + }; ++ ++&hdmi0 { ++ status = "okay"; ++}; ++ ++&hdptxphy_hdmi0 { ++ status = "okay"; ++}; ++ ++&display_subsystem { ++ clocks = <&hdptxphy_hdmi0>; ++ clock-names = "hdmi0_phy_pll"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&hdmi0_in { ++ hdmi0_in_vp0: endpoint { ++ remote-endpoint = <&vp0_out_hdmi0>; ++ }; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vp0 { ++ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { ++ reg = ; ++ remote-endpoint = <&hdmi0_in_vp0>; ++ }; ++}; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 2 Mar 2024 19:13:59 +0300 +Subject: arm64: dts: rockchip: Add AP6275P wireless support to Khadas Edge 2 + +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 17 ++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -361,6 +361,23 @@ &pcie2x1l2 { + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie_wl>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0x400000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ranges; ++ device_type = "pci"; ++ bus-range = <0x40 0x4f>; ++ ++ wifi: wifi@0,0 { ++ compatible = "pci14e4,449d"; ++ reg = <0x410000 0 0 0 0>; ++ clocks = <&hym8563>; ++ clock-names = "32k"; ++ }; ++ }; ++ + }; + + &pwm11 { +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 2 Mar 2024 19:26:09 +0300 +Subject: arm64: dts: rockchip: Add cpufreq support to Khadas Edge 2 + +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 12 ++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -161,34 +161,42 @@ vdd_3v3_sd: vdd-3v3-sd-regulator { + + &cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; ++ mem-supply = <&vdd_cpu_big0_mem_s0>; + }; + + &cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; ++ mem-supply = <&vdd_cpu_big0_mem_s0>; + }; + + &cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; ++ mem-supply = <&vdd_cpu_big1_mem_s0>; + }; + + &cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; ++ mem-supply = <&vdd_cpu_big1_mem_s0>; + }; + + &cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; ++ mem-supply = <&vdd_cpu_lit_mem_s0>; + }; + + &cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; ++ mem-supply = <&vdd_cpu_lit_mem_s0>; + }; + + &cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; ++ mem-supply = <&vdd_cpu_lit_mem_s0>; + }; + + &cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; ++ mem-supply = <&vdd_cpu_lit_mem_s0>; + }; + + &combphy0_ps { +@@ -204,7 +212,7 @@ &i2c0 { + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + +- vdd_cpu_big0_s0: regulator@42 { ++ vdd_cpu_big0_s0: vdd_cpu_big0_mem_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; +@@ -221,7 +229,7 @@ regulator-state-mem { + }; + }; + +- vdd_cpu_big1_s0: regulator@43 { ++ vdd_cpu_big1_s0: vdd_cpu_big1_mem_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 23 Mar 2024 16:09:41 +0300 +Subject: arm64: dts: rockchip: Add GPU to Khadas Edge 2 + +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -505,6 +505,7 @@ rk806_dvs3_null: dvs3-null-pins { + + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { ++ regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; +@@ -873,6 +874,11 @@ &usb_host2_xhci { + status = "okay"; + }; + ++&gpu { ++ mali-supply = <&vdd_gpu_s0>; ++ status = "okay"; ++}; ++ + &hdmi0 { + status = "okay"; + }; +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1041-board-khadas-edge2-mcu.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1041-board-khadas-edge2-mcu.patch new file mode 100644 index 000000000000..05ed0084e734 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1041-board-khadas-edge2-mcu.patch @@ -0,0 +1,441 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Wed, 6 Mar 2024 00:09:25 +0300 +Subject: mfd: khadas-mcu: add Edge2 registers + +--- + drivers/mfd/khadas-mcu.c | 8 +++- + include/linux/mfd/khadas-mcu.h | 24 ++++++++++ + 2 files changed, 30 insertions(+), 2 deletions(-) + +diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c +index 111111111111..222222222222 100644 +--- a/drivers/mfd/khadas-mcu.c ++++ b/drivers/mfd/khadas-mcu.c +@@ -26,6 +26,10 @@ static bool khadas_mcu_reg_volatile(struct device *dev, unsigned int reg) + case KHADAS_MCU_CHECK_USER_PASSWD_REG: + case KHADAS_MCU_WOL_INIT_START_REG: + case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG: ++ case KHADAS_MCU_LED_ON_RAM_REG: ++ case KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG_V2: ++ case KHADAS_MCU_WDT_EN_REG: ++ case KHADAS_MCU_SYS_RST_REG: + return true; + default: + return false; +@@ -69,14 +73,14 @@ static const struct regmap_config khadas_mcu_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, +- .max_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG, ++ .max_register = KHADAS_MCU_SYS_RST_REG, + .volatile_reg = khadas_mcu_reg_volatile, + .writeable_reg = khadas_mcu_reg_writeable, + .cache_type = REGCACHE_RBTREE, + }; + + static struct mfd_cell khadas_mcu_fan_cells[] = { +- /* VIM1/2 Rev13+ and VIM3 only */ ++ /* VIM1/2 Rev13+, VIM3 and Edge2 only */ + { .name = "khadas-mcu-fan-ctrl", }, + }; + +diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h +index 111111111111..222222222222 100644 +--- a/include/linux/mfd/khadas-mcu.h ++++ b/include/linux/mfd/khadas-mcu.h +@@ -35,26 +35,45 @@ + #define KHADAS_MCU_FACTORY_TEST_REG 0x16 /* R */ + #define KHADAS_MCU_BOOT_MODE_REG 0x20 /* RW */ + #define KHADAS_MCU_BOOT_EN_WOL_REG 0x21 /* RW */ ++#define KHADAS_MCU_BOOT_EN_DCIN_REG_V2 0x21 /* RW */ + #define KHADAS_MCU_BOOT_EN_RTC_REG 0x22 /* RW */ + #define KHADAS_MCU_BOOT_EN_EXP_REG 0x23 /* RW */ ++#define KHADAS_MCU_LED_MODE_ON_REG_V2 0x23 /* RW */ ++#define KHADAS_MCU_LED_MODE_OFF_REG_V2 0x24 /* RW */ + #define KHADAS_MCU_BOOT_EN_IR_REG 0x24 /* RW */ + #define KHADAS_MCU_BOOT_EN_DCIN_REG 0x25 /* RW */ ++#define KHADAS_MCU_RGB_ON_R_REG 0x25 /* RW */ ++#define KHADAS_MCU_RGB_ON_G_REG 0x26 /* RW */ + #define KHADAS_MCU_BOOT_EN_KEY_REG 0x26 /* RW */ ++#define KHADAS_MCU_RGB_ON_B_REG 0x27 /* RW */ + #define KHADAS_MCU_KEY_MODE_REG 0x27 /* RW */ ++#define KHADAS_MCU_RGB_OFF_R_REG 0x28 /* RW */ + #define KHADAS_MCU_LED_MODE_ON_REG 0x28 /* RW */ ++#define KHADAS_MCU_RGB_OFF_G_REG 0x29 /* RW */ + #define KHADAS_MCU_LED_MODE_OFF_REG 0x29 /* RW */ ++#define KHADAS_MCU_RGB_OFF_B_REG 0x2a /* RW */ + #define KHADAS_MCU_SHUTDOWN_NORMAL_REG 0x2c /* RW */ + #define KHADAS_MCU_MAC_SWITCH_REG 0x2d /* RW */ ++#define KHADAS_MCU_REST_CONF_REG 0x2e /* RW */ + #define KHADAS_MCU_MCU_SLEEP_MODE_REG 0x2e /* RW */ ++#define KHADAS_MCU_BOOT_EN_IR_REG_V2 0x2f /* RW */ + #define KHADAS_MCU_IR_CODE1_0_REG 0x2f /* RW */ + #define KHADAS_MCU_IR_CODE1_1_REG 0x30 /* RW */ ++#define KHADAS_MCU_IR1_CUST1_REG 0x30 /* RW */ + #define KHADAS_MCU_IR_CODE1_2_REG 0x31 /* RW */ ++#define KHADAS_MCU_IR1_CUST2_REG 0x31 /* RW */ + #define KHADAS_MCU_IR_CODE1_3_REG 0x32 /* RW */ ++#define KHADAS_MCU_IR1_ORDER1_REG 0x32 /* RW */ + #define KHADAS_MCU_USB_PCIE_SWITCH_REG 0x33 /* RW */ ++#define KHADAS_MCU_IR1_ORDER2_REG 0x33 /* RW */ ++#define KHADAS_MCU_IR2_CUST1_REG 0x34 /* RW */ + #define KHADAS_MCU_IR_CODE2_0_REG 0x34 /* RW */ + #define KHADAS_MCU_IR_CODE2_1_REG 0x35 /* RW */ ++#define KHADAS_MCU_IR2_CUST2_REG 0x35 /* RW */ + #define KHADAS_MCU_IR_CODE2_2_REG 0x36 /* RW */ ++#define KHADAS_MCU_IR2_ORDER1_REG 0x36 /* RW */ + #define KHADAS_MCU_IR_CODE2_3_REG 0x37 /* RW */ ++#define KHADAS_MCU_IR2_ORDER2_REG 0x36 /* RW */ + #define KHADAS_MCU_PASSWD_USER_0_REG 0x40 /* RW */ + #define KHADAS_MCU_PASSWD_USER_1_REG 0x41 /* RW */ + #define KHADAS_MCU_PASSWD_USER_2_REG 0x42 /* RW */ +@@ -69,6 +88,10 @@ + #define KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG 0x86 /* RO */ + #define KHADAS_MCU_WOL_INIT_START_REG 0x87 /* WO */ + #define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG 0x88 /* WO */ ++#define KHADAS_MCU_LED_ON_RAM_REG 0x89 /* WO */ ++#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG_V2 0x8A /* WO */ ++#define KHADAS_MCU_WDT_EN_REG 0x8B /* WO */ ++#define KHADAS_MCU_SYS_RST_REG 0x91 /* WO */ + + enum { + KHADAS_BOARD_VIM1 = 0x1, +@@ -76,6 +99,7 @@ enum { + KHADAS_BOARD_VIM3, + KHADAS_BOARD_EDGE = 0x11, + KHADAS_BOARD_EDGE_V, ++ KHADAS_BOARD_EDGE2, + }; + + /** +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Wed, 6 Mar 2024 00:09:58 +0300 +Subject: mfd: khadas-mcu: drop unused code + +--- + drivers/mfd/khadas-mcu.c | 11 ---------- + 1 file changed, 11 deletions(-) + +diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c +index 111111111111..222222222222 100644 +--- a/drivers/mfd/khadas-mcu.c ++++ b/drivers/mfd/khadas-mcu.c +@@ -84,10 +84,6 @@ static struct mfd_cell khadas_mcu_fan_cells[] = { + { .name = "khadas-mcu-fan-ctrl", }, + }; + +-static struct mfd_cell khadas_mcu_cells[] = { +- { .name = "khadas-mcu-user-mem", }, +-}; +- + static int khadas_mcu_probe(struct i2c_client *client) + { + struct device *dev = &client->dev; +@@ -109,13 +105,6 @@ static int khadas_mcu_probe(struct i2c_client *client) + return ret; + } + +- ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, +- khadas_mcu_cells, +- ARRAY_SIZE(khadas_mcu_cells), +- NULL, 0, NULL); +- if (ret) +- return ret; +- + if (of_property_present(dev->of_node, "#cooling-cells")) + return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + khadas_mcu_fan_cells, +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Wed, 6 Mar 2024 00:13:10 +0300 +Subject: thermal: khadas_mcu_fan: add support for Khadas Edge 2 + +--- + drivers/thermal/khadas_mcu_fan.c | 77 +++++++++- + 1 file changed, 73 insertions(+), 4 deletions(-) + +diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c +index 111111111111..222222222222 100644 +--- a/drivers/thermal/khadas_mcu_fan.c ++++ b/drivers/thermal/khadas_mcu_fan.c +@@ -15,10 +15,16 @@ + #include + + #define MAX_LEVEL 3 ++#define MAX_SPEED 0x64 + + struct khadas_mcu_fan_ctx { + struct khadas_mcu *mcu; + unsigned int level; ++ ++ unsigned int fan_max_level; ++ unsigned int fan_register; ++ unsigned int *fan_cooling_levels; ++ + struct thermal_cooling_device *cdev; + }; + +@@ -26,9 +32,21 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx, + unsigned int level) + { + int ret; ++ unsigned int write_level = level; ++ ++ if (level > ctx->fan_max_level) ++ return -EINVAL; ++ ++ if (ctx->fan_cooling_levels != NULL) { ++ write_level = ctx->fan_cooling_levels[level]; ++ ++ if (write_level > MAX_SPEED) ++ return -EINVAL; ++ } ++ ++ ret = regmap_write(ctx->mcu->regmap, ctx->fan_register, ++ write_level); + +- ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG, +- level); + if (ret) + return ret; + +@@ -40,7 +58,9 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx, + static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev, + unsigned long *state) + { +- *state = MAX_LEVEL; ++ struct khadas_mcu_fan_ctx *ctx = cdev->devdata; ++ ++ *state = ctx->fan_max_level; + + return 0; + } +@@ -61,7 +81,7 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev, + { + struct khadas_mcu_fan_ctx *ctx = cdev->devdata; + +- if (state > MAX_LEVEL) ++ if (state > ctx->fan_max_level) + return -EINVAL; + + if (state == ctx->level) +@@ -76,6 +96,48 @@ static const struct thermal_cooling_device_ops khadas_mcu_fan_cooling_ops = { + .set_cur_state = khadas_mcu_fan_set_cur_state, + }; + ++// Khadas Edge 2 sets fan level by passing fan speed(0-100). So we need different logic here like pwm-fan cooling-levels. ++// This is optional and just necessary for Edge 2. ++static int khadas_mcu_fan_get_cooling_data_edge2(struct khadas_mcu_fan_ctx *ctx, struct device *dev) { ++ struct device_node *np = ctx->mcu->dev->of_node; ++ int num, i, ret; ++ ++ if (!of_property_present(np, "cooling-levels")) ++ return 0; ++ ++ ret = of_property_count_u32_elems(np, "cooling-levels"); ++ if (ret <= 0) { ++ dev_err(dev, "Wrong data!\n"); ++ return ret ? : -EINVAL; ++ } ++ ++ num = ret; ++ ctx->fan_cooling_levels = devm_kcalloc(dev, num, sizeof(u32), ++ GFP_KERNEL); ++ if (!ctx->fan_cooling_levels) ++ return -ENOMEM; ++ ++ ret = of_property_read_u32_array(np, "cooling-levels", ++ ctx->fan_cooling_levels, num); ++ if (ret) { ++ dev_err(dev, "Property 'cooling-levels' cannot be read!\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < num; i++) { ++ if (ctx->fan_cooling_levels[i] > MAX_SPEED) { ++ dev_err(dev, "PWM fan state[%d]:%d > %d\n", i, ++ ctx->fan_cooling_levels[i], MAX_SPEED); ++ return -EINVAL; ++ } ++ } ++ ++ ctx->fan_max_level = num - 1; ++ ctx->fan_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG_V2; ++ ++ return 0; ++} ++ + static int khadas_mcu_fan_probe(struct platform_device *pdev) + { + struct khadas_mcu *mcu = dev_get_drvdata(pdev->dev.parent); +@@ -90,6 +152,13 @@ static int khadas_mcu_fan_probe(struct platform_device *pdev) + ctx->mcu = mcu; + platform_set_drvdata(pdev, ctx); + ++ ctx->fan_max_level = MAX_LEVEL; ++ ctx->fan_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG; ++ ++ ret = khadas_mcu_fan_get_cooling_data_edge2(ctx, dev); ++ if (ret) ++ return ret; ++ + cdev = devm_thermal_of_cooling_device_register(dev->parent, + dev->parent->of_node, "khadas-mcu-fan", ctx, + &khadas_mcu_fan_cooling_ops); +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Wed, 6 Mar 2024 00:14:58 +0300 +Subject: dt-bindings: mfd: khadas-mcu: add cooling-levels property + +--- + Documentation/devicetree/bindings/mfd/khadas,mcu.yaml | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml +index 111111111111..222222222222 100644 +--- a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml ++++ b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml +@@ -11,7 +11,7 @@ maintainers: + + description: | + Khadas embeds a microcontroller on their VIM and Edge boards adding some +- system feature as PWM Fan control (for VIM2 rev14 or VIM3), User memory ++ system feature as PWM Fan control (for VIM2 rev14, VIM3, Edge2), User memory + storage, IR/Key resume control, system power LED control and more. + + properties: +@@ -22,6 +22,11 @@ properties: + "#cooling-cells": # Only needed for boards having FAN control feature + const: 2 + ++ cooling-levels: ++ description: Max speed of PWM fan. This property is necessary for Khadas Edge 2. ++ items: ++ maximum: 100 ++ + reg: + maxItems: 1 + +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Wed, 6 Mar 2024 00:17:58 +0300 +Subject: arm64: dts: rockchip: Add MCU to Khadas Edge 2 + +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -307,6 +307,13 @@ hym8563: rtc@51 { + clock-output-names = "hym8563"; + wakeup-source; + }; ++ ++ khadas_mcu: system-controller@18 { ++ compatible = "khadas,mcu"; ++ reg = <0x18>; ++ cooling-levels = <0 50 72 100>; ++ #cooling-cells = <2>; ++ }; + }; + + &pinctrl { +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Mon, 25 Mar 2024 22:41:26 +0300 +Subject: arm64: dts: rockchip: Add automatic fan control to Khadas Edge 2 + +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 56 ++++++++++ + 1 file changed, 56 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -316,6 +316,62 @@ khadas_mcu: system-controller@18 { + }; + }; + ++&package_thermal { ++ polling-delay = <1000>; ++ ++ trips { ++ package_fan0: package-fan0 { ++ temperature = <45000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ package_fan1: package-fan1 { ++ temperature = <55000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ package_fan2: package-fan2 { ++ temperature = <60000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ package_fan3: package-fan3 { ++ temperature = <70000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&package_fan0>; ++ cooling-device = <&khadas_mcu 0 1>; ++ contribution = <1024>; ++ }; ++ ++ map1 { ++ trip = <&package_fan1>; ++ cooling-device = <&khadas_mcu 1 2>; ++ contribution = <1024>; ++ }; ++ ++ map2 { ++ trip = <&package_fan2>; ++ cooling-device = <&khadas_mcu 2 3>; ++ contribution = <1024>; ++ }; ++ ++ map3 { ++ trip = <&package_fan3>; ++ cooling-device = <&khadas_mcu 3 THERMAL_NO_LIMIT>; ++ contribution = <1024>; ++ }; ++ }; ++}; ++ + &pinctrl { + vdd_sd { + vdd_sd_en: vdd-sd-en { +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1047-fix-initial-PERST#-GPIO-value.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1047-fix-initial-PERST#-GPIO-value.patch new file mode 100644 index 000000000000..8212b6261b87 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1047-fix-initial-PERST#-GPIO-value.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: yangchaohong <45483831+yangchaohong@users.noreply.github.com> +Date: Wed, 1 May 2024 08:30:43 +0100 +Subject: [ARCHEOLOGY] Fix PCIe for RK35xx+Fix ROCK5A PCIe device tree + +> X-Git-Archeology: - Revision b1f648ee755de73a922a33d6a432f310ea4ff3e0: https://github.com/armbian/build/commit/b1f648ee755de73a922a33d6a432f310ea4ff3e0 +> X-Git-Archeology: Date: Wed, 01 May 2024 08:30:43 +0100 +> X-Git-Archeology: From: yangchaohong <45483831+yangchaohong@users.noreply.github.com> +> X-Git-Archeology: Subject: Fix PCIe for RK35xx+Fix ROCK5A PCIe device tree +> X-Git-Archeology: +--- + drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c +index 111111111111..222222222222 100644 +--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c ++++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c +@@ -240,7 +240,7 @@ static int rockchip_pcie_resource_get(struct platform_device *pdev, + return PTR_ERR(rockchip->apb_base); + + rockchip->rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", +- GPIOD_OUT_HIGH); ++ GPIOD_OUT_LOW); + if (IS_ERR(rockchip->rst_gpio)) + return PTR_ERR(rockchip->rst_gpio); + +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-armsom-sige7.dts b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-armsom-sige7.dts new file mode 100644 index 000000000000..bee75afd5fa6 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-armsom-sige7.dts @@ -0,0 +1,767 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include +#include +#include +#include "rk3588.dtsi" + +/ { + model = "ArmSoM Sige7"; + compatible = "armsom,sige7", "rockchip,rk3588"; + + aliases { + mmc0 = &sdhci; + mmc1 = &sdmmc; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + analog-sound { + compatible = "audio-graph-card"; + dais = <&i2s0_8ch_p0>; + label = "rk3588-es8316"; + hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&hp_detect>; + routing = "MIC2", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR"; + widgets = "Microphone", "Mic Jack", + "Headphone", "Headphones"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_rgb_g>; + + led_green: led-0 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + + led_red: led-1 { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio4 RK_PC5 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "none"; + }; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + cooling-levels = <0 95 145 195 255>; + fan-supply = <&vcc5v0_sys>; + pwms = <&pwm1 0 50000 0>; + #cooling-cells = <2>; + }; + + vcc3v3_pcie2x1l2: vcc3v3-pcie2x1l2-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pcie2x1l2"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <5000>; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc3v3_pcie30: vcc3v3-pcie30-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>; + regulator-name = "vcc3v3_pcie30"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <5000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy1_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + status = "okay"; +}; + +&hdmi0 { + status = "okay"; +}; + +&hdmi0_in { + hdmi0_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi0>; + }; +}; + +&hdptxphy_hdmi0 { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + + vdd_cpu_big0_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c6 { + status = "okay"; + + hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + interrupt-parent = <&gpio0>; + interrupts = ; + #clock-cells = <0>; + clock-output-names = "hym8563"; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + wakeup-source; + }; +}; + +&i2c7 { + status = "okay"; + + es8316: audio-codec@11 { + compatible = "everest,es8316"; + reg = <0x11>; + assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; + assigned-clock-rates = <12288000>; + clocks = <&cru I2S0_8CH_MCLKOUT>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + + port { + es8316_p0_0: endpoint { + remote-endpoint = <&i2s0_8ch_p0_0>; + }; + }; + }; +}; + +&i2s0_8ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_lrck + &i2s0_mclk + &i2s0_sclk + &i2s0_sdi0 + &i2s0_sdo0>; + status = "okay"; + + i2s0_8ch_p0: port { + i2s0_8ch_p0_0: endpoint { + dai-format = "i2s"; + mclk-fs = <256>; + remote-endpoint = <&es8316_p0_0>; + }; + }; +}; + +/* phy1 - right ethernet port */ +&pcie2x1l0 { + reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +/* phy2 - WiFi */ +&pcie2x1l1 { + reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>; + status = "okay"; + + pcie@0,0 { + reg = <0x300000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + device_type = "pci"; + bus-range = <0x30 0x3f>; + + wifi: wifi@0,0 { + compatible = "pci14e4,449d"; + reg = <0x310000 0 0 0 0>; + clocks = <&hym8563>; + clock-names = "32k"; + }; + }; +}; + +/* phy0 - left ethernet port */ +&pcie2x1l2 { + reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&pcie30phy { + status = "okay"; +}; + +&pcie3x4 { + reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie30>; + status = "okay"; +}; + +&pinctrl { + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + leds { + led_rgb_g: led-rgb-g { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + led_rgb_r: led-rgb-r { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sound { + hp_detect: hp-detect { + rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm1 { + status = "okay"; +}; + +&saradc { + vref-supply = <&avcc_1v8_s0>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + mmc-hs200-1_8v; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + max-frequency = <200000000>; + no-sdio; + no-mmc; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_s3>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&spi2 { + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + num-cs = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + status = "okay"; + + pmic@0 { + compatible = "rockchip,rk806"; + spi-max-frequency = <1000000>; + reg = <0x0>; + + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + + gpio-controller; + #gpio-cells = <2>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + + system-power-controller; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc5v0_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc5v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl1"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_gpu_s0"; + regulator-enable-ramp-delay = <400>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_lit_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_log_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_vdenc_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdd2_ddr_s3: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_2v0_pldo_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_3v3_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vddq_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "avcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s0: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avdd_1v2_s0: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "avdd_1v2_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_3v3_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vccio_sd_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + pldo6_s3: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "pldo6_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_ddr_pll_s0: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_ddr_pll_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + avdd_0v75_s0: nldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "avdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_0v85_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v75_s0: nldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; +}; + +&u2phy1 { + status = "okay"; +}; + +&u2phy1_otg { + status = "okay"; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy3_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +&usbdp_phy1 { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_xhci { + dr_mode = "host"; + status = "okay"; +}; + +&vop { + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = ; + remote-endpoint = <&hdmi0_in_vp0>; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-bananapi-m7.dts b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-bananapi-m7.dts new file mode 100644 index 000000000000..8489240ab8bd --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-bananapi-m7.dts @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include "rk3588-armsom-sige7.dts" + +/ { + model = "Banana Pi M7"; + compatible = "bananapi,m7", "rockchip,rk3588"; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-hinlink-h88k.dts b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-hinlink-h88k.dts new file mode 100644 index 000000000000..ed962d5a9ee1 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-hinlink-h88k.dts @@ -0,0 +1,858 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include +#include +#include +#include "rk3588.dtsi" + +/ { + model = "HINLINK H88K"; + compatible = "hinlink,h88k", "rockchip,rk3588"; + + aliases { + ethernet0 = &gmac0; + mmc0 = &sdhci; + mmc1 = &sdmmc; + mmc2 = &sdio; + }; + + analog-sound { + compatible = "simple-audio-card"; + label = "rockchip,es8388-codec"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_detect>; + simple-audio-card,name = "Analog"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,hp-det-gpio = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>; + simple-audio-card,bitclock-master = <&daicpu>; + simple-audio-card,frame-master = <&daicpu>; + + simple-audio-card,widgets = + "Microphone", "Onboard Microphone", + "Microphone", "Microphone Jack", + "Speaker", "Speaker", + "Headphone", "Headphones"; + + simple-audio-card,routing = + "Headphones", "LOUT1", + "Headphones", "ROUT1", + "Speaker", "LOUT2", + "Speaker", "ROUT2", + + /* single ended signal to LINPUT1 */ + "LINPUT1", "Microphone Jack", + "RINPUT1", "Microphone Jack", + /* differential signal */ + "LINPUT2", "Onboard Microphone", + "RINPUT2", "Onboard Microphone"; + + daicpu: simple-audio-card,cpu { + sound-dai = <&i2s0_8ch>; + system-clock-frequency = <12288000>; + }; + + daicodec: simple-audio-card,codec { + sound-dai = <&es8388>; + system-clock-frequency = <12288000>; + }; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_net_en>, <&led_sata_en>, + <&led_user_en>, <&led_work_en>; + + net { + label = "blue:net"; + gpios = <&gpio2 RK_PC3 GPIO_ACTIVE_HIGH>; + }; + + sata { + label = "amber:sata"; + gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>; + }; + + user { + label = "green:user"; + gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>; + }; + + work { + label = "red:work"; + gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + vcc12v_dcin: vcc12v-dcin { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-name = "vcc12v_dcin"; + }; + + vcc3v3_pcie30: vcc3v3-pcie30-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>; + regulator-name = "vcc3v3_pcie30"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <5000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_usb_hub: vcc5v0-usb-hub { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_usb_hub_en>; + regulator-name = "vcc5v0_usb_hub"; + regulator-always-on; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy1_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&gmac0 { + clock_in_out = "output"; + phy-handle = <&rgmii_phy>; + phy-mode = "rgmii-rxid"; + pinctrl-0 = <&gmac0_miim + &gmac0_tx_bus2 + &gmac0_rx_bus2 + &gmac0_rgmii_clk + &gmac0_rgmii_bus>; + pinctrl-names = "default"; + rx_delay = <0x00>; + tx_delay = <0x43>; + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + status = "okay"; +}; + +&hdmi0 { + status = "okay"; +}; + + +&hdptxphy_hdmi0 { + status = "okay"; +}; + +&hdmi0_in { + hdmi0_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi0>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + + vdd_cpu_big0_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + + hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-output-names = "hym8563"; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + interrupt-parent = <&gpio0>; + interrupts = ; + wakeup-source; + }; +}; + +&i2c7 { + pinctrl-0 = <&i2c7m0_xfer>; + status = "okay"; + + es8388: audio-codec@11 { + compatible = "everest,es8388"; + reg = <0x11>; + assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; + assigned-clock-rates = <12288000>; + AVDD-supply = <&vcc_3v3_s3>; + clocks = <&cru I2S0_8CH_MCLKOUT>; + clock-names = "mclk"; + DVDD-supply = <&vcc_1v8_s3>; + HPVDD-supply = <&vcc_3v3_s3>; + PVDD-supply = <&vcc_1v8_s3>; + #sound-dai-cells = <0>; + + port { + es8388_p0_0: endpoint { + remote-endpoint = <&i2s0_8ch_p0_0>; + }; + }; + }; +}; + +&i2s0_8ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_lrck + &i2s0_mclk + &i2s0_sclk + &i2s0_sdi0 + &i2s0_sdo0>; + status = "okay"; + + i2s0_8ch_p0: port { + i2s0_8ch_p0_0: endpoint { + dai-format = "i2s"; + mclk-fs = <256>; + remote-endpoint = <&es8388_p0_0>; + }; + }; +}; + +&mdio0 { + rgmii_phy: ethernet-phy@1 { + /* RTL8211F */ + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x1>; + pinctrl-names = "default"; + pinctrl-0 = <&rtl8211f_rst>; + reset-assert-us = <20000>; + reset-deassert-us = <100000>; + reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_LOW>; + }; +}; + +&pcie2x1l0 { + reset-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&pcie2x1l1 { + reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&pcie2x1l2 { + reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&pcie30phy { + status = "okay"; +}; + +&pcie3x4 { + pinctrl-names = "default"; + reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie30>; + status = "okay"; +}; + +&pinctrl { + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + leds { + led_net_en: led_net_en { + rockchip,pins = <2 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + led_sata_en: led_sata_en { + rockchip,pins = <2 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + led_user_en: led_user_en { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + led_work_en: led_work_en { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + rtl8211f { + rtl8211f_rst: rtl8211f-rst { + rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sound { + hp_detect: hp-detect { + rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc5v0_usb_hub_en: vcc5v0_usb_hub_en { + rockchip,pins = <4 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&saradc { + vref-supply = <&avcc_1v8_s0>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + mmc-hs200-1_8v; + status = "okay"; +}; + +&sdmmc { + max-frequency = <200000000>; + no-sdio; + no-mmc; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_s3>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + num-cs = <1>; + + pmic@0 { + compatible = "rockchip,rk806"; + spi-max-frequency = <1000000>; + reg = <0x0>; + + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + + system-power-controller; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc5v0_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc5v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + gpio-controller; + #gpio-cells = <2>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl1"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_gpu_s0"; + regulator-enable-ramp-delay = <400>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_lit_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_log_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_vdenc_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdd2_ddr_s3: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_2v0_pldo_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_3v3_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vddq_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "avcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s0: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avdd_1v2_s0: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "avdd_1v2_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_3v3_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vccio_sd_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + pldo6_s3: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "pldo6_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_ddr_pll_s0: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_ddr_pll_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + avdd_0v75_s0: nldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "avdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_0v85_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v75_s0: nldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&tsadc { + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +&u2phy1 { + status = "okay"; +}; + +&u2phy1_otg { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy2_host { + /* connected to USB hub, which is powered by vcc5v0_sys */ + phy-supply = <&vcc5v0_sys>; + status = "okay"; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy3_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&usbdp_phy1 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host1_xhci { + status = "okay"; +}; + +&usb_host2_xhci { + status = "okay"; +}; + +&vop { + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = ; + remote-endpoint = <&hdmi0_in_vp0>; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-mixtile-blade3.dts b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-mixtile-blade3.dts new file mode 100644 index 000000000000..ef0adae48ebf --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-mixtile-blade3.dts @@ -0,0 +1,712 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include +#include +#include "rk3588.dtsi" + +/ { + model = "Mixtile Blade 3"; + compatible = "mixtile,blade3", "rockchip,rk3588"; + + aliases { + mmc0 = &sdhci; + mmc1 = &sdmmc; + serial2 = &uart2; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + vcc12v_dcin: vcc12v-dcin-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc12v_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usbdcin: vcc5v0-usbdcin-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usbdcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usb: vcc5v0-usb-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usbdcin>; + }; + + pcie20_avdd0v85: pcie20-avdd0v85-regulator { + compatible = "regulator-fixed"; + regulator-name = "pcie20_avdd0v85"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + vin-supply = <&vdd_0v85_s0>; + }; + + pcie20_avdd1v8: pcie20-avdd1v8-regulator { + compatible = "regulator-fixed"; + regulator-name = "pcie20_avdd1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&avcc_1v8_s0>; + }; + + pcie30_avdd0v75: pcie30-avdd0v75-regulator { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd0v75"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + vin-supply = <&avdd_0v75_s0>; + }; + + pcie30_avdd1v8: pcie30-avdd1v8-regulator { + compatible = "regulator-fixed"; + regulator-name = "pcie30_avdd1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&avcc_1v8_s0>; + }; + + vcc3v3_pcie30: vcc3v3-pcie30-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pcie30"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + regulator-boot-on; + regulator-always-on; + gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>; + startup-delay-us = <5000>; + vin-supply = <&vcc12v_dcin>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie3_vcc3v3_en>; + }; + + vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_sd_s0"; + gpio = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_pwr>; + enable-active-high; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy1_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; + mem-supply = <&vdd_cpu_big0_mem_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; + mem-supply = <&vdd_cpu_big0_mem_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; + mem-supply = <&vdd_cpu_big1_mem_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; + mem-supply = <&vdd_cpu_big1_mem_s0>; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; + mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; + mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; + mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; + mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + + vdd_cpu_big0_s0: vdd_cpu_big0_mem_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: vdd_cpu_big1_mem_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1m2_xfer>; + status = "okay"; + + vdd_npu_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_npu_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c4 { + pinctrl-0 = <&i2c4m0_xfer>; + status = "okay"; +}; + +/* exposed on the 30-pin connector; shows up as i2c-3 */ +&i2c5 { + pinctrl-0 = <&i2c5m3_xfer>; + status = "okay"; +}; + +&i2s2_2ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s2m1_mclk + &i2s2m1_lrck + &i2s2m1_sclk + &i2s2m1_sdi + &i2s2m1_sdo>; + status = "okay"; +}; + +&pcie2x1l0 { + reset-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_0_rst>; + status = "okay"; +}; + +&pcie2x1l1 { + reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_1_rst>; + status = "okay"; +}; + +&pcie30phy { + status = "okay"; +}; + +&pcie3x4 { + reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie30>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie3_rst>; + status = "okay"; +}; + +&pinctrl { + sdmmc { + sdmmc_pwr: sdmmc-pwr { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + pcie2 { + pcie2_0_rst: pcie2-0-rst { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie2_1_rst: pcie2-1-rst { + rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pcie3 { + pcie3_rst: pcie3-rst { + rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie3_vcc3v3_en: pcie3-vcc3v3-en { + rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm8 { + pinctrl-names = "active"; + pinctrl-0 = <&pwm8m2_pins>; + status = "okay"; +}; + +&pwm14 { + pinctrl-0 = <&pwm14m2_pins>; + status = "okay"; +}; + +&pwm15 { + pinctrl-0 = <&pwm15m3_pins>; + status = "disabled"; +}; + +&spi4 { + pinctrl-names = "default"; + pinctrl-0 = <&spi4m2_cs0 &spi4m2_pins>; + num-cs = <1>; + status = "okay"; +}; + +&saradc { + status = "okay"; + vref-supply = <&vcc_1v8_s0>; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + max-frequency = <200000000>; + // hs400 causes immediate trouble, hs200 works at around 150mb/s + // mmc-hs400-1_8v; + // mmc-hs400-enhanced-strobe; + mmc-hs200-1_8v; + status = "okay"; +}; + +&sdmmc { + max-frequency = <150000000>; + no-sdio; + no-mmc; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_s3>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + num-cs = <1>; + + pmic@0 { + compatible = "rockchip,rk806"; + spi-max-frequency = <1000000>; + reg = <0x0>; + + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc5v0_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc5v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + gpio-controller; + #gpio-cells = <2>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_gpu_s0"; + regulator-enable-ramp-delay = <400>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_lit_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_log_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_vdenc_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdd2_ddr_s3: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_2v0_pldo_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_3v3_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vddq_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "avcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s0: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avdd_1v2_s0: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "avdd_1v2_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_3v3_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vccio_sd_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + pldo6_s3: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "pldo6_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_ddr_pll_s0: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_ddr_pll_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + avdd_0v75_s0: nldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "avdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_0v85_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v75_s0: nldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&tsadc { + status = "okay"; +}; + +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-nanopc-cm3588-nas.dts b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-nanopc-cm3588-nas.dts new file mode 100644 index 000000000000..f95c8a708aba --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588-nanopc-cm3588-nas.dts @@ -0,0 +1,1436 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * Copyright (c) 2023 FriendlyElec Computer Tech. Co., Ltd. + * Copyright (c) 2023 Thomas McKahan + * Author: ColorfulRhino + * + */ + +/dts-v1/; + +#include +#include +#include +#include +#include +#include "rk3588.dtsi" + +/ { + model = "FriendlyElec CM3588 NAS"; + compatible = "friendlyarm,cm3588", "rockchip,rk3588"; + + aliases { + mmc0 = &sdhci; + mmc1 = &sdmmc; + // nvme0 = &nvme0; + // nvme1 = &nvme1; + // nvme2 = &nvme2; + // nvme3 = &nvme3; + // ethernet0 = &r8125_u10; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + adc_keys: adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 1>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + + button-vol-up { + label = "Volume Up"; + linux,code = ; + press-threshold-microvolt = <17000>; + }; + }; + + analog-sound { + compatible = "simple-audio-card"; + pinctrl-names = "default"; + pinctrl-0 = <&headphone_detect>; + + simple-audio-card,name = "realtek,rt5616-codec"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + + simple-audio-card,hp-det-gpio = <&gpio1 RK_PC4 GPIO_ACTIVE_LOW>; + + simple-audio-card,routing = + "Headphones", "HPOL", + "Headphones", "HPOR", + "MIC1", "Microphone Jack", + "Microphone Jack", "micbias1"; + simple-audio-card,widgets = + "Headphone", "Headphones", + "Microphone", "Microphone Jack"; + + simple-audio-card,cpu { + sound-dai = <&i2s0_8ch>; + }; + + simple-audio-card,codec { + sound-dai = <&rt5616>; + }; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + cooling-levels = <0 50 100 150 200 255>; + pwms = <&pwm1 0 50000 0>; + status = "disabled"; + }; + + gpio_keys: gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&key1_pin>; + + button-user { + debounce-interval = <50>; + gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_LOW>; + label = "User Button"; + linux,code = ; + wakeup-source; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_sys: led-0 { + gpios = <&gpio2 RK_PC5 GPIO_ACTIVE_HIGH>; + label = "system-led"; + linux,default-trigger = "heartbeat"; + pinctrl-names = "default"; + pinctrl-0 = <&led_sys_pin>; + }; + + led_usr: led-1 { + gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>; + label = "user-led"; + pinctrl-names = "default"; + pinctrl-0 = <&led_usr_pin>; + }; + }; + + vcc_12v_dcin: vcc-12v-dcin-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_12v_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + /* vcc_5v0_sys powers peripherals */ + vcc_5v0_sys: vcc-5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc_12v_dcin>; + }; + + vcc_5v0_host_20: vcc-5v0-host-20 { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PA4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc_5v0_host20_en>; + regulator-name = "vcc_5v0_host_20"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc_5v0_sys>; + }; + + vcc_5v0_host_30: vcc-5v0-host-30 { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc_5v0_host30_en>; + regulator-name = "vcc_5v0_host_30"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc_5v0_sys>; + }; + + vcc_3v3_host_32: vcc-3v3-host-32-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc_3v3_host32_en>; + regulator-name = "vcc_3v3_host_32"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_5v0_sys>; + }; + + vbus_5v0_typec: vbus-5v0-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&typec_5v_pwr_en>; + regulator-name = "vbus_5v0_typec"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc_5v0_sys>; + }; + + /* vcc_4v0_sys powers the RK806, RK860's */ + vcc_4v0_sys: vcc-4v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_4v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <4000000>; + regulator-max-microvolt = <4000000>; + vin-supply = <&vcc_12v_dcin>; + }; + + vcc_3v3_pcie20: vcc-3v3-pcie20-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_pcie20"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc_3v3_pcie30: vcc-3v3-pcie30-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_pcie30"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_5v0_sys>; + }; + + vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&sd_s0_pwr>; + regulator-boot-on; + regulator-max-microvolt = <3300000>; + regulator-min-microvolt = <3300000>; + regulator-name = "vcc_3v3_sd_s0"; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc-1v1-nldo-s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc_4v0_sys>; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy1_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +/* Properties "clock" and "clock-names" introduced by Collabora https://gitlab.collabora.com/hardware-enablement/rockchip-3588/linux/-/commit/8fff68cb7cfe1e698445896252e34f79fad41720 */ +&display_subsystem { + clocks = <&hdptxphy_hdmi0>; + clock-names = "hdmi0_phy_pll"; +}; + +/* Signal labels [SIGNAL_LABEL] are from the official CM3588 NAS schematic revision 2309 */ +/* Some GPIOs like USB, sdmmc or SPI-NOR are not listed here */ +&gpio0 { + gpio-line-names = + /* GPIO0 A0-A7 */ + "", "", "", "", + "", "", "", "", + /* GPIO0 B0-B7 */ + "", "", "", "", + "", "", "", "", + /* GPIO0 C0-C7 */ + "", "", "", "", + "Pin 10 [UART0_RX_M0]", "Pin 08 [UART0_TX_M0/PWM4_M0]", "Pin 32 [PWM5_M1]", "", + /* GPIO0 D0-D7 */ + "", "", "", "", + "IR sensor [PWM3_IR_M0]", "User Button", "", ""; +}; + +&gpio1 { + gpio-line-names = + /* GPIO1 A0-A7 */ + "Pin 27 [UART6_RX_M1]", "Pin 28 [UART6_TX_M1]", "", "", + "", "", "", "Pin 15", + /* GPIO1 B0-B7 */ + "Pin 26", "Pin 21 [SPI0_MISO_M2]", "Pin 19 [SPI0_MOSI_M2/UART4_RX_M2]", "Pin 23 [SPI0_CLK_M2/UART4_TX_M2]", + "Pin 24 [SPI0_CS0_M2/UART7_RX_M2]", "Pin 22 [SPI0_CS1_M0/UART7_TX_M2]", "", "CSI-Pin 14 [MIPI_CAM2_CLKOUT]", + /* GPIO1 C0-C7 */ + "", "", "", "", + "Headphone detect [HP_DET_L]", "", "", "", + /* GPIO1 D0-D7 */ + "", "", "", "Fan [PWM1_M1]", + "", "", "Pin 05 [I2C8_SCL_M2]", "Pin 03 [I2C8_SDA_M2]"; +}; + +&gpio2 { + gpio-line-names = + /* GPIO2 A0-A7 */ + "", "", "", "", + "", "", "", "", + /* GPIO2 B0-B7 */ + "", "", "", "", + "", "", "", "", + /* GPIO2 C0-C7 */ + "", "CSI-Pin 11 [MIPI_CAM2_RESET_L]", "CSI-Pin 12 [MIPI_CAM2_PDN_L]", "", + "", "", "", "", + /* GPIO2 D0-D7 */ + "", "", "", "", + "", "", "", ""; +}; + +&gpio3 { + gpio-line-names = + /* GPIO3 A0-A7 */ + "Pin 35 [SPI4_MISO_M1/PW M10_M0]", "Pin 38 [SPI4_MOSI_M1]", "Pin 40 [SPI4_CLK_M1/UART8_TX_M1]", "Pin 36 [SPI4_CS0_M1/UART8_RX_M1]", + "Pin 37 [SPI4_CS1_M1]", "", "DSI-Pin 12 [LCD_RST]", "Buzzer [PW M8_M0]", + /* GPIO3 B0-B7 */ + "Pin 33 [PW M9_M0]", "DSI-Pin 10 [PW M2_M1/LCD_BL]", "Pin 07", "Pin 16", + "Pin 18", "Pin 29 [UART3_TX_M1/PW M12_M0]", "Pin 31 [UART3_RX_M1/PW M13_M0]", "Pin 12", + /* GPIO3 C0-C7 */ + "DSI-Pin 08 [TP_INT_L]", "DSI-Pin 14 [TP_RST_L]", "Pin 11 [PWM14_M0]", "Pin 13 [PWM15_IR_M0]", + "", "", "", "DSI-Pin 06 [I2C5_SCL_M0_TP]", + /* GPIO3 D0-D7 */ + "DSI-Pin 05 [I2C5_SDA_M0_TP]", "", "", "", + "", "", "", ""; +}; + +&gpio4 { + gpio-line-names = + /* GPIO4 A0-A7 */ + "", "", "", "", + "", "", "", "", + /* GPIO4 B0-B7 */ + "", "", "", "", + "", "", "", "", + /* GPIO4 C0-C7 */ + "", "", "", "", + "", "", "", "", + /* GPIO4 D0-D7 */ + "", "", "", "", + "", "", "", ""; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + sram-supply = <&vdd_gpu_mem_s0>; + status = "okay"; +}; + +&hdmi0 { + // avdd-0v9-supply = + // avdd-1v8-supply = + /* Dmesg error/warning: + * [ +0.000055] dwhdmi-rockchip fde80000.hdmi: Looking up avdd-0v9-supply from device tree + * [ +0.000011] dwhdmi-rockchip fde80000.hdmi: Looking up avdd-0v9-supply property in node /hdmi@fde80000 failed + * [ +0.000014] dwhdmi-rockchip fde80000.hdmi: supply avdd-0v9 not found, using dummy regulator + * [ +0.000080] dwhdmi-rockchip fde80000.hdmi: Looking up avdd-1v8-supply from device tree + * [ +0.000010] dwhdmi-rockchip fde80000.hdmi: Looking up avdd-1v8-supply property in node /hdmi@fde80000 failed + * [ +0.000010] dwhdmi-rockchip fde80000.hdmi: supply avdd-1v8 not found, using dummy regulator + * [ +0.001009] dwhdmi-rockchip fde80000.hdmi: registered ddc I2C bus driver + */ + status = "okay"; +}; + +&hdmi0_in { + hdmi0_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi0>; + }; +}; + +&hdptxphy_hdmi0 { + status = "okay"; +}; + +// /* 4k HDMI capture controller (see rk3588.dtsi) */ +// &hdmirx_cma { +// status = "okay"; +// }; + +// &hdmirx_ctrler { +// status = "okay"; +// hdmirx-5v-detection-gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_LOW>; +// pinctrl-0 = <&hdmim1_rx_cec &hdmim1_rx_hpdin &hdmim1_rx_scl &hdmim1_rx_sda &hdmirx_5v_detection>; +// pinctrl-names = "default"; +// memory-region = <&hdmirx_cma>; +// }; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + + vdd_cpu_big0_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc_4v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc_4v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + + vdd_npu_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_npu_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc_4v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4m3_xfer>; + status = "disabled"; +}; + +/* Connected to MIPI-DSI0 */ +&i2c5 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c5m0_xfer>; + status = "disabled"; +}; + +&i2c6 { + clock-frequency = <200000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c6m0_xfer>; + status = "okay"; + + fusb302: typec-portc@22 { + compatible = "fcs,fusb302"; + reg = <0x22>; + interrupt-parent = <&gpio0>; + interrupts = ; + pinctrl-0 = <&usbc0_int>; + pinctrl-names = "default"; + vbus-supply = <&vbus_5v0_typec>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_role_sw: endpoint@0 { + remote-endpoint = <&dwc3_0_role_switch>; + }; + }; + }; + + usb_con: connector { + compatible = "usb-c-connector"; + data-role = "dual"; + label = "USB-C"; + op-sink-microwatt = <1000000>; + power-role = "dual"; + source-pdos = ; + sink-pdos = ; + try-power-role = "sink"; + + altmodes { + #address-cells = <1>; + #size-cells = <0>; + + altmode@0 { + reg = <0>; + svid = <0xff01>; + vdo = <0xffffffff>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + usbc0_orien_sw: endpoint { + remote-endpoint = <&usbdp_phy0_orientation_switch>; + }; + }; + + port@1 { + reg = <1>; + dp_altmode_mux: endpoint { + remote-endpoint = <&usbdp_phy0_dp_altmode_mux>; + }; + }; + }; + }; + }; + + hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-output-names = "hym8563"; + interrupt-parent = <&gpio0>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&hym8563_int>; + wakeup-source; + }; +}; + +/* Connected to MIPI-CSI1 */ +&i2c7 { + clock-frequency = <200000>; + status = "okay"; + + rt5616: audio-codec@1b { + compatible = "realtek,rt5616"; + reg = <0x1b>; + assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; + assigned-clock-rates = <12288000>; + clocks = <&cru I2S0_8CH_MCLKOUT>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + + port { + rt5616_p0_0: endpoint { + remote-endpoint = <&i2s0_8ch_p0_0>; + }; + }; + }; +}; + +/* GPIO Connector, connected to 40-pin GPIO header */ +&i2c8 { + pinctrl-0 = <&i2c8m2_xfer>; +}; + +&i2s0_8ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_lrck + &i2s0_mclk + &i2s0_sclk + &i2s0_sdi0 + &i2s0_sdo0>; + status = "okay"; + + i2s0_8ch_p0: port { + i2s0_8ch_p0_0: endpoint { + dai-format = "i2s"; + mclk-fs = <256>; + remote-endpoint = <&rt5616_p0_0>; + }; + }; +}; + +&i2s5_8ch { + status = "okay"; +}; + +&i2s6_8ch { + status = "okay"; +}; + +&i2s7_8ch { + status = "okay"; +}; + +/* Temperature sensor near the center of the SoC */ +&package_thermal { + polling-delay = <1000>; + + trips { + package_hot: package_hot { + hysteresis = <2000>; + temperature = <65000>; + type = "active"; + }; + }; + + cooling-maps { + map0 { + cooling-device = <&fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + trip = <&package_hot>; + }; + }; +}; + +&pcie2x1l0 { // @fe170000 + /* 2. M.2 slot, CON14: pcie30phy port0 lane1 */ + max-link-speed = <3>; + num-lanes = <1>; + phys = <&pcie30phy>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_0_rst>; + reset-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie30>; + status = "okay"; + + // pcie@0,0 { + // reg = <0x00200000 0 0 0 0>; + // #address-cells = <3>; + // #size-cells = <2>; + + // nvme1: pcie@20,0 { + // reg = <0x000000 0 0 0 0>; + // }; + // }; +}; + +&pcie2x1l1 { // @fe180000 + /* 4. M.2 slot, CON16: pcie30phy port1 lane1 */ + max-link-speed = <3>; + num-lanes = <1>; + phys = <&pcie30phy>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_1_rst>; + reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie30>; + status = "okay"; + + // pcie@0,0 { + // reg = <0x00300000 0 0 0 0>; + // #address-cells = <3>; + // #size-cells = <2>; + + // nvme3: pcie@30,0 { + // reg = <0x000000 0 0 0 0>; + // }; + // }; +}; + +&pcie2x1l2 { // @fe190000 + /* r8125 ethernet */ + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_2_rst>; + reset-gpios = <&gpio4 RK_PA4 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie20>; + status = "okay"; + + // pcie@0,0 { + // reg = <0x00400000 0 0 0 0>; + // #address-cells = <3>; + // #size-cells = <2>; + + // r8125_u10: pcie@40,0 { + // reg = <0x000000 0 0 0 0>; + // local-mac-address = [ 00 00 00 00 00 00 ]; + // }; + // }; +}; + +&pcie30phy { + /* + * Michal Tomek describes: + * The PHY offers the following mapping options: + * + * port 0 lane 0 - always mapped to controller 0 (4L) + * port 0 lane 1 - to controller 0 or 2 (1L0) + * port 1 lane 0 - to controller 0 or 1 (2L) + * port 1 lane 1 - to controller 0, 1 or 3 (1L1) + * + * The data-lanes DT property maps these as follows: + * + * 0 = no controller (unsupported by the HW) + * 1 = 4L + * 2 = 2L + * 3 = 1L0 + * 4 = 1L1 + * + * <1 3 2 4> = NABIBI = [3 3] = x1x1 x1x1 (bif. of both ports; + */ + data-lanes = <1 3 2 4>; + status = "okay"; +}; + +&pcie3x4 { // @fe150000 + /* 1. M.2 slot, CON13: pcie30phy port0 lane0 */ + max-link-speed = <3>; + num-lanes = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie3x4_rst>; + reset-gpios = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie30>; + status = "okay"; + + // pcie@0,0 { + // reg = <0x00000000 0 0 0 0>; + // #address-cells = <3>; + // #size-cells = <2>; + + // nvme0: pcie@0,0 { + // reg = <0x000000 0 0 0 0>; + // }; + // }; +}; + +&pcie3x2 { // @fe160000 + /* 3. M.2 slot, CON15: pcie30phy port1 lane0 */ + max-link-speed = <3>; + num-lanes = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie3x2_rst>; + reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie30>; + status = "okay"; + + // pcie@0,0 { + // reg = <0x00100000 0 0 0 0>; + // #address-cells = <3>; + // #size-cells = <2>; + + // nvme2: pcie@10,0 { + // reg = <0x000000 0 0 0 0>; + // }; + // }; +}; + +&pinctrl { + audio { + headphone_detect: headphone-detect { + rockchip,pins = <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + gpio-key { + key1_pin: key1-pin { + rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-leds { + led_sys_pin: led-sys-pin { + rockchip,pins = <2 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + led_usr_pin: led-usr-pin { + rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + hym8563 { + hym8563_int: hym8563-int { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + pcie { + pcie2_0_rst: pcie2-0-rst { + rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie2_1_rst: pcie2-1-rst { + rockchip,pins = <4 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie2_2_rst: pcie2-2-rst { + rockchip,pins = <4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie3x2_rst: pcie3x2-rst { + rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie3x4_rst: pcie3x4-rst { + rockchip,pins = <4 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdmmc { + sd_s0_pwr: sd-s0-pwr { + rockchip,pins = <4 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + vcc_5v0_host20_en: vcc-5v0-host20-en { + rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc_5v0_host30_en: vcc-5v0-host30-en { + rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc_3v3_host32_en: vcc-3v3-host32-en { + rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb-typec { + usbc0_int: usbc0-int { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + typec_5v_pwr_en: typec-5v-pwr-en { + rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +/* Connected to 5V Fan */ +&pwm1 { + pinctrl-0 = <&pwm1m1_pins>; + status = "okay"; +}; + +/* Connected to MIPI-DSI0 */ +&pwm2 { + pinctrl-0 = <&pwm2m1_pins>; +}; + +/* GPIO Connector, connected to 40-pin GPIO header */ +&pwm5 { + pinctrl-0 = <&pwm5m1_pins>; + status = "okay"; +}; + +/* GPIO Connector */ +&pwm8 { + pinctrl-0 = <&pwm8m0_pins>; + status = "okay"; +}; + +/* GPIO Connector */ +&pwm9 { + pinctrl-0 = <&pwm9m0_pins>; + status = "okay"; +}; + +&saradc { + vref-supply = <&avcc_1v8_s0>; + status = "okay"; +}; + +/* eMMC */ +&sdhci { + bus-width = <8>; + full-pwr-cycle-in-suspend; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + no-sd; + no-sdio; + non-removable; + status = "okay"; +}; + +/* microSD card */ +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + max-frequency = <150000000>; + no-mmc; + no-sdio; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_sd_s0>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +/* GPIO Connector */ +&spi0 { + num-cs = <1>; + pinctrl-0 = <&spi0m2_cs0 &spi0m2_pins>; + status = "disabled"; +}; + +&spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + num-cs = <1>; + + rk806_single: pmic@0 { + compatible = "rockchip,rk806"; + reg = <0x0>; + + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + + spi-max-frequency = <1000000>; + + system-power-controller; + + vcc1-supply = <&vcc_4v0_sys>; + vcc2-supply = <&vcc_4v0_sys>; + vcc3-supply = <&vcc_4v0_sys>; + vcc4-supply = <&vcc_4v0_sys>; + vcc5-supply = <&vcc_4v0_sys>; + vcc6-supply = <&vcc_4v0_sys>; + vcc7-supply = <&vcc_4v0_sys>; + vcc8-supply = <&vcc_4v0_sys>; + vcc9-supply = <&vcc_4v0_sys>; + vcc10-supply = <&vcc_4v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc_4v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc_4v0_sys>; + + gpio-controller; + #gpio-cells = <2>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl1"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_gpu_s0"; + regulator-enable-ramp-delay = <400>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_lit_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_log_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_vdenc_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdd2_ddr_s3: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_2v0_pldo_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_3v3_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vddq_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "avcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s0: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avdd_1v2_s0: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "avdd_1v2_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_3v3_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vccio_sd_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + pldo6_s3: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "pldo6_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_ddr_pll_s0: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_ddr_pll_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + avdd_0v75_s0: nldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "avdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_0v85_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v75_s0: nldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +/* GPIO Connector, connected to 40-pin GPIO header */ +&spi4 { + num-cs = <1>; + pinctrl-0 = <&spi4m1_cs0 &spi4m1_pins>; + status = "disabled"; +}; + +&tsadc { + status = "okay"; +}; + +/* GPIO Connector, connected to 40-pin GPIO header */ +&uart0 { + pinctrl-0 = <&uart0m0_xfer>; + status = "disabled"; +}; + +/* Debug UART */ +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +/* GPIO Connector, connected to 40-pin GPIO header */ +&uart3 { + pinctrl-0 = <&uart3m1_xfer>; + status = "disabled"; +}; + +/* GPIO Connector, connected to 40-pin GPIO header */ +&uart4 { + pinctrl-0 = <&uart4m2_xfer>; + status = "disabled"; +}; + +/* GPIO Connector, connected to 40-pin GPIO header */ +&uart6 { + pinctrl-0 = <&uart6m1_xfer>; + status = "okay"; +}; + +/* GPIO Connector, connected to 40-pin GPIO header */ +&uart7 { + pinctrl-0 = <&uart7m2_xfer>; + status = "disabled"; +}; + +/* GPIO Connector, connected to 40-pin GPIO header */ +&uart8 { + pinctrl-0 = <&uart8m1_xfer>; + status = "disabled"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + rockchip,typec-vbus-det; /* @TODO Note: This flag is not (yet?) present in Linux 6.9 "Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml" */ + status = "okay"; +}; + +&u2phy1 { + status = "okay"; +}; + +&u2phy1_otg { + phy-supply = <&vcc_5v0_host_30>; + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy2_host { + phy-supply = <&vcc_5v0_host_20>; + status = "okay"; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy3_host { + phy-supply = <&vcc_3v3_host_32>; + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "otg"; + usb-role-switch; + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + dwc3_0_role_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_role_sw>; + }; + }; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +/* Upper USB 3.0 port */ +&usb_host1_xhci { + dr_mode = "host"; + snps,xhci-trb-ent-quirk; + status = "okay"; +}; + +/* Lower USB 3.0 port */ +&usb_host2_xhci { + dr_mode = "host"; + status = "okay"; +}; + +&usbdp_phy0 { + orientation-switch; + svid = <0xff01>; + sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>; + sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + usbdp_phy0_orientation_switch: endpoint@0 { + reg = <0>; + remote-endpoint = <&usbc0_orien_sw>; + }; + + usbdp_phy0_dp_altmode_mux: endpoint@1 { + reg = <1>; + remote-endpoint = <&dp_altmode_mux>; + }; + }; +}; + +&usbdp_phy1 { + status = "okay"; +}; + +&vop { + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = ; + remote-endpoint = <&hdmi0_in_vp0>; + }; +}; + +&wdt { + status = "okay"; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-nanopi-r6c.dts b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-nanopi-r6c.dts new file mode 100644 index 000000000000..5c8b850efe75 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-nanopi-r6c.dts @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include "rk3588s-nanopi-r6s.dts" + +/ { + model = "FriendlyElec NanoPi R6C"; + compatible = "friendlyelec,nanopi-r6c", "rockchip,rk3588s"; +}; + +&lan2_led { + /delete-property/ linux,default-trigger; + label = "user_led"; +}; + +&pcie2x1l2 { + /delete-node/ pcie@0,0; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-nanopi-r6s.dts b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-nanopi-r6s.dts new file mode 100644 index 000000000000..42b9d72f4bfd --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-nanopi-r6s.dts @@ -0,0 +1,863 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include +#include +#include +#include +#include "rk3588s.dtsi" + +/ { + model = "FriendlyElec NanoPi R6S"; + compatible = "friendlyelec,nanopi-r6s", "rockchip,rk3588s"; + + aliases { + mmc0 = &sdmmc; + mmc1 = &sdhci; + serial2 = &uart2; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + leds { + compatible = "gpio-leds"; + + sys_led: led-0 { + label = "sys_led"; + gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + pinctrl-names = "default"; + pinctrl-0 = <&sys_led_pin>; + }; + + wan_led: led-1 { + label = "wan_led"; + gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "r8169-3-3100:00:link"; + pinctrl-names = "default"; + pinctrl-0 = <&wan_led_pin>; + }; + + lan1_led: led-2 { + label = "lan1_led"; + gpios = <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "r8169-4-4100:00:link"; + pinctrl-names = "default"; + pinctrl-0 = <&lan1_led_pin>; + }; + + lan2_led: led-3 { + label = "lan2_led"; + gpios = <&gpio1 RK_PC4 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "stmmac-0:01:link"; + pinctrl-names = "default"; + pinctrl-0 = <&lan2_led_pin>; + }; + }; + + adc-keys { + compatible = "adc-keys"; + io-channels = <&saradc 0>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + + button-maskrom { + label = "Maskrom"; + linux,code = ; + press-threshold-microvolt = <1800>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&key1_pin>; + + button-user { + label = "User"; + linux,code = ; + gpios = <&gpio1 RK_PC0 GPIO_ACTIVE_LOW>; + debounce-interval = <50>; + wakeup-source; + }; + }; + + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc_3v3_sd_s0: vcc-3v3-sd-s0-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_sd_s0"; + enable-active-high; + regulator-boot-on; + gpio = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&sd_s0_pwr>; + regulator-max-microvolt = <3000000>; + regulator-min-microvolt = <3000000>; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc_3v3_pcie20: vcc3v3-pcie20-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_pcie20"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc5v0_usb: vcc5v0-usb-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_usb_otg0: vcc5v0-usb-otg0-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb_otg0"; + enable-active-high; + gpio = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&typec5v_pwren>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + }; + + vcc5v0_host_20: vcc5v0-host-20-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host_20"; + enable-active-high; + gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host20_en>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_usb>; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&gmac1 { + clock_in_out = "output"; + phy-handle = <&rgmii_phy1>; + phy-mode = "rgmii-rxid"; + pinctrl-0 = <&gmac1_miim + &gmac1_tx_bus2 + &gmac1_rx_bus2 + &gmac1_rgmii_clk + &gmac1_rgmii_bus>; + pinctrl-names = "default"; + tx_delay = <0x42>; + status = "okay"; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; + mem-supply = <&vdd_cpu_big0_mem_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; + mem-supply = <&vdd_cpu_big0_mem_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; + mem-supply = <&vdd_cpu_big1_mem_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; + mem-supply = <&vdd_cpu_big1_mem_s0>; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; + mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; + mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; + mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; + mem-supply = <&vdd_cpu_lit_mem_s0>; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + + vdd_cpu_big0_s0: vdd_cpu_big0_mem_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: vdd_cpu_big1_mem_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + + vdd_npu_s0: vdd_npu_mem_s0: rk8602@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_npu_s0"; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + regulator-boot-on; + regulator-always-on; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c6 { + clock-frequency = <200000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c6m0_xfer>; + status = "okay"; + + hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-output-names = "hym8563"; + pinctrl-names = "default"; + pinctrl-0 = <&rtc_int>; + interrupt-parent = <&gpio0>; + interrupts = ; + wakeup-source; + }; + + eeprom@53 { + compatible = "microchip,24c02", "atmel,24c02"; + reg = <0x53>; + #address-cells = <2>; + #size-cells = <0>; + pagesize = <16>; + size = <256>; + + eui_48: eui-48@fa { + reg = <0xfa 0x06>; + }; + }; +}; + +&mdio1 { + rgmii_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-id001c.c916"; + reg = <0x1>; + pinctrl-names = "default"; + pinctrl-0 = <&rtl8211f_rst>; + reset-assert-us = <20000>; + reset-deassert-us = <100000>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + }; +}; + +&pcie2x1l1 { + reset-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie20>; + status = "okay"; + + pcie@0,0 { + reg = <0x00300000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + + r8125_u25: pcie@30,0 { + reg = <0x000000 0 0 0 0>; + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + }; +}; + +&pcie2x1l2 { + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie20>; + status = "okay"; + + pcie@0,0 { + reg = <0x00400000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + + r8125_u40: pcie@40,0 { + reg = <0x000000 0 0 0 0>; + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + }; +}; + +&pinctrl { + gpio-key { + key1_pin: key1-pin { + rockchip,pins = <1 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + gpio-leds { + sys_led_pin: sys-led-pin { + rockchip,pins = + <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + wan_led_pin: wan-led-pin { + rockchip,pins = + <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + lan1_led_pin: lan1-led-pin { + rockchip,pins = + <1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + lan2_led_pin: lan2-led-pin { + rockchip,pins = + <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + hym8563 { + rtc_int: rtc-int { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sdmmc { + sd_s0_pwr: sd-s0-pwr { + rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb { + typec5v_pwren: typec5v-pwren { + rockchip,pins = <1 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + /omit-if-no-ref/ + usbc0_int: usbc0-int { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vcc5v0_host20_en: vcc5v0-host20-en { + rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + rtl8211f { + rtl8211f_rst: rtl8211f-rst { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&saradc { + vref-supply = <&avcc_1v8_s0>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + /* HS400 doesn't work properly -> https://github.com/torvalds/linux/commit/cee572756aa2cb46e959e9797ad4b730b78a050b */ + mmc-hs200-1_8v; + max-frequency = <200000000>; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-sd-highspeed; + disable-wp; + max-frequency = <150000000>; + no-mmc; + no-sdio; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_sd_s0>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + num-cs = <1>; + + pmic@0 { + compatible = "rockchip,rk806"; + spi-max-frequency = <1000000>; + reg = <0x0>; + + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc5v0_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc5v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + gpio-controller; + #gpio-cells = <2>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fudr_moden0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_gpu_s0"; + regulator-enable-ramp-delay = <400>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_lit_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_log_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-init-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_vdenc_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdd2_ddr_s3: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_2v0_pldo_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_3v3_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vddq_ddr_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "avcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_1v8_s0: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avdd_1v2_s0: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "avdd_1v2_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_3v3_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vccio_sd_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + pldo6_s3: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "pldo6_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s3"; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_ddr_pll_s0: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_ddr_pll_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + avdd_0v75_s0: nldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "avdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_0v85_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v75_s0: nldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s0"; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +&tsadc { + status = "okay"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + phy-supply = <&vcc5v0_usb_otg0>; + status = "okay"; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy2_host { + phy-supply = <&vcc5v0_host_20>; + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "host"; + extcon = <&u2phy0>; + status = "okay"; +}; + +&usbdp_phy0 { + status = "okay"; +}; + +&hdmi0 { + status = "okay"; +}; + + +&hdptxphy_hdmi0 { + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&hdmi0_in { + hdmi0_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi0>; + }; +}; + +&vop { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = ; + remote-endpoint = <&hdmi0_in_vp0>; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-orangepi-5b.dts b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-orangepi-5b.dts new file mode 100644 index 000000000000..3194df7a5fc8 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-orangepi-5b.dts @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include "rk3588s-orangepi-5.dts" + +/ { + model = "Xunlong Orange Pi 5B"; + compatible = "xunlong,orangepi-5b", "rockchip,rk3588s"; + + aliases { + mmc0 = &sdmmc; + mmc1 = &sdhci; + }; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + /* HS400 doesn't work properly -> https://github.com/torvalds/linux/commit/cee572756aa2cb46e959e9797ad4b730b78a050b */ + mmc-hs200-1_8v; + max-frequency = <200000000>; + status = "okay"; +}; + +&sfc { + status = "disabled"; +}; + +&pcie2x1l2 { + pcie@0,0 { + reg = <0x400000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + device_type = "pci"; + bus-range = <0x40 0x4f>; + + wifi: wifi@0,0 { + compatible = "pci14e4,449d"; + reg = <0x410000 0 0 0 0>; + clocks = <&hym8563>; + clock-names = "32k"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-rock-5c.dts b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-rock-5c.dts new file mode 100644 index 000000000000..0666da126cf0 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/dt/rk3588s-rock-5c.dts @@ -0,0 +1,825 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include +#include +#include +#include +#include "rk3588s.dtsi" + +/ { + model = "Radxa ROCK 5 Model C"; + compatible = "radxa,rock-5c", "rockchip,rk3588s"; + + aliases { + ethernet0 = &gmac1; + mmc0 = &sdhci; + mmc1 = &sdmmc; + }; + + analog-sound { + compatible = "audio-graph-card"; + label = "rk3588-es8316"; + + widgets = "Microphone", "Mic Jack", + "Headphone", "Headphones"; + + routing = "MIC2", "Mic Jack", + "Headphones", "HPOL", + "Headphones", "HPOR"; + + dais = <&i2s0_8ch_p0>; + }; + + chosen { + stdout-path = "serial2:1500000n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + + user-led { + gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; + }; + + io-led { + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + cooling-levels = <0 95 145 195 255>; + fan-supply = <&vcc_5v0>; + pwms = <&pwm3 0 50000 0>; + #cooling-cells = <2>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc3v3_pcie: vcc3v3-pcie { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pcie"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <5000>; + enable-active-high; + gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc_5v0: vcc-5v0 { + compatible = "regulator-fixed"; + regulator-name = "vcc_5v0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + enable-active-high; + gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc_5v0_en>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + vin-supply = <&vcc5v0_sys>; + }; + + vcc5v0_otg: vcc5v0-otg-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_otg"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_otg_en>; + vin-supply = <&vcc5v0_sys>; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy2_psu { + status = "okay"; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_big0_s0>; +}; + +&cpu_b2 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_b3 { + cpu-supply = <&vdd_cpu_big1_s0>; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0m2_xfer>; + status = "okay"; + + vdd_cpu_big0_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big0_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_big1_s0: regulator@43 { + compatible = "rockchip,rk8603", "rockchip,rk8602"; + reg = <0x43>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_cpu_big1_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1050000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + + vdd_npu_s0: regulator@42 { + compatible = "rockchip,rk8602"; + reg = <0x42>; + fcs,suspend-voltage-selector = <1>; + regulator-name = "vdd_npu_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <2300>; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + eeprom: eeprom@50 { + compatible = "belling,bl24c16a", "atmel,24c16"; + reg = <0x50>; + pagesize = <16>; + }; +}; + +&i2c3 { + status = "okay"; +}; + +&i2c5 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5m2_xfer>; +}; + +&i2c7 { + status = "okay"; + + es8316: audio-codec@11 { + compatible = "everest,es8316"; + reg = <0x11>; + clocks = <&cru I2S0_8CH_MCLKOUT>; + clock-names = "mclk"; + assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; + assigned-clock-rates = <12288000>; + #sound-dai-cells = <0>; + + port { + es8316_p0_0: endpoint { + remote-endpoint = <&i2s0_8ch_p0_0>; + }; + }; + }; +}; + +&i2s0_8ch { + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_lrck + &i2s0_mclk + &i2s0_sclk + &i2s0_sdi0 + &i2s0_sdo0>; + status = "okay"; + + i2s0_8ch_p0: port { + i2s0_8ch_p0_0: endpoint { + dai-format = "i2s"; + mclk-fs = <256>; + remote-endpoint = <&es8316_p0_0>; + }; + }; +}; + +&gmac1 { + clock_in_out = "output"; + phy-handle = <&rgmii_phy1>; + phy-mode = "rgmii"; + pinctrl-0 = <&gmac1_miim + &gmac1_tx_bus2 + &gmac1_rx_bus2 + &gmac1_rgmii_clk + &gmac1_rgmii_bus>; + pinctrl-names = "default"; + tx_delay = <0x3a>; + rx_delay = <0x3e>; + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + status = "okay"; +}; + +&mdio1 { + rgmii_phy1: ethernet-phy@1 { + /* RTL8211F */ + compatible = "ethernet-phy-id001c.c916"; + reg = <0x1>; + pinctrl-names = "default"; + pinctrl-0 = <&rtl8211f_rst>; + reset-assert-us = <20000>; + reset-deassert-us = <100000>; + reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + }; +}; + +&pcie2x1l2 { + status = "okay"; + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; +}; + +&pinctrl { + power { + vcc_5v0_en: vcc-5v0-en { + rockchip,pins = <4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + rtl8211f { + rtl8211f_rst: rtl8211f-rst { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + vcc5v0_otg_en: vcc5v0-otg-en { + rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wifibt { + wifibt_en: wifibit-en { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + host_wake_wl: host-wake-wl { + rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_output_high>; + }; + + wl_wake_host: wl-wake-host { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + host_wake_bt: host-wake-bt { + rockchip,pins = <1 RK_PA6 RK_FUNC_GPIO &pcfg_output_high>; + }; + + bt_wake_host: bt-wake-host { + rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm3 { + pinctrl-names = "default"; + pinctrl-0 = <&pwm3m1_pins>; + status = "okay"; +}; + +&saradc { + vref-supply = <&avcc_1v8_s0>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + disable-wp; + max-frequency = <150000000>; + no-sdio; + no-mmc; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_s0>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; +}; + +&spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + num-cs = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + + pmic@0 { + compatible = "rockchip,rk806"; + reg = <0x0>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, + <&rk806_dvs2_null>, <&rk806_dvs3_null>; + spi-max-frequency = <1000000>; + + system-power-controller; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc5v0_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc5v0_sys>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + gpio-controller; + #gpio-cells = <2>; + + rk806_dvs1_null: dvs1-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs2_null: dvs2-null-pins { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs3_null: dvs3-null-pins { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + regulators { + vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { + regulator-name = "vdd_gpu_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-enable-ramp-delay = <400>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { + regulator-name = "vdd_cpu_lit_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-name = "vdd_log_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: vdd_vdenc_mem_s0: dcdc-reg4 { + regulator-name = "vdd_vdenc_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_ddr_s0: dcdc-reg5 { + regulator-name = "vdd_ddr_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vdd2_ddr_s3: dcdc-reg6 { + regulator-name = "vdd2_ddr_s3"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-name = "vdd_2v0_pldo_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vcc_3v3_s3: dcdc-reg8 { + regulator-name = "vcc_3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vddq_ddr_s0: dcdc-reg9 { + regulator-name = "vddq_ddr_s0"; + regulator-always-on; + regulator-boot-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: dcdc-reg10 { + regulator-name = "vcc_1v8_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-name = "avcc_1v8_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s0: pldo-reg2 { + regulator-name = "vcc_1v8_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + avdd_1v2_s0: pldo-reg3 { + regulator-name = "avdd_1v2_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-name = "vcc_3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-name = "vccio_sd_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + pldo6_s3: pldo-reg6 { + regulator-name = "pldo6_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-name = "vdd_0v75_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_ddr_pll_s0: nldo-reg2 { + regulator-name = "vdd_ddr_pll_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + avdd_0v75_s0: nldo-reg3 { + regulator-name = "avdd_0v75_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg4 { + regulator-name = "vdd_0v85_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v75_s0: nldo-reg5 { + regulator-name = "vdd_0v75_s0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; + vbus-supply = <&vcc5v0_otg>; +}; + +&u2phy2 { + status = "okay"; +}; + +&u2phy2_host { + status = "okay"; + phy-supply = <&vcc5v0_host>; +}; + +&u2phy3 { + status = "okay"; +}; + +&u2phy3_host { + phy-supply = <&vcc5v0_host>; + status = "okay"; +}; + +&uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; +}; + +&usbdp_phy0 { + status = "okay"; + rockchip,dp-lane-mux = <2 3>; +}; + +&usb_host0_ehci { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&wifibt_en &host_wake_wl &wl_wake_host &host_wake_bt &bt_wake_host>; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host0_xhci { + dr_mode = "host"; + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usb_host2_xhci { + status = "okay"; +}; + +&hdmi0 { + status = "okay"; +}; + +&hdptxphy_hdmi0 { + status = "okay"; +}; + +&vop_mmu { + status = "okay"; +}; + +&hdmi0_in { + hdmi0_in_vp0: endpoint { + remote-endpoint = <&vp0_out_hdmi0>; + }; +}; + +&vop { + status = "okay"; +}; + +&vp0 { + vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { + reg = ; + remote-endpoint = <&hdmi0_in_vp0>; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/Makefile b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/Makefile new file mode 100644 index 000000000000..573aed747464 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/Makefile @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0 +dtbo-$(CONFIG_ARCH_ROCKCHIP) += \ + rockchip-rk3588-sata1.dtbo \ + rockchip-rk3588-sata2.dtbo \ + rockchip-rk3588-pwm0-m0.dtbo \ + rockchip-rk3588-pwm0-m1.dtbo \ + rockchip-rk3588-pwm0-m2.dtbo \ + rockchip-rk3588-pwm1-m0.dtbo \ + rockchip-rk3588-pwm1-m1.dtbo \ + rockchip-rk3588-pwm1-m2.dtbo \ + rockchip-rk3588-pwm2-m1.dtbo \ + rockchip-rk3588-pwm3-m0.dtbo \ + rockchip-rk3588-pwm3-m1.dtbo \ + rockchip-rk3588-pwm3-m2.dtbo \ + rockchip-rk3588-pwm3-m3.dtbo \ + rockchip-rk3588-pwm5-m2.dtbo \ + rockchip-rk3588-pwm6-m0.dtbo \ + rockchip-rk3588-pwm6-m2.dtbo \ + rockchip-rk3588-pwm7-m0.dtbo \ + rockchip-rk3588-pwm7-m3.dtbo \ + rockchip-rk3588-pwm8-m0.dtbo \ + rockchip-rk3588-pwm10-m0.dtbo \ + rockchip-rk3588-pwm11-m0.dtbo \ + rockchip-rk3588-pwm11-m1.dtbo \ + rockchip-rk3588-pwm12-m0.dtbo \ + rockchip-rk3588-pwm13-m0.dtbo \ + rockchip-rk3588-pwm13-m2.dtbo \ + rockchip-rk3588-pwm14-m0.dtbo \ + rockchip-rk3588-pwm14-m1.dtbo \ + rockchip-rk3588-pwm14-m2.dtbo \ + rockchip-rk3588-pwm15-m0.dtbo \ + rockchip-rk3588-pwm15-m1.dtbo \ + rockchip-rk3588-pwm15-m2.dtbo \ + rockchip-rk3588-pwm15-m3.dtbo + +targets += $(dtbo-y) + +always := $(dtbo-y) +clean-files := *.dtbo + diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m0.dts new file mode 100644 index 000000000000..211ddc646f45 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m0.dts @@ -0,0 +1,14 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm0>; + + __overlay__ { + status = "okay"; + pinctrl-names = "active"; + pinctrl-0 = <&pwm0m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m1.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m1.dts new file mode 100644 index 000000000000..353162ec79ee --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m1.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm0>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm0m1_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m2.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m2.dts new file mode 100644 index 000000000000..f7c03e93e3b8 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm0-m2.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm0>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm0m2_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m0.dts new file mode 100644 index 000000000000..bb19090ad249 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m0.dts @@ -0,0 +1,14 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm1>; + + __overlay__ { + status = "okay"; + pinctrl-names = "active"; + pinctrl-0 = <&pwm1m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m1.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m1.dts new file mode 100644 index 000000000000..e935135023ee --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m1.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm1>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm1m1_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m2.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m2.dts new file mode 100644 index 000000000000..155d0bd4138b --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm1-m2.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm1>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm1m2_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm10-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm10-m0.dts new file mode 100644 index 000000000000..281071bbbc0f --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm10-m0.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm10>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm10m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm11-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm11-m0.dts new file mode 100644 index 000000000000..1bebcd619d95 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm11-m0.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm11>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm11m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm11-m1.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm11-m1.dts new file mode 100644 index 000000000000..b85076feabad --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm11-m1.dts @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + metadata { + title = "Enable PWM11-M1"; + compatible = "radxa,rock-5a"; + category = "misc"; + exclusive = "GPIO4_B4"; + description = "Enable PWM11-M1.\nOn Radxa ROCK 5A this is pin 15."; + }; + + fragment@0 { + target = <&pwm11>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm11m1_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm12-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm12-m0.dts new file mode 100644 index 000000000000..6dc0c7ed0b58 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm12-m0.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm12>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm12m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm13-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm13-m0.dts new file mode 100644 index 000000000000..38ec499ce586 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm13-m0.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm13>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm13m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm13-m2.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm13-m2.dts new file mode 100644 index 000000000000..0d9b225fff0d --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm13-m2.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm13>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm13m2_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m0.dts new file mode 100644 index 000000000000..330406d939ad --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m0.dts @@ -0,0 +1,14 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm14>; + + __overlay__ { + status = "okay"; + pinctrl-names = "active"; + pinctrl-0 = <&pwm14m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m1.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m1.dts new file mode 100644 index 000000000000..82fec22ebbd1 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m1.dts @@ -0,0 +1,14 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm14>; + + __overlay__ { + status = "okay"; + pinctrl-names = "active"; + pinctrl-0 = <&pwm14m1_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m2.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m2.dts new file mode 100644 index 000000000000..7a26f2dc891a --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm14-m2.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm14>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm14m2_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m0.dts new file mode 100644 index 000000000000..076bef9f64d9 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m0.dts @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + metadata { + title = "Enable PWM15-M0"; + compatible = "radxa,rock-5b"; + category = "misc"; + exclusive = "GPIO3_C3"; + description = "Enable PWM15-M0.\nOn Radxa ROCK 5B this is pin 7."; + }; + + fragment@0 { + target = <&pwm15>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm15m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m1.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m1.dts new file mode 100644 index 000000000000..7d3de70b05cf --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m1.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm15>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm15m1_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m2.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m2.dts new file mode 100644 index 000000000000..c1b2aea10acb --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m2.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm15>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm15m2_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m3.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m3.dts new file mode 100644 index 000000000000..79e421a4958f --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm15-m3.dts @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + metadata { + title = "Enable PWM15-M3"; + compatible = "radxa,rock-5a", "radxa,rock-5b"; + category = "misc"; + exclusive = "GPIO1_D7"; + description = "Enable PWM15-M3.\nOn Radxa ROCK 5A this is pin 3.\nOn Radxa ROCK 5B this is pin 29."; + }; + + fragment@0 { + target = <&pwm15>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm15m3_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm2-m1.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm2-m1.dts new file mode 100644 index 000000000000..653583fdb7e4 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm2-m1.dts @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + metadata { + title = "Enable PWM2-M1"; + compatible = "radxa,rock-5b"; + category = "misc"; + exclusive = "GPIO3_B1"; + description = "Enable PWM2-M1.\nOn Radxa ROCK 5B this is pin 36."; + }; + + fragment@0 { + target = <&pwm2>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm2m1_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m0.dts new file mode 100644 index 000000000000..a6a9181ab596 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m0.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm3>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm3m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m1.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m1.dts new file mode 100644 index 000000000000..23ff1ad68993 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m1.dts @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + metadata { + title = "Enable PWM3-M1"; + compatible = "radxa,rock-5b"; + category = "misc"; + exclusive = "GPIO3_B2"; + description = "Enable PWM3-M1.\nOn Radxa ROCK 5B this is pin 38."; + }; + + fragment@0 { + target = <&pwm3>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm3m1_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m2.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m2.dts new file mode 100644 index 000000000000..b70d2097ea32 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m2.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm3>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm3m2_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m3.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m3.dts new file mode 100644 index 000000000000..db544f2502fd --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm3-m3.dts @@ -0,0 +1,13 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pwm3>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm3m3_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm5-m2.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm5-m2.dts new file mode 100644 index 000000000000..ce26d29f33cf --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm5-m2.dts @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + metadata { + title = "Enable PWM5-M2"; + compatible = "radxa,rock-5b"; + category = "misc"; + exclusive = "GPIO4_C4"; + description = "Enable PWM5-M2.\nOn Radxa ROCK 5B this is pin 18."; + }; + + fragment@0 { + target = <&pwm5>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm5m2_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm6-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm6-m0.dts new file mode 100644 index 000000000000..e4d0ce3f5864 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm6-m0.dts @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + metadata { + title = "Enable PWM6-M0"; + compatible = "radxa,rock-5a"; + category = "misc"; + exclusive = "GPIO0_C7"; + description = "Enable PWM6-M0.\nOn Radxa ROCK 5A this is pin 27."; + }; + + fragment@0 { + target = <&pwm6>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm6m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm6-m2.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm6-m2.dts new file mode 100644 index 000000000000..5e66d1d33ef4 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm6-m2.dts @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + metadata { + title = "Enable PWM6-M2"; + compatible = "radxa,rock-5b"; + category = "misc"; + exclusive = "GPIO4_C5"; + description = "Enable PWM6-M2.\nOn Radxa ROCK 5B this is pin 28."; + }; + + fragment@0 { + target = <&pwm6>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm6m2_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm7-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm7-m0.dts new file mode 100644 index 000000000000..6516762486dd --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm7-m0.dts @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + metadata { + title = "Enable PWM7-M0"; + compatible = "radxa,rock-5a"; + category = "misc"; + exclusive = "GPIO0_D0"; + description = "Enable PWM7-M0.\nOn Radxa ROCK 5A this is pin 28."; + }; + + fragment@0 { + target = <&pwm7>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm7m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm7-m3.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm7-m3.dts new file mode 100644 index 000000000000..9a7d919f6cd6 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm7-m3.dts @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + metadata { + title = "Enable PWM7-M3"; + compatible = "radxa,rock-5b"; + category = "misc"; + exclusive = "GPIO4_C6"; + description = "Enable PWM7-M3.\nOn Radxa ROCK 5B this is pin 27."; + }; + + fragment@0 { + target = <&pwm7>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm7m3_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm8-m0.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm8-m0.dts new file mode 100644 index 000000000000..e461cffb597a --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-pwm8-m0.dts @@ -0,0 +1,21 @@ +/dts-v1/; +/plugin/; + +/ { + metadata { + title = "Enable PWM8-M0"; + compatible = "radxa,rock-5b"; + category = "misc"; + exclusive = "GPIO3_A7"; + description = "Enable PWM8-M0.\nOn Radxa ROCK 5B this is pin 33."; + }; + + fragment@0 { + target = <&pwm8>; + + __overlay__ { + status = "okay"; + pinctrl-0 = <&pwm8m0_pins>; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-sata1.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-sata1.dts new file mode 100644 index 000000000000..2759ab9cf7af --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-sata1.dts @@ -0,0 +1,20 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pcie2x1l0>; + + __overlay__ { + status = "disabled"; + }; + }; + + fragment@1 { + target = <&sata1>; + + __overlay__ { + status = "okay"; + }; + }; +}; diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-sata2.dts b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-sata2.dts new file mode 100644 index 000000000000..c68e11dc1604 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/overlay/rockchip-rk3588-sata2.dts @@ -0,0 +1,20 @@ +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target = <&pcie2x1l1>; + + __overlay__ { + status = "disabled"; + }; + }; + + fragment@1 { + target = <&sata2>; + + __overlay__ { + status = "okay"; + }; + }; +}; From 994f3768883771cacf8981aa9924efa41483a8c7 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Wed, 12 Jun 2024 13:40:39 +0200 Subject: [PATCH 35/53] rk3588: edge: Set kernel patch folder name to default Move kernel patch folder to archive/rockchip-rk3588-${KERNEL_MAJOR_MINOR} which is the default. Also rename kernel config to linux-rockchip-rk3588-${KERNEL_MAJOR_MINOR} --- ...nfig => linux-rockchip-rk3588-6.10.config} | 0 config/sources/families/rockchip-rk3588.conf | 20 +++++++++---------- .../0000.patching_config.yaml | 0 .../0001-general-add-overlay-support.patch | 0 .../0010-fix-clk-divisions.patch | 0 .../0011-irqchip-fix-its-timeout-issue.patch | 0 .../0012-fix-initial-PERST-GPIO-value.patch | 0 ...3588-Add-Thermal-and-CpuFreq-Support.patch | 0 .../0024-RK3588-Add-Crypto-Support.patch | 0 .../0025-RK3588-Add-HW-RNG-Support.patch | 0 ...-rockchip-Add-HDMI0-bridge-to-rk3588.patch | 0 ...ip-Enable-HDMI0-PHY-clk-provider-on-.patch | 0 ...p-samsung-hdptx-Add-FRL-EARC-support.patch | 0 ...hip-samsung-hdptx-Add-clock-provider.patch | 0 ...2-Improve-display-modes-handling-on-.patch | 0 ...kchip-rk3588-add-VDPU-and-RGA2-nodes.patch | 0 ...itial-support-for-DW-HDMI-Controller.patch | 0 ...-bridge-synopsys-Fix-HDMI-Controller.patch | 0 .../0801-wireless-add-bcm43752.patch | 0 .../0802-wireless-add-clk-property.patch | 0 ...b-Slow-down-emmc-to-hs200-and-add-ts.patch | 0 ...d-rock-5b-arm64-dts-enable-spi-flash.patch | 0 ...dts-rockchip-Enable-HDMI0-on-rock-5b.patch | 0 ...-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch | 0 ...5-board-rock5b-automatic-fan-control.patch | 0 .../1020-Add-HDMI-and-VOP2-to-Rock-5A.patch | 0 ...rm64-dts-enable-gpu-node-for-rock-5a.patch | 0 ...dd-missing-nodes-to-Orange-Pi-5-Plus.patch | 0 ...rockchip-support-poweroff-on-rock-5a.patch | 0 ...ip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch | 0 ...hip-Add-HDMI-support-to-ArmSoM-Sige7.patch | 0 ...ip-Add-ap6275p-wireless-support-to-A.patch | 0 .../1041-board-khadas-edge2-mcu.patch | 0 ...dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch | 0 .../dt/rk3588-bananapi-m7.dts | 0 .../dt/rk3588-hinlink-h88k.dts | 0 .../dt/rk3588-mixtile-blade3.dts | 0 .../dt/rk3588-nanopc-cm3588-nas.dts | 0 .../dt/rk3588s-nanopi-r6c.dts | 0 .../dt/rk3588s-nanopi-r6s.dts | 0 .../dt/rk3588s-orangepi-5.dts | 0 .../dt/rk3588s-orangepi-5b.dts | 0 .../dt/rk3588s-rock-5c.dts | 0 .../rockchip-rk3588-6.10}/overlay/Makefile | 0 .../overlay/rockchip-rk3588-pwm0-m0.dtso | 0 .../overlay/rockchip-rk3588-pwm0-m1.dtso | 0 .../overlay/rockchip-rk3588-pwm0-m2.dtso | 0 .../overlay/rockchip-rk3588-pwm1-m0.dtso | 0 .../overlay/rockchip-rk3588-pwm1-m1.dtso | 0 .../overlay/rockchip-rk3588-pwm1-m2.dtso | 0 .../overlay/rockchip-rk3588-pwm10-m0.dtso | 0 .../overlay/rockchip-rk3588-pwm11-m0.dtso | 0 .../overlay/rockchip-rk3588-pwm11-m1.dtso | 0 .../overlay/rockchip-rk3588-pwm12-m0.dtso | 0 .../overlay/rockchip-rk3588-pwm13-m0.dtso | 0 .../overlay/rockchip-rk3588-pwm13-m2.dtso | 0 .../overlay/rockchip-rk3588-pwm14-m0.dtso | 0 .../overlay/rockchip-rk3588-pwm14-m1.dtso | 0 .../overlay/rockchip-rk3588-pwm14-m2.dtso | 0 .../overlay/rockchip-rk3588-pwm15-m0.dtso | 0 .../overlay/rockchip-rk3588-pwm15-m1.dtso | 0 .../overlay/rockchip-rk3588-pwm15-m2.dtso | 0 .../overlay/rockchip-rk3588-pwm15-m3.dtso | 0 .../overlay/rockchip-rk3588-pwm2-m1.dtso | 0 .../overlay/rockchip-rk3588-pwm3-m0.dtso | 0 .../overlay/rockchip-rk3588-pwm3-m1.dtso | 0 .../overlay/rockchip-rk3588-pwm3-m2.dtso | 0 .../overlay/rockchip-rk3588-pwm3-m3.dtso | 0 .../overlay/rockchip-rk3588-pwm5-m2.dtso | 0 .../overlay/rockchip-rk3588-pwm6-m0.dtso | 0 .../overlay/rockchip-rk3588-pwm6-m2.dtso | 0 .../overlay/rockchip-rk3588-pwm7-m0.dtso | 0 .../overlay/rockchip-rk3588-pwm7-m3.dtso | 0 .../overlay/rockchip-rk3588-pwm8-m0.dtso | 0 .../overlay/rockchip-rk3588-sata1.dtso | 0 .../overlay/rockchip-rk3588-sata2.dtso | 0 76 files changed, 10 insertions(+), 10 deletions(-) rename config/kernel/{linux-rockchip-rk3588-edge.config => linux-rockchip-rk3588-6.10.config} (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0000.patching_config.yaml (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0001-general-add-overlay-support.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0010-fix-clk-divisions.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0011-irqchip-fix-its-timeout-issue.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0012-fix-initial-PERST-GPIO-value.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0024-RK3588-Add-Crypto-Support.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0025-RK3588-Add-HW-RNG-Support.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0801-wireless-add-bcm43752.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/0802-wireless-add-clk-property.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1015-board-rock5b-automatic-fan-control.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1041-board-khadas-edge2-mcu.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/dt/rk3588-bananapi-m7.dts (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/dt/rk3588-hinlink-h88k.dts (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/dt/rk3588-mixtile-blade3.dts (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/dt/rk3588-nanopc-cm3588-nas.dts (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/dt/rk3588s-nanopi-r6c.dts (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/dt/rk3588s-nanopi-r6s.dts (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/dt/rk3588s-orangepi-5.dts (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/dt/rk3588s-orangepi-5b.dts (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/dt/rk3588s-rock-5c.dts (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/Makefile (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm0-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm0-m1.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm0-m2.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm1-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm1-m1.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm1-m2.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm10-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm11-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm11-m1.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm12-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm13-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm13-m2.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm14-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm14-m1.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm14-m2.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm15-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm15-m1.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm15-m2.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm15-m3.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm2-m1.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm3-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm3-m1.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm3-m2.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm3-m3.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm5-m2.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm6-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm6-m2.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm7-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm7-m3.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-pwm8-m0.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-sata1.dtso (100%) rename patch/kernel/{rockchip-rk3588-edge => archive/rockchip-rk3588-6.10}/overlay/rockchip-rk3588-sata2.dtso (100%) diff --git a/config/kernel/linux-rockchip-rk3588-edge.config b/config/kernel/linux-rockchip-rk3588-6.10.config similarity index 100% rename from config/kernel/linux-rockchip-rk3588-edge.config rename to config/kernel/linux-rockchip-rk3588-6.10.config diff --git a/config/sources/families/rockchip-rk3588.conf b/config/sources/families/rockchip-rk3588.conf index 7b05e7208712..25dbcf85e1bb 100644 --- a/config/sources/families/rockchip-rk3588.conf +++ b/config/sources/families/rockchip-rk3588.conf @@ -42,17 +42,17 @@ case $BRANCH in current) # Branch based on a stable kernel release (will stay on the next LTS kernel release once released, 6.12? LTS) LINUXFAMILY=rockchip-rk3588 - KERNEL_MAJOR_MINOR="6.8" # Major and minor versions of this kernel. - LINUXCONFIG="linux-rockchip-rk3588-${KERNEL_MAJOR_MINOR}" # Attention: not -${BRANCH} (edge/current/legacy), but -${KERNEL_MAJOR_MINOR} thus 6.8 / 6.10 etc - # No need to set KERNELPATCHDIR, since default is: KERNELPATCHDIR='archive/rockchip-rk3588-6.8' + KERNEL_MAJOR_MINOR="6.8" # Major and minor versions of this kernel. + LINUXCONFIG="linux-rockchip-rk3588-${KERNEL_MAJOR_MINOR}" # Attention: not -${BRANCH} (edge/current/legacy), but -${KERNEL_MAJOR_MINOR} thus 6.6 / 6.12 etc + # No need to set KERNELPATCHDIR, since default is: KERNELPATCHDIR='archive/rockchip-rk3588-${KERNEL_MAJOR_MINOR}' ;; edge) # Branch based on the latest kernel release including RC releases, to benefit from the latest RK3588 mainline advancements. Might be unstable! LINUXFAMILY=rockchip-rk3588 - LINUXCONFIG='linux-rockchip-rk3588-'$BRANCH - KERNEL_MAJOR_MINOR="6.10" # Major and minor versions of this kernel. - KERNELPATCHDIR='rockchip-rk3588-edge' + KERNEL_MAJOR_MINOR="6.10" # Major and minor versions of this kernel. + LINUXCONFIG="linux-rockchip-rk3588-${KERNEL_MAJOR_MINOR}" # Attention: not -${BRANCH} (edge/current/legacy), but -${KERNEL_MAJOR_MINOR} thus 6.8 / 6.10 etc + # No need to set KERNELPATCHDIR, since default is: KERNELPATCHDIR='archive/rockchip-rk3588-${KERNEL_MAJOR_MINOR}' ;; collabora) @@ -60,10 +60,10 @@ case $BRANCH in LINUXFAMILY=rockchip-rk3588 LINUXCONFIG='linux-rockchip-rk3588-'$BRANCH KERNEL_MAJOR_MINOR="6.9" # Major and minor versions of this kernel. - KERNELPATCHDIR='rockchip-rk3588-collabora' - KERNELSOURCE='https://gitlab.collabora.com/hardware-enablement/rockchip-3588/linux.git' - KERNELBRANCH='branch:rk3588-v6.9' # Rolling kernel branch, will be rebased - KERNEL_DRIVERS_SKIP+=(driver_rtw88) # This is a custom kernel, while the rtw88 driver patching expects pure mainline + KERNELPATCHDIR='rockchip-rk3588-collabora' # Try to keep this as empty as possible. We won't work on top of Collabora's branch, they rebase all the time. New DTs are ok. + KERNELSOURCE='https://gitlab.collabora.com/hardware-enablement/rockchip-3588/linux.git' # Directly from Collabora... + KERNELBRANCH='branch:rk3588-v6.9' # Rolling kernel branch, will be rebased + KERNEL_DRIVERS_SKIP+=(driver_rtw88) # This is a custom kernel, while the rtw88 driver patching expects pure mainline ;; esac diff --git a/patch/kernel/rockchip-rk3588-edge/0000.patching_config.yaml b/patch/kernel/archive/rockchip-rk3588-6.10/0000.patching_config.yaml similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0000.patching_config.yaml rename to patch/kernel/archive/rockchip-rk3588-6.10/0000.patching_config.yaml diff --git a/patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0001-general-add-overlay-support.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0001-general-add-overlay-support.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0001-general-add-overlay-support.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0010-fix-clk-divisions.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0010-fix-clk-divisions.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0010-fix-clk-divisions.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0010-fix-clk-divisions.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0011-irqchip-fix-its-timeout-issue.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0011-irqchip-fix-its-timeout-issue.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0011-irqchip-fix-its-timeout-issue.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0011-irqchip-fix-its-timeout-issue.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0012-fix-initial-PERST-GPIO-value.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0012-fix-initial-PERST-GPIO-value.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0012-fix-initial-PERST-GPIO-value.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0012-fix-initial-PERST-GPIO-value.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0022-RK3588-Add-Thermal-and-CpuFreq-Support.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0024-RK3588-Add-Crypto-Support.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0024-RK3588-Add-Crypto-Support.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0024-RK3588-Add-Crypto-Support.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0024-RK3588-Add-Crypto-Support.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0025-RK3588-Add-HW-RNG-Support.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0025-RK3588-Add-HW-RNG-Support.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0025-RK3588-Add-HW-RNG-Support.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0025-RK3588-Add-HW-RNG-Support.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0144-phy-phy-rockchip-samsung-hdptx-Add-FRL-EARC-support.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0145-phy-phy-rockchip-samsung-hdptx-Add-clock-provider.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0146-drm-rockchip-vop2-Improve-display-modes-handling-on-.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0161-drm-bridge-synopsys-Add-initial-support-for-DW-HDMI-Controller.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0162-drm-bridge-synopsys-Fix-HDMI-Controller.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0801-wireless-add-bcm43752.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0801-wireless-add-bcm43752.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0801-wireless-add-bcm43752.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0801-wireless-add-bcm43752.patch diff --git a/patch/kernel/rockchip-rk3588-edge/0802-wireless-add-clk-property.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0802-wireless-add-clk-property.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/0802-wireless-add-clk-property.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0802-wireless-add-clk-property.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1010-arm64-dts-rock-5b-Slow-down-emmc-to-hs200-and-add-ts.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1011-board-rock-5b-arm64-dts-enable-spi-flash.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1012-arm64-dts-rockchip-Enable-HDMI0-on-rock-5b.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1014-arm64-dts-rockchip-Make-use-of-HDMI0-PHY-PLL-on-rock5b.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1015-board-rock5b-automatic-fan-control.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1015-board-rock5b-automatic-fan-control.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1015-board-rock5b-automatic-fan-control.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1020-Add-HDMI-and-VOP2-to-Rock-5A.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1021-arch-arm64-dts-enable-gpu-node-for-rock-5a.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1021-arm64-dts-Add-missing-nodes-to-Orange-Pi-5-Plus.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1022-arm64-dts-rockchip-support-poweroff-on-rock-5a.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1023-arm64-dts-rockchip-add-PCIe-for-M.2-E-Key-to-rock-5a.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1031-arm64-dts-rockchip-Add-HDMI-support-to-ArmSoM-Sige7.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1032-arm64-dts-rockchip-Add-ap6275p-wireless-support-to-A.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1041-board-khadas-edge2-mcu.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1041-board-khadas-edge2-mcu.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1041-board-khadas-edge2-mcu.patch diff --git a/patch/kernel/rockchip-rk3588-edge/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch diff --git a/patch/kernel/rockchip-rk3588-edge/dt/rk3588-bananapi-m7.dts b/patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588-bananapi-m7.dts similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/dt/rk3588-bananapi-m7.dts rename to patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588-bananapi-m7.dts diff --git a/patch/kernel/rockchip-rk3588-edge/dt/rk3588-hinlink-h88k.dts b/patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588-hinlink-h88k.dts similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/dt/rk3588-hinlink-h88k.dts rename to patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588-hinlink-h88k.dts diff --git a/patch/kernel/rockchip-rk3588-edge/dt/rk3588-mixtile-blade3.dts b/patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588-mixtile-blade3.dts similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/dt/rk3588-mixtile-blade3.dts rename to patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588-mixtile-blade3.dts diff --git a/patch/kernel/rockchip-rk3588-edge/dt/rk3588-nanopc-cm3588-nas.dts b/patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588-nanopc-cm3588-nas.dts similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/dt/rk3588-nanopc-cm3588-nas.dts rename to patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588-nanopc-cm3588-nas.dts diff --git a/patch/kernel/rockchip-rk3588-edge/dt/rk3588s-nanopi-r6c.dts b/patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588s-nanopi-r6c.dts similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/dt/rk3588s-nanopi-r6c.dts rename to patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588s-nanopi-r6c.dts diff --git a/patch/kernel/rockchip-rk3588-edge/dt/rk3588s-nanopi-r6s.dts b/patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588s-nanopi-r6s.dts similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/dt/rk3588s-nanopi-r6s.dts rename to patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588s-nanopi-r6s.dts diff --git a/patch/kernel/rockchip-rk3588-edge/dt/rk3588s-orangepi-5.dts b/patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588s-orangepi-5.dts similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/dt/rk3588s-orangepi-5.dts rename to patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588s-orangepi-5.dts diff --git a/patch/kernel/rockchip-rk3588-edge/dt/rk3588s-orangepi-5b.dts b/patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588s-orangepi-5b.dts similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/dt/rk3588s-orangepi-5b.dts rename to patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588s-orangepi-5b.dts diff --git a/patch/kernel/rockchip-rk3588-edge/dt/rk3588s-rock-5c.dts b/patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588s-rock-5c.dts similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/dt/rk3588s-rock-5c.dts rename to patch/kernel/archive/rockchip-rk3588-6.10/dt/rk3588s-rock-5c.dts diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/Makefile b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/Makefile similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/Makefile rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/Makefile diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm0-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm0-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m1.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm0-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m1.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm0-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m2.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm0-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm0-m2.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm0-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm1-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm1-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m1.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm1-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m1.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm1-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m2.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm1-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm1-m2.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm1-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm10-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm10-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm10-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm10-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm11-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm11-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m1.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm11-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm11-m1.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm11-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm12-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm12-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm12-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm12-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm13-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm13-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m2.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm13-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm13-m2.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm13-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm14-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm14-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m1.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm14-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m1.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm14-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m2.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm14-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm14-m2.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm14-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm15-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm15-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m1.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm15-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m1.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm15-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m2.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm15-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m2.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm15-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m3.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm15-m3.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm15-m3.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm15-m3.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm2-m1.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm2-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm2-m1.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm2-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm3-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm3-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m1.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm3-m1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m1.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm3-m1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m2.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm3-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m2.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm3-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m3.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm3-m3.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm3-m3.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm3-m3.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm5-m2.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm5-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm5-m2.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm5-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm6-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm6-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m2.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm6-m2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm6-m2.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm6-m2.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm7-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm7-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m3.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm7-m3.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm7-m3.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm7-m3.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm8-m0.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm8-m0.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-pwm8-m0.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-pwm8-m0.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata1.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-sata1.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata1.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-sata1.dtso diff --git a/patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata2.dtso b/patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-sata2.dtso similarity index 100% rename from patch/kernel/rockchip-rk3588-edge/overlay/rockchip-rk3588-sata2.dtso rename to patch/kernel/archive/rockchip-rk3588-6.10/overlay/rockchip-rk3588-sata2.dtso From 874c09f896e0e29119a5dd220ad4998422f7e5fa Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:39:23 +0200 Subject: [PATCH 36/53] rk3588: Add board NanoPi R6C With support for the latest mainline U-Boot. --- config/boards/nanopi-r6c.csc | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 config/boards/nanopi-r6c.csc diff --git a/config/boards/nanopi-r6c.csc b/config/boards/nanopi-r6c.csc new file mode 100644 index 000000000000..0ca97a11a1fe --- /dev/null +++ b/config/boards/nanopi-r6c.csc @@ -0,0 +1,55 @@ +# Rockchip RK3588S octa core 8GB RAM SoC eMMC 1x NVMe 1x USB3 1x USB2 1x 2.5GbE 1x GbE +BOARD_NAME="NanoPi R6C" +BOARDFAMILY="rockchip-rk3588" +BOARD_MAINTAINER="ColorfulRhino" +BOOTCONFIG="nanopi-r6c-rk3588s_defconfig" # vendor name, not standard, see hook below, set BOOT_SOC below to compensate +BOOT_SOC="rk3588" +KERNEL_TARGET="vendor,current,edge" +FULL_DESKTOP="yes" +BOOT_LOGO="desktop" +IMAGE_PARTITION_TABLE="gpt" +BOOT_FDT_FILE="rockchip/rk3588s-nanopi-r6c.dtb" +BOOT_SCENARIO="spl-blobs" +DDR_BLOB='rk35/rk3588_ddr_lp4_2112MHz_lp5_2400MHz_v1.16.bin' +BL31_BLOB='rk35/rk3588_bl31_v1.45.elf' + +function post_family_tweaks__nanopi_r6c_naming_audios() { + display_alert "$BOARD" "Renaming NanoPi R6C HDMI audio interface to human-readable form" "info" + + mkdir -p $SDCARD/etc/udev/rules.d/ + cat <<- EOF > $SDCARD/etc/udev/rules.d/90-naming-audios.rules + SUBSYSTEM=="sound", ENV{ID_PATH}=="platform-hdmi0-sound", ENV{SOUND_DESCRIPTION}="HDMI0 Audio"' + EOF +} + +function post_family_tweaks__nanopi_r6c_naming_udev_network_interfaces() { + display_alert "$BOARD" "Renaming NanoPi R6C network interfaces to 'wan' and 'lan'" "info" + + mkdir -p $SDCARD/etc/udev/rules.d/ + cat <<- EOF > "${SDCARD}/etc/udev/rules.d/70-persistent-net.rules" + SUBSYSTEM=="net", ACTION=="add", KERNELS=="fe1c0000.ethernet", NAME:="wan" + SUBSYSTEM=="net", ACTION=="add", KERNELS=="0003:31:00.0", NAME:="lan" + EOF +} + +# Mainline U-Boot +function post_family_config__nanopi_r6c_use_mainline_uboot() { + display_alert "$BOARD" "Using mainline U-Boot for $BOARD / $BRANCH" "info" + + declare -g BOOTCONFIG="generic-rk3588_defconfig" # Use generic defconfig which should boot all RK3588 boards + declare -g BOOTDELAY=1 # Wait for UART interrupt to enter UMS/RockUSB mode etc + declare -g BOOTSOURCE="https://github.com/u-boot/u-boot.git" # We â¤ï¸ Mainline U-Boot + declare -g BOOTBRANCH="tag:v2024.07-rc4" + declare -g BOOTPATCHDIR="v2024.07/board_${BOARD}" + # Don't set BOOTDIR, allow shared U-Boot source directory for disk space efficiency + + declare -g UBOOT_TARGET_MAP="BL31=${RKBIN_DIR}/${BL31_BLOB} ROCKCHIP_TPL=${RKBIN_DIR}/${DDR_BLOB};;u-boot-rockchip.bin" + + # Disable stuff from rockchip64_common; we're using binman here which does all the work already + unset uboot_custom_postprocess write_uboot_platform write_uboot_platform_mtd + + # Just use the binman-provided u-boot-rockchip.bin, which is ready-to-go + function write_uboot_platform() { + dd "if=$1/u-boot-rockchip.bin" "of=$2" bs=32k seek=1 conv=notrunc status=none + } +} From 96eba61177d04298baf0149611b6b37c704501d9 Mon Sep 17 00:00:00 2001 From: Muhammed Efe Cetin Date: Thu, 13 Jun 2024 13:34:40 +0300 Subject: [PATCH 37/53] rockchip-rk3588-edge: re-add edge2 patches and fix mcu fan control patch --- .../1040-board-khadas-edge2-add-nodes.patch | 325 ++++++++++++++++++ .../1041-board-khadas-edge2-mcu.patch | 18 +- ...dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch | 18 +- 3 files changed, 340 insertions(+), 21 deletions(-) create mode 100644 patch/kernel/archive/rockchip-rk3588-6.10/1040-board-khadas-edge2-add-nodes.patch diff --git a/patch/kernel/archive/rockchip-rk3588-6.10/1040-board-khadas-edge2-add-nodes.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1040-board-khadas-edge2-add-nodes.patch new file mode 100644 index 000000000000..1cd96d16869d --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.10/1040-board-khadas-edge2-add-nodes.patch @@ -0,0 +1,325 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Mon, 12 Feb 2024 17:35:13 +0300 +Subject: arm64: dts: rockchip: Add USB-C to Khadas Edge 2 + +Khadas Edge 2 has 2x Type-C port. One just supports PD and +controlled by MCU. The other one supports PD, DP Alt mode and DRD. This +commit adds support for DRD. + +Signed-off-by: Muhammed Efe Cetin +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 120 ++++++++++ + 1 file changed, 120 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include "rk3588s.dtsi" + + / { +@@ -76,6 +77,18 @@ blue_led: led-2 { + }; + }; + ++ vbus5v0_typec: vbus5v0-typec-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vbus5v0_typec"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&vcc5v0_sys>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&typec5v_pwren>; ++ }; ++ + vcc3v3_pcie_wl: vcc3v3-pcie-wl-regulator { + compatible = "regulator-fixed"; + enable-active-high; +@@ -224,6 +237,56 @@ regulator-state-mem { + &i2c2 { + status = "okay"; + ++ usbc0: usb-typec@22 { ++ compatible = "fcs,fusb302"; ++ reg = <0x22>; ++ interrupt-parent = <&gpio1>; ++ interrupts = ; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usbc0_int>; ++ vbus-supply = <&vbus5v0_typec>; ++ status = "okay"; ++ ++ usb_con: connector { ++ compatible = "usb-c-connector"; ++ label = "USB-C"; ++ data-role = "dual"; ++ power-role = "dual"; ++ try-power-role = "source"; ++ op-sink-microwatt = <1000000>; ++ sink-pdos = ; ++ source-pdos = ; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ usbc0_orien_sw: endpoint { ++ remote-endpoint = <&usbdp_phy0_orientation_switch>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ usbc0_role_sw: endpoint { ++ remote-endpoint = <&dwc3_0_role_switch>; ++ }; ++ }; ++ ++ port@2 { ++ reg = <2>; ++ dp_altmode_mux: endpoint { ++ remote-endpoint = <&usbdp_phy0_dp_altmode_mux>; ++ }; ++ }; ++ }; ++ }; ++ }; ++ + hym8563: rtc@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; +@@ -256,6 +319,16 @@ vcc5v0_host_en: vcc5v0-host-en { + }; + }; + ++ usb-typec { ++ usbc0_int: usbc0-int { ++ rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ ++ typec5v_pwren: typec5v-pwren { ++ rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ + ir-receiver { + ir_receiver_pin: ir-receiver-pin { + rockchip,pins = <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>; +@@ -681,6 +754,15 @@ &uart9 { + status = "okay"; + }; + ++&u2phy0 { ++ status = "okay"; ++}; ++ ++&u2phy0_otg { ++ status = "okay"; ++}; ++ ++ + &u2phy2 { + status = "okay"; + }; +@@ -707,6 +789,44 @@ &usb_host0_ohci { + status = "okay"; + }; + ++&usbdp_phy0 { ++ orientation-switch; ++ mode-switch; ++ svid = <0xff01>; ++ sbu1-dc-gpios = <&gpio4 RK_PA0 GPIO_ACTIVE_HIGH>; ++ sbu2-dc-gpios = <&gpio4 RK_PA1 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ usbdp_phy0_orientation_switch: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&usbc0_orien_sw>; ++ }; ++ ++ usbdp_phy0_dp_altmode_mux: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&dp_altmode_mux>; ++ }; ++ }; ++}; ++ ++&usb_host0_xhci { ++ usb-role-switch; ++ status = "okay"; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ dwc3_0_role_switch: endpoint@0 { ++ reg = <0>; ++ remote-endpoint = <&usbc0_role_sw>; ++ }; ++ }; ++}; ++ + &usb_host1_ehci { + status = "okay"; + }; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Mon, 12 Feb 2024 17:35:13 +0300 +Subject: arm64: dts: rockchip: Add bluetooth rfkill to Khadas Edge 2 + +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -116,6 +116,15 @@ vcc5v0_host: vcc5v0-host-regulator { + vin-supply = <&vcc5v0_sys>; + }; + ++ bluetooth-rfkill { ++ compatible = "rfkill-gpio"; ++ label = "rfkill-bluetooth"; ++ radio-type = "bluetooth"; ++ shutdown-gpios = <&gpio0 RK_PD4 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bt_reset_pin>; ++ }; ++ + vcc5v0_sys: vcc5v0-sys-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Mon, 19 Feb 2024 23:32:11 +0300 +Subject: arm64: dts: rockchip: Add HDMI & VOP2 to Khadas Edge 2 + +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 36 ++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include "rk3588s.dtsi" + + / { +@@ -823,6 +824,7 @@ usbdp_phy0_dp_altmode_mux: endpoint@1 { + }; + + &usb_host0_xhci { ++ dr-mode = "otg"; + usb-role-switch; + status = "okay"; + +@@ -847,3 +849,37 @@ &usb_host1_ohci { + &usb_host2_xhci { + status = "okay"; + }; ++ ++&hdmi0 { ++ status = "okay"; ++}; ++ ++&hdptxphy_hdmi0 { ++ status = "okay"; ++}; ++ ++&display_subsystem { ++ clocks = <&hdptxphy_hdmi0>; ++ clock-names = "hdmi0_phy_pll"; ++}; ++ ++&vop_mmu { ++ status = "okay"; ++}; ++ ++&hdmi0_in { ++ hdmi0_in_vp0: endpoint { ++ remote-endpoint = <&vp0_out_hdmi0>; ++ }; ++}; ++ ++&vop { ++ status = "okay"; ++}; ++ ++&vp0 { ++ vp0_out_hdmi0: endpoint@ROCKCHIP_VOP2_EP_HDMI0 { ++ reg = ; ++ remote-endpoint = <&hdmi0_in_vp0>; ++ }; ++}; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Muhammed Efe Cetin +Date: Sat, 2 Mar 2024 19:13:59 +0300 +Subject: arm64: dts: rockchip: Add AP6275P wireless support to Khadas Edge 2 + +--- + arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts | 17 ++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +@@ -366,6 +366,23 @@ &pcie2x1l2 { + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie_wl>; + status = "okay"; ++ ++ pcie@0,0 { ++ reg = <0x400000 0 0 0 0>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ ranges; ++ device_type = "pci"; ++ bus-range = <0x40 0x4f>; ++ ++ wifi: wifi@0,0 { ++ compatible = "pci14e4,449d"; ++ reg = <0x410000 0 0 0 0>; ++ clocks = <&hym8563>; ++ clock-names = "32k"; ++ }; ++ }; ++ + }; + + &pwm11 { +-- +Armbian + diff --git a/patch/kernel/archive/rockchip-rk3588-6.10/1041-board-khadas-edge2-mcu.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1041-board-khadas-edge2-mcu.patch index feb3f1838c84..985f0b34c403 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.10/1041-board-khadas-edge2-mcu.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.10/1041-board-khadas-edge2-mcu.patch @@ -4,9 +4,9 @@ Date: Wed, 6 Mar 2024 00:09:25 +0300 Subject: mfd: khadas-mcu: add Edge2 registers --- - drivers/mfd/khadas-mcu.c | 6 ++- + drivers/mfd/khadas-mcu.c | 8 +++- include/linux/mfd/khadas-mcu.h | 24 ++++++++++ - 2 files changed, 29 insertions(+), 1 deletion(-) + 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c index 111111111111..222222222222 100644 @@ -23,7 +23,15 @@ index 111111111111..222222222222 100644 return true; default: return false; -@@ -76,7 +80,7 @@ static const struct regmap_config khadas_mcu_regmap_config = { +@@ -69,14 +73,14 @@ static const struct regmap_config khadas_mcu_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, +- .max_register = KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG, ++ .max_register = KHADAS_MCU_SYS_RST_REG, + .volatile_reg = khadas_mcu_reg_volatile, + .writeable_reg = khadas_mcu_reg_writeable, + .cache_type = REGCACHE_MAPLE, }; static struct mfd_cell khadas_mcu_fan_cells[] = { @@ -335,7 +343,7 @@ diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/ index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -231,6 +231,13 @@ hym8563: rtc@51 { +@@ -304,6 +304,13 @@ hym8563: rtc@51 { clock-output-names = "hym8563"; wakeup-source; }; @@ -365,7 +373,7 @@ diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts b/arch/arm64/ index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-khadas-edge2.dts -@@ -240,6 +240,62 @@ khadas_mcu: system-controller@18 { +@@ -313,6 +313,62 @@ khadas_mcu: system-controller@18 { }; }; diff --git a/patch/kernel/archive/rockchip-rk3588-6.10/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch b/patch/kernel/archive/rockchip-rk3588-6.10/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch index 71955ebcdd19..6b842c006ea3 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.10/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.10/1051-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch @@ -9,17 +9,10 @@ Signed-off-by: Ricardo Pardini 1 file changed, 14 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts -index ad8e36a339dc4..2085e73a44642 100644 +index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts -@@ -569,20 +569,34 @@ &sdmmc { - cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; - disable-wp; - no-mmc; - no-sdio; - sd-uhs-sdr104; - vmmc-supply = <&vcc3v3_sd_s0>; - vqmmc-supply = <&vccio_sd_s0>; +@@ -576,6 +576,20 @@ &sdmmc { status = "okay"; }; @@ -40,13 +33,6 @@ index ad8e36a339dc4..2085e73a44642 100644 &spi2 { status = "okay"; assigned-clocks = <&cru CLK_SPI2>; - assigned-clock-rates = <200000000>; - pinctrl-names = "default"; - pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; - num-cs = <1>; - - pmic@0 { - compatible = "rockchip,rk806"; -- Armbian From d0684925e37c9e3e838059ec7b9994eaac299e09 Mon Sep 17 00:00:00 2001 From: Muhammed Efe Cetin Date: Thu, 13 Jun 2024 16:18:09 +0300 Subject: [PATCH 38/53] rockchip-rk3588-edge: add vop2 clocks reset patch --- ...ckchip-vop2-add-clocks-reset-support.patch | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 patch/kernel/archive/rockchip-rk3588-6.10/0170-drm-rockchip-vop2-add-clocks-reset-support.patch diff --git a/patch/kernel/archive/rockchip-rk3588-6.10/0170-drm-rockchip-vop2-add-clocks-reset-support.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0170-drm-rockchip-vop2-add-clocks-reset-support.patch new file mode 100644 index 000000000000..e67dea963614 --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.10/0170-drm-rockchip-vop2-add-clocks-reset-support.patch @@ -0,0 +1,190 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Detlev Casanova +Date: Fri, 3 May 2024 14:27:39 -0400 +Subject: vop2: Add clock resets support + +At the end of initialization, each VP clock needs to be reset before +they can be used. + +Failing to do so can put the VOP in an undefined state where the +generated HDMI signal is either lost or not matching the selected mode. + +Signed-off-by: Detlev Casanova +--- + drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 30 ++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +index 111111111111..222222222222 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c ++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -159,6 +160,7 @@ struct vop2_win { + struct vop2_video_port { + struct drm_crtc crtc; + struct vop2 *vop2; ++ struct reset_control *dclk_rst; + struct clk *dclk; + unsigned int id; + const struct vop2_video_port_data *data; +@@ -2064,6 +2066,26 @@ static struct vop2_clk *vop2_clk_get(struct vop2 *vop2, const char *name) + return NULL; + } + ++static int vop2_clk_reset(struct vop2_video_port *vp) ++{ ++ struct reset_control *rstc = vp->dclk_rst; ++ struct vop2 *vop2 = vp->vop2; ++ int ret; ++ ++ if (!rstc) ++ return 0; ++ ++ ret = reset_control_assert(rstc); ++ if (ret < 0) ++ drm_warn(vop2->drm, "failed to assert reset\n"); ++ udelay(10); ++ ret = reset_control_deassert(rstc); ++ if (ret < 0) ++ drm_warn(vop2->drm, "failed to deassert reset\n"); ++ ++ return ret; ++} ++ + static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *state) + { +@@ -2233,6 +2255,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, + + vop2_vp_write(vp, RK3568_VP_DSP_CTRL, dsp_ctrl); + ++ vop2_clk_reset(vp); ++ + drm_crtc_vblank_on(crtc); + + vop2_unlock(vop2); +@@ -2920,6 +2944,12 @@ static int vop2_create_crtcs(struct vop2 *vop2) + vp->data = vp_data; + + snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id); ++ vp->dclk_rst = devm_reset_control_get_optional(vop2->dev, dclk_name); ++ if (IS_ERR(vp->dclk_rst)) { ++ drm_err(vop2->drm, "failed to get %s reset\n", dclk_name); ++ return PTR_ERR(vp->dclk_rst); ++ } ++ + vp->dclk = devm_clk_get(vop2->dev, dclk_name); + if (IS_ERR(vp->dclk)) { + drm_err(vop2->drm, "failed to get %s\n", dclk_name); +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Detlev Casanova +Date: Fri, 3 May 2024 14:28:12 -0400 +Subject: arm64: dts: rockchip: Add VOP clock resets for rk3588s + +This adds the needed clock resets for all rk3588(s) based SOCs. + +Signed-off-by: Detlev Casanova +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -1348,6 +1348,14 @@ vop: vop@fdd90000 { + "pclk_vop"; + iommus = <&vop_mmu>; + power-domains = <&power RK3588_PD_VOP>; ++ resets = <&cru SRST_D_VOP0>, ++ <&cru SRST_D_VOP1>, ++ <&cru SRST_D_VOP2>, ++ <&cru SRST_D_VOP3>; ++ reset-names = "dclk_vp0", ++ "dclk_vp1", ++ "dclk_vp2", ++ "dclk_vp3"; + rockchip,grf = <&sys_grf>; + rockchip,vop-grf = <&vop_grf>; + rockchip,vo1-grf = <&vo1_grf>; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Detlev Casanova +Date: Mon, 6 May 2024 13:54:01 -0400 +Subject: dt-bindings: display: vop2: Add VP clock resets + +Add the documentation for VOP2 video ports reset clocks. +One reset can be set per video port. + +Signed-off-by: Detlev Casanova +--- + Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml | 27 ++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml +index 111111111111..222222222222 100644 +--- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml ++++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml +@@ -65,6 +65,22 @@ properties: + - const: dclk_vp3 + - const: pclk_vop + ++ resets: ++ minItems: 3 ++ items: ++ - description: Pixel clock reset for video port 0. ++ - description: Pixel clock reset for video port 1. ++ - description: Pixel clock reset for video port 2. ++ - description: Pixel clock reset for video port 3. ++ ++ reset-names: ++ minItems: 3 ++ items: ++ - const: dclk_vp0 ++ - const: dclk_vp1 ++ - const: dclk_vp2 ++ - const: dclk_vp3 ++ + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: +@@ -128,6 +144,11 @@ allOf: + clock-names: + minItems: 7 + ++ resets: ++ minItems: 4 ++ reset-names: ++ minItems: 4 ++ + ports: + required: + - port@0 +@@ -183,6 +204,12 @@ examples: + "dclk_vp0", + "dclk_vp1", + "dclk_vp2"; ++ resets = <&cru SRST_VOP0>, ++ <&cru SRST_VOP1>, ++ <&cru SRST_VOP2>; ++ reset-names = "dclk_vp0", ++ "dclk_vp1", ++ "dclk_vp2"; + power-domains = <&power RK3568_PD_VO>; + iommus = <&vop_mmu>; + vop_out: ports { +-- +Armbian + From 24938adafeea9cd158557891eb85ea0730b41852 Mon Sep 17 00:00:00 2001 From: Viacheslav Bocharov Date: Thu, 13 Jun 2024 09:25:44 +0300 Subject: [PATCH 39/53] JetHub D2 (j200) add u-boot 2024.01 patches --- .../0001-Add-some-amlogic-sm-functions.patch | 218 +++++ .../0002-jethub-D2-j200-add.patch | 869 ++++++++++++++++++ .../board_jethubj200/0003-fix-j200.patch | 30 + ...ACK-mmc-meson-gx-limit-to-24MHz.patch.diff | 29 + .../enable-DT-overlays-support.patch | 15 + 5 files changed, 1161 insertions(+) create mode 100644 patch/u-boot/v2024.01/board_jethubj200/0001-Add-some-amlogic-sm-functions.patch create mode 100644 patch/u-boot/v2024.01/board_jethubj200/0002-jethub-D2-j200-add.patch create mode 100644 patch/u-boot/v2024.01/board_jethubj200/0003-fix-j200.patch create mode 100644 patch/u-boot/v2024.01/board_jethubj200/0004-HACK-mmc-meson-gx-limit-to-24MHz.patch.diff create mode 100644 patch/u-boot/v2024.01/board_jethubj200/enable-DT-overlays-support.patch diff --git a/patch/u-boot/v2024.01/board_jethubj200/0001-Add-some-amlogic-sm-functions.patch b/patch/u-boot/v2024.01/board_jethubj200/0001-Add-some-amlogic-sm-functions.patch new file mode 100644 index 000000000000..a3959078b299 --- /dev/null +++ b/patch/u-boot/v2024.01/board_jethubj200/0001-Add-some-amlogic-sm-functions.patch @@ -0,0 +1,218 @@ +From 166c1ab03acbfaafd90d2013eda6ff0a84ab0a91 Mon Sep 17 00:00:00 2001 +From: Viacheslav Bocharov +Date: Tue, 31 Oct 2023 12:16:43 +0300 +Subject: [PATCH 1/2] Add some amlogic sm functions + +--- + arch/arm/include/asm/arch-meson/sm.h | 18 ++++++++++ + arch/arm/mach-meson/sm.c | 41 +++++++++++++++++++++++ + cmd/meson/sm.c | 49 +++++++++++++++++++++++++++- + drivers/sm/meson-sm.c | 1 + + include/meson/sm.h | 1 + + 5 files changed, 109 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/include/asm/arch-meson/sm.h b/arch/arm/include/asm/arch-meson/sm.h +index 4b1d564bc4..57ab90ab1c 100644 +--- a/arch/arm/include/asm/arch-meson/sm.h ++++ b/arch/arm/include/asm/arch-meson/sm.h +@@ -26,7 +26,16 @@ ssize_t meson_sm_read_efuse(uintptr_t offset, void *buffer, size_t size); + */ + ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size); + ++/** ++ * meson_sm_getmax - get max size of user efuse ++ * @buffer: pointer to buffer ++ * @size: buffer size ++ * @return: size of user efuse or -errno on failure ++ */ ++ssize_t meson_sm_getmax(void *buffer, size_t size); ++ + #define SM_SERIAL_SIZE 12 ++#define SM_SERIAL2_SIZE 16 + + /** + * meson_sm_get_serial - read chip unique id into buffer +@@ -37,6 +46,15 @@ ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size); + */ + int meson_sm_get_serial(void *buffer, size_t size); + ++/** ++ * meson_sm_get_serial2 - read chip unique id (ver.2) into buffer ++ * ++ * @buffer: pointer to buffer ++ * @size: buffer size. ++ * @return: zero on success or -errno on failure ++ */ ++int meson_sm_get_serial2(void *buffer, size_t size); ++ + enum { + REBOOT_REASON_COLD = 0, + REBOOT_REASON_NORMAL = 1, +diff --git a/arch/arm/mach-meson/sm.c b/arch/arm/mach-meson/sm.c +index 914fd11c98..6f4861a30c 100644 +--- a/arch/arm/mach-meson/sm.c ++++ b/arch/arm/mach-meson/sm.c +@@ -77,7 +77,26 @@ ssize_t meson_sm_write_efuse(uintptr_t offset, void *buffer, size_t size) + return err; + } + ++ssize_t meson_sm_getmax(void *buffer, size_t size) ++{ ++ struct udevice *dev; ++ struct pt_regs regs = { 0 }; ++ int err; ++ ++ dev = meson_get_sm_device(); ++ if (IS_ERR(dev)) ++ return PTR_ERR(dev); ++ ++ err = sm_call_read(dev, buffer, size, ++ MESON_SMC_CMD_EFUSE_MAX, ®s); ++ if (err < 0) ++ pr_err("Failed to read max size of efuse memory (%d)\n", err); ++ ++ return err; ++} ++ + #define SM_CHIP_ID_LENGTH 119 ++#define SM_CHIP_ID_LENGTH2 128 + #define SM_CHIP_ID_OFFSET 4 + #define SM_CHIP_ID_SIZE 12 + +@@ -102,6 +121,28 @@ int meson_sm_get_serial(void *buffer, size_t size) + return 0; + } + ++int meson_sm_get_serial2(void *buffer, size_t size) ++{ ++ struct udevice *dev; ++ struct pt_regs regs = { 0 }; ++ regs.regs[1] = 2; ++ u8 id_buffer[SM_CHIP_ID_LENGTH2]; ++ int err; ++ ++ dev = meson_get_sm_device(); ++ if (IS_ERR(dev)) ++ return PTR_ERR(dev); ++ ++ err = sm_call_read(dev, id_buffer, SM_CHIP_ID_LENGTH, ++ MESON_SMC_CMD_CHIP_ID_GET, ®s); ++ if (err < 0) ++ pr_err("Failed to read serial number (%d)\n", err); ++ ++ memcpy(buffer, id_buffer + SM_CHIP_ID_OFFSET, size); ++ ++ return 0; ++} ++ + #define AO_SEC_SD_CFG15 0xfc + #define REBOOT_REASON_MASK GENMASK(15, 12) + +diff --git a/cmd/meson/sm.c b/cmd/meson/sm.c +index de9a242e17..faa7240621 100644 +--- a/cmd/meson/sm.c ++++ b/cmd/meson/sm.c +@@ -33,6 +33,25 @@ static int do_sm_serial(struct cmd_tbl *cmdtp, int flag, int argc, + return CMD_RET_SUCCESS; + } + ++static int do_sm_serialv2(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ ulong address; ++ int ret; ++ ++ if (argc < 2) ++ return CMD_RET_USAGE; ++ ++ address = simple_strtoul(argv[1], NULL, 0); ++ ++ ret = meson_sm_get_serial2((void *)address, SM_SERIAL2_SIZE); ++ if (ret) ++ return CMD_RET_FAILURE; ++ ++ return CMD_RET_SUCCESS; ++} ++ ++ + #define MAX_REBOOT_REASONS 14 + + static const char *reboot_reasons[MAX_REBOOT_REASONS] = { +@@ -152,12 +171,38 @@ free_buffer: + return ret; + } + ++static int do_efuse_getmax(struct cmd_tbl *cmdtp, int flag, int argc, ++ char *const argv[]) ++{ ++ char efusesizeprint[32]; // this covers int64 (2^64), which is 20 digits long ++ char *destarg = NULL; ++ int efusesize; ++ ++ if (argc > 1) ++ destarg = argv[1]; ++ ++ efusesize = meson_sm_getmax(NULL, 0); // TODO: check if this is correct ++ if (efusesize < 0) ++ return CMD_RET_FAILURE; ++ ++ snprintf(efusesizeprint, sizeof(efusesizeprint), "%d", efusesize); ++ if (destarg) ++ env_set(destarg, efusesizeprint); ++ else ++ printf("%s\n", efusesizeprint); ++ ++ return CMD_RET_SUCCESS; ++} ++ + static struct cmd_tbl cmd_sm_sub[] = { + U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""), ++ U_BOOT_CMD_MKENT(serialv2, 2, 1, do_sm_serialv2, "", ""), + U_BOOT_CMD_MKENT(reboot_reason, 1, 1, do_sm_reboot_reason, "", ""), + U_BOOT_CMD_MKENT(efuseread, 4, 1, do_efuse_read, "", ""), + U_BOOT_CMD_MKENT(efusewrite, 4, 0, do_efuse_write, "", ""), + U_BOOT_CMD_MKENT(efusedump, 3, 1, do_efuse_dump, "", ""), ++ U_BOOT_CMD_MKENT(getmax, 2, 1, do_efuse_getmax, "", ""), ++ + }; + + static int do_sm(struct cmd_tbl *cmdtp, int flag, int argc, +@@ -184,8 +229,10 @@ U_BOOT_CMD( + sm, 5, 0, do_sm, + "Secure Monitor Control", + "serial
- read chip unique id to memory address\n" ++ "serialv2
- read chip unique id (ver 2) to memory address\n" + "sm reboot_reason [name] - get reboot reason and store to environment\n" + "sm efuseread
- read efuse to memory address\n" + "sm efusewrite
- write into efuse from memory address\n" +- "sm efusedump - dump efuse data range to console" ++ "sm efusedump - dump efuse data range to console\n" ++ "sm getmax [name] - get max size of user accesible efuse and store to environment\n" + ); +diff --git a/drivers/sm/meson-sm.c b/drivers/sm/meson-sm.c +index 15b3b0e267..c98af83a67 100644 +--- a/drivers/sm/meson-sm.c ++++ b/drivers/sm/meson-sm.c +@@ -167,6 +167,7 @@ static const struct meson_sm_data meson_sm_gxbb_data = { + .cmd_get_shmem_out = 0x82000021, + .shmem_size = SZ_4K, + .cmd = { ++ SET_CMD(MESON_SMC_CMD_EFUSE_MAX, 0x82000033), + SET_CMD(MESON_SMC_CMD_EFUSE_READ, 0x82000030), + SET_CMD(MESON_SMC_CMD_EFUSE_WRITE, 0x82000031), + SET_CMD(MESON_SMC_CMD_CHIP_ID_GET, 0x82000044), +diff --git a/include/meson/sm.h b/include/meson/sm.h +index fbaab1f1ee..99da308fb9 100644 +--- a/include/meson/sm.h ++++ b/include/meson/sm.h +@@ -9,6 +9,7 @@ + #define __MESON_SM_CMD_H__ + + enum meson_smc_cmd { ++ MESON_SMC_CMD_EFUSE_MAX, /* get max size of user efuse */ + MESON_SMC_CMD_EFUSE_READ, /* read efuse memory */ + MESON_SMC_CMD_EFUSE_WRITE, /* write efuse memory */ + MESON_SMC_CMD_CHIP_ID_GET, /* readh chip unique id */ +-- +2.34.1 + diff --git a/patch/u-boot/v2024.01/board_jethubj200/0002-jethub-D2-j200-add.patch b/patch/u-boot/v2024.01/board_jethubj200/0002-jethub-D2-j200-add.patch new file mode 100644 index 000000000000..dfeed8dad31d --- /dev/null +++ b/patch/u-boot/v2024.01/board_jethubj200/0002-jethub-D2-j200-add.patch @@ -0,0 +1,869 @@ +From 7160af7b3b2a2a7fedb9104bcdefddf114467358 Mon Sep 17 00:00:00 2001 +From: Viacheslav Bocharov +Date: Mon, 22 Jan 2024 18:38:08 +0300 +Subject: [PATCH 2/2] jethub D2 j200 add + +--- + arch/arm/dts/Makefile | 1 + + .../arm/dts/meson-sm1-jethome-jethub-j200.dts | 614 ++++++++++++++++++ + board/amlogic/jethub-j200/MAINTAINERS | 8 + + board/amlogic/jethub-j200/Makefile | 6 + + board/amlogic/jethub-j200/jethub-j200.c | 76 +++ + configs/jethub_j200_defconfig | 100 +++ + 6 files changed, 805 insertions(+) + create mode 100644 arch/arm/dts/meson-sm1-jethome-jethub-j200.dts + create mode 100644 board/amlogic/jethub-j200/MAINTAINERS + create mode 100644 board/amlogic/jethub-j200/Makefile + create mode 100644 board/amlogic/jethub-j200/jethub-j200.c + create mode 100644 configs/jethub_j200_defconfig + +diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile +index b5c588c336..33b5afe133 100644 +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -249,6 +249,7 @@ dtb-$(CONFIG_ARCH_MESON) += \ + meson-g12b-radxa-zero2.dtb \ + meson-sm1-bananapi-m2-pro.dtb \ + meson-sm1-bananapi-m5.dtb \ ++ meson-sm1-jethome-jethub-j200.dtb \ + meson-sm1-khadas-vim3l.dtb \ + meson-sm1-odroid-c4.dtb \ + meson-sm1-odroid-hc4.dtb \ +diff --git a/arch/arm/dts/meson-sm1-jethome-jethub-j200.dts b/arch/arm/dts/meson-sm1-jethome-jethub-j200.dts +new file mode 100644 +index 0000000000..9ebe3effb6 +--- /dev/null ++++ b/arch/arm/dts/meson-sm1-jethome-jethub-j200.dts +@@ -0,0 +1,614 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2020 JetHome ++ * Author: Viacheslav Bocharov ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1.dtsi" ++ ++#include ++#include ++#include ++ ++ ++/ { ++ ++ compatible = "jethome,jethub-j200", "amlogic,sm1"; ++ model = "JetHome JetHub D2"; ++ ++ aliases { ++ serial0 = &uart_AO; ++ ethernet0 = ðmac; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x40000000>; ++ }; ++ ++ emmc_pwrseq: emmc-pwrseq { ++ compatible = "mmc-pwrseq-emmc"; ++ reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>; ++ }; ++ ++ tflash_vdd: regulator-tflash_vdd { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "TFLASH_VDD"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ao GPIOAO_3 GPIO_OPEN_DRAIN>; // #TODO: check ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ tf_io: gpio-regulator-tf_io { ++ compatible = "regulator-gpio"; ++ ++ regulator-name = "TF_IO"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_5v>; ++ ++ enable-gpios = <&gpio_ao GPIOE_2 GPIO_OPEN_DRAIN>; ++ enable-active-high; ++ regulator-always-on; ++ ++ gpios = <&gpio_ao GPIOAO_6 GPIO_OPEN_SOURCE>; // #TODO: check ++ gpios-states = <0>; ++ ++ states = <3300000 0>, ++ <1800000 1>; ++ }; ++ ++ flash_1v8: regulator-flash_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "FLASH_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc_3v3>; ++ regulator-always-on; ++ }; ++ ++ main_12v: regulator-main_12v { ++ compatible = "regulator-fixed"; ++ regulator-name = "12V"; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ regulator-always-on; ++ }; ++ ++ vcc_5v: regulator-vcc_5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "5V"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ vin-supply = <&main_12v>; ++ gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>; // #TODO: check ++ enable-active-high; ++ }; ++ ++ vcc_1v8: regulator-vcc_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc_3v3>; ++ regulator-always-on; ++ }; ++ ++ vcc_3v3: regulator-vcc_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vddao_3v3>; ++ regulator-always-on; ++ /* FIXME: actually controlled by VDDCPU_B_EN */ ++ }; ++ ++ vddcpu: regulator-vddcpu { ++ /* ++ * MP8756GD Regulator. ++ */ ++ compatible = "pwm-regulator"; ++ ++ regulator-name = "VDDCPU"; ++ regulator-min-microvolt = <721000>; ++ regulator-max-microvolt = <1022000>; ++ ++ pwm-supply = <&main_12v>; ++ ++ pwms = <&pwm_AO_cd 1 1250 0>; ++ pwm-dutycycle-range = <100 0>; ++ ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ usb_pwr_en: regulator-usb_pwr_en { ++ compatible = "regulator-fixed"; ++ regulator-name = "USB_PWR_EN"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc_5v>; ++ ++ /* Connected to the microUSB port power enable */ ++ gpio = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vddao_1v8: regulator-vddao_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDAO_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vddao_3v3>; ++ regulator-always-on; ++ }; ++ ++ vddao_3v3: regulator-vddao_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDAO_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&main_12v>; ++ regulator-always-on; ++ }; ++ ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&hdmi_tx_tmds_out>; ++ }; ++ }; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDM_B Playback", "TDMOUT_B OUT"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ ++ /* 8ch hdmi interface */ ++ dai-link-0 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-1 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++ ++ meson64-reboot { ++ compatible = "meson64,reboot"; ++ sys_reset = <0x84000009>; ++ sys_poweroff = <0x84000008>; ++ ++ sd-vqen = <&gpio_ao GPIOE_2 GPIO_ACTIVE_HIGH>; ++ sd-vqsw = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; ++ sd-vmmc = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-red { ++ color = ; ++ function = LED_FUNCTION_STATUS; ++ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "heartbeat"; ++ panic-indicator; ++ }; ++ /* ++ led-red { ++ color = ; ++ function = LED_FUNCTION_POWER; ++ gpios = <&gpio_ao GPIOAO_7 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ */ ++ }; ++ ++ sound { ++ model = "JETHUB-D2"; ++ }; ++ ++}; ++ ++ ++&arb { ++ status = "okay"; ++}; ++ ++&cec_AO { ++ pinctrl-0 = <&cec_ao_a_h_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ hdmi-phandle = <&hdmi_tx>; ++}; ++ ++&cecb_AO { ++ pinctrl-0 = <&cec_ao_b_h_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ hdmi-phandle = <&hdmi_tx>; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU1_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU2_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU3_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&ext_mdio { ++ external_phy: ethernet-phy@0 { ++ /* Realtek RTL8211F (0x001cc916) */ ++ reg = <0>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; ++ /* interrupts = ;*/ ++ }; ++}; ++ ++ðmac { ++ pinctrl-0 = <ð_pins>, <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ phy-mode = "rgmii"; ++ phy-handle = <&external_phy>; ++ amlogic,tx-delay-ns = <2>; ++}; ++ ++&gpio { ++ gpio-line-names = ++ /* GPIOZ */ ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ /* GPIOH */ ++ "", "", "", "", "", ++ "LED_RED", /* GPIOH_5 */ ++ "I2C_SDA_MODULES", /* GPIOH_6 */ ++ "I2C_SCL_MODULES", /* GPIOH_7 */ ++ "", ++ /* BOOT */ ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", "", "", ++ /* GPIOC */ ++ "", "", "", "", "", "", "", "", ++ /* GPIOA */ ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "", "", ++ "I2C_SDA_SYSBUS", /* GPIOA_14 */ ++ "I2C_SCL_SYSBUS", /* GPIOA_15 */ ++ /* GPIOX */ ++ "", /* GPIOX_0 */ ++ "", /* GPIOX_1 */ ++ "", /* GPIOX_2 */ ++ "", /* GPIOX_3 */ ++ "", /* GPIOX_4 */ ++ "", /* GPIOX_5 */ ++ "RS485_TX", /* GPIOX_6 */ ++ "RS485_RX", /* GPIOX_7 */ ++ "", /* GPIOX_8 */ ++ "", /* GPIOX_9 */ ++ "", /* GPIOX_10 */ ++ "", /* GPIOX_11 */ ++ "", /* GPIOX_12 */ ++ "", /* GPIOX_13 */ ++ "", /* GPIOX_14 */ ++ "", /* GPIOX_15 */ ++ "", /* GPIOX_16 */ ++ "I2C_SDA_LCDBUS", /* GPIOX_17 */ ++ "I2C_SCL_LCDBUS", /* GPIOX_18 */ ++ ""; /* GPIOX_19 */ ++}; ++ ++&gpio_ao { ++ gpio-line-names = ++ /* GPIOAO */ ++ "", "", "", "", ++ "MCU_RESET", /* GPIOAO_4 */ ++ "POWER_GOOD", /* GPIOAO_5 */ ++ "", ++ "MCU_BOOT", /* GPIOAO_7 */ ++ "MCU_UART_TX", /* GPIOAO_8 */ ++ "MCU_UART_RX", /* GPIOAO_9 */ ++ "BUTTON_USR", /* GPIOAO_10 */ ++ "LED_SYSTEM", /* GPIOAO_11 */ ++ /* GPIOE */ ++ "", "", ""; ++}; ++ ++&hdmi_tx { ++ status = "okay"; ++ pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>; ++ pinctrl-names = "default"; ++ hdmi-supply = <&vcc_5v>; ++}; ++ ++&hdmi_tx_tmds_port { ++ hdmi_tx_tmds_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ }; ++}; ++ ++&pwm_AO_cd { ++ pinctrl-0 = <&pwm_ao_d_e_pins>; // GPIOE_1 ++ pinctrl-names = "default"; ++ clocks = <&xtal>; ++ clock-names = "clkin1"; ++ status = "okay"; ++}; ++ ++&saradc { ++ status = "okay"; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ status = "okay"; ++ pinctrl-0 = <&sdcard_c_pins>; ++ pinctrl-1 = <&sdcard_clk_gate_c_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ max-frequency = <200000000>; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ disable-wp; ++ ++ cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>; ++ vmmc-supply = <&tflash_vdd>; ++ vqmmc-supply = <&tf_io>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ status = "okay"; ++ pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_8b_pins>, <&emmc_ds_pins>; ++ pinctrl-1 = <&emmc_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ max-frequency = <200000000>; ++ disable-wp; ++ ++ mmc-pwrseq = <&emmc_pwrseq>; ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&flash_1v8>; ++}; ++ ++/* ++&sd_emmc_c { ++ pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_4b_pins>, <&emmc_ds_pins>; ++ bus-width = <4>; ++}; ++ ++&spifc { ++ status = "okay"; ++ pinctrl-0 = <&nor_pins>; ++ pinctrl-names = "default"; ++ ++ flash@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <104000000>; ++ }; ++}; ++*/ ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_AO { ++ status = "okay"; ++ pinctrl-0 = <&uart_ao_a_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&uart_AO_B { ++ status = "okay"; ++ pinctrl-0 = <&uart_ao_b_8_9_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&uart_B { ++ status = "okay"; ++ pinctrl-0 = <&uart_b_pins>; ++ pinctrl-names = "default"; ++}; ++ ++ ++&usb { ++ status = "okay"; ++ vbus-supply = <&usb_pwr_en>; ++}; ++ ++&dwc2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* USB 2.0 hub on otg port */ ++ hub_2_0: hub@1 { ++ compatible = "usb4b4,6504"; /* use 10000us timeout for reset */ ++ reg = <1>; ++ reset-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_LOW>; ++ vdd-supply = <&vcc_5v>; ++ }; ++}; ++ ++&usb2_phy0 { ++ phy-supply = <&vcc_5v>; ++}; ++ ++ ++/* I2C for modules */ ++&i2c1 { ++ status = "okay"; ++ pinctrl-0 = <&i2c1_sda_h6_pins>, <&i2c1_sck_h7_pins>; ++ pinctrl-names = "default"; ++}; ++ ++ ++/* I2C for lcd/etc */ ++&i2c2 { ++ status = "okay"; ++ pinctrl-0 = <&i2c2_sda_x_pins>, <&i2c2_sck_x_pins>; ++ pinctrl-names = "default"; ++}; ++ ++/* I2C for CPU board */ ++&i2c3 { ++ status = "okay"; ++ pinctrl-0 = <&i2c3_sda_a_pins>, <&i2c3_sck_a_pins>; ++ pinctrl-names = "default"; ++ ++ u9: gpio@20 { ++ compatible = "nxp,pca9535"; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ gpio-line-names = ++ "RELAY_1", "RELAY_2", ++ "", "", ++ "UXM1_RESET", "UXM1_BOOT", ++ "UXM2_RESET", "UXM2_BOOT", ++ "DIN_1", "DIN_2", "DIN_3", ++ "","","","",""; ++ }; ++ ++ /* I2C for rtc */ ++ rtc: rtc@51 { ++ status = "okay"; ++ compatible = "nxp,pcf8563"; ++ reg = <0x51>; ++ wakeup-source; ++ }; ++ ++ /* FRAM on base board */ ++ fram: eeprom@52 { ++ compatible = "atmel,24c64"; ++ reg = <0x52>; ++ pagesize = <0x20>; ++ label = "fram"; ++ address-width = <0x10>; ++ vcc-supply = <&vddao_3v3>; ++ }; ++ ++ /* EEPROM on CPU board */ ++ eepromc: eeprom@54 { ++ compatible = "atmel,24c64"; ++ reg = <0x54>; ++ pagesize = <0x20>; ++ label = "eepromc"; ++ address-width = <0x10>; ++ vcc-supply = <&vddao_3v3>; ++ }; ++ ++ /* EEPROM on base board */ ++ eeprompd: eeprom@56 { ++ compatible = "atmel,24c64"; ++ reg = <0x56>; ++ pagesize = <0x20>; ++ label = "eeprompd"; ++ address-width = <0x10>; ++ vcc-supply = <&vddao_3v3>; ++ }; ++ ++ /* EEPROM on power module */ ++ eeprompm: eeprom@57 { ++ compatible = "atmel,24c64"; ++ reg = <0x57>; ++ pagesize = <0x20>; ++ label = "eeprompm"; ++ address-width = <0x10>; ++ vcc-supply = <&vddao_3v3>; ++ }; ++ ++}; +\ No newline at end of file +diff --git a/board/amlogic/jethub-j200/MAINTAINERS b/board/amlogic/jethub-j200/MAINTAINERS +new file mode 100644 +index 0000000000..82f4e1c40f +--- /dev/null ++++ b/board/amlogic/jethub-j200/MAINTAINERS +@@ -0,0 +1,8 @@ ++JetHome JetHub ++M: Viacheslav Bocharov ++S: Maintained ++L: u-boot-amlogic@groups.io ++F: board/amlogic/jethub-j200/ ++F: configs/jethub_j200_defconfig ++F: doc/board/amlogic/jethub-j200.rst ++F: include/configs/jethub.h +diff --git a/board/amlogic/jethub-j200/Makefile b/board/amlogic/jethub-j200/Makefile +new file mode 100644 +index 0000000000..cb1f5cbcb2 +--- /dev/null ++++ b/board/amlogic/jethub-j200/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0+ ++# ++# (C) Copyright 2024 JetHome ++# Author: Viacheslav Bocharov ++ ++obj-y := jethub-j200.o +diff --git a/board/amlogic/jethub-j200/jethub-j200.c b/board/amlogic/jethub-j200/jethub-j200.c +new file mode 100644 +index 0000000000..d8b6d96356 +--- /dev/null ++++ b/board/amlogic/jethub-j200/jethub-j200.c +@@ -0,0 +1,76 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (C) 2024 JetHome ++ * Author: Viacheslav Bocharov ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define EFUSE_SN_OFFSET 50 ++#define EFUSE_SN_SIZE 32 ++#define EFUSE_MAC_OFFSET 0 ++#define EFUSE_MAC_SIZE 6 ++#define EFUSE_USID_OFFSET 18 ++#define EFUSE_USID_SIZE 32 ++ ++// #TODO: recheck this ++int mmc_get_env_dev(void) ++{ ++ if (meson_get_boot_device() == BOOT_DEVICE_EMMC) ++ return 1; ++ return 0; ++} ++ ++int misc_init_r(void) ++{ ++ u8 mac_addr[EFUSE_MAC_SIZE]; ++ char serial[EFUSE_SN_SIZE]; ++ char usid[EFUSE_USID_SIZE]; ++ ssize_t len; ++ /* unsigned int adcval;*/ ++ /* int ret;*/ ++ ++ if (!eth_env_get_enetaddr("ethaddr", mac_addr)) { ++ len = meson_sm_read_efuse(EFUSE_MAC_OFFSET, ++ mac_addr, EFUSE_MAC_SIZE); ++ if (len == EFUSE_MAC_SIZE && is_valid_ethaddr(mac_addr)) ++ eth_env_set_enetaddr("ethaddr", mac_addr); ++ else ++ meson_generate_serial_ethaddr(); ++ } ++ ++ if (!env_get("serial")) { ++ len = meson_sm_read_efuse(EFUSE_SN_OFFSET, serial, ++ EFUSE_SN_SIZE); ++ if (len == EFUSE_SN_SIZE) ++ env_set("serial", serial); ++ } ++ ++ if (!env_get("usid")) { ++ len = meson_sm_read_efuse(EFUSE_USID_OFFSET, usid, ++ EFUSE_USID_SIZE); ++ if (len == EFUSE_USID_SIZE) ++ env_set("usid", usid); ++ } ++ ++/* #TODO: rewrite to read gpio GPIOAO_10 ++ ret = adc_channel_single_shot("adc@8680", 0, &adcval); ++ if (adcval < 3000) ++ env_set("userbutton", "true"); ++ else ++ env_set("userbutton", "false"); ++ ++*/ ++ ++ return 0; ++} +diff --git a/configs/jethub_j200_defconfig b/configs/jethub_j200_defconfig +new file mode 100644 +index 0000000000..340fbb10da +--- /dev/null ++++ b/configs/jethub_j200_defconfig +@@ -0,0 +1,100 @@ ++CONFIG_ARM=y ++CONFIG_SYS_BOARD="jethub-j200" ++CONFIG_SYS_CONFIG_NAME="jethub" ++CONFIG_ARCH_MESON=y ++CONFIG_TEXT_BASE=0x01000000 ++CONFIG_NR_DRAM_BANKS=1 ++CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y ++CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x20000000 ++CONFIG_ENV_SIZE=0x2000 ++CONFIG_DM_GPIO=y ++CONFIG_DEFAULT_DEVICE_TREE="meson-sm1-jethome-jethub-j200" ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_DM_RESET=y ++CONFIG_MESON_G12A=y ++CONFIG_DEBUG_UART_BASE=0xff803000 ++CONFIG_DEBUG_UART_CLOCK=24000000 ++CONFIG_IDENT_STRING=" jethubj200" ++CONFIG_SYS_LOAD_ADDR=0x01000000 ++CONFIG_DEBUG_UART=y ++CONFIG_REMAKE_ELF=y ++CONFIG_FIT=y ++CONFIG_FIT_SIGNATURE=y ++CONFIG_FIT_VERBOSE=y ++CONFIG_LEGACY_IMAGE_FORMAT=y ++CONFIG_OF_BOARD_SETUP=y ++# CONFIG_DISPLAY_CPUINFO is not set ++CONFIG_MISC_INIT_R=y ++CONFIG_SYS_MAXARGS=32 ++# CONFIG_CMD_BDI is not set ++# CONFIG_CMD_IMI is not set ++CONFIG_CMD_EEPROM=y ++CONFIG_CMD_DFU=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_I2C=y ++# CONFIG_CMD_LOADS is not set ++CONFIG_CMD_MMC=y ++CONFIG_CMD_USB=y ++CONFIG_CMD_USB_MASS_STORAGE=y ++CONFIG_CMD_RTC=y ++CONFIG_CMD_REGULATOR=y ++CONFIG_PARTITION_TYPE_GUID=y ++CONFIG_OF_CONTROL=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_DFU_RAM=y ++CONFIG_DM_I2C=y ++CONFIG_SYS_I2C_MESON=y ++CONFIG_MMC_MESON_GX=y ++CONFIG_PHY_REALTEK=y ++CONFIG_DM_MDIO=y ++CONFIG_DM_MDIO_MUX=y ++CONFIG_ETH_DESIGNWARE_MESON8B=y ++CONFIG_MDIO_MUX_MESON_G12A=y ++CONFIG_MESON_G12A_USB_PHY=y ++CONFIG_PINCTRL=y ++CONFIG_PINCTRL_MESON_G12A=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_MESON_EE_POWER_DOMAIN=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_RTC=y ++CONFIG_RTC_PCF8563=y ++CONFIG_DEBUG_UART_ANNOUNCE=y ++CONFIG_DEBUG_UART_SKIP_INIT=y ++CONFIG_MESON_SERIAL=y ++CONFIG_USB=y ++CONFIG_DM_USB_GADGET=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_DWC3=y ++CONFIG_USB_DWC3=y ++# CONFIG_USB_DWC3_GADGET is not set ++CONFIG_USB_DWC3_MESON_G12A=y ++CONFIG_USB_KEYBOARD=y ++CONFIG_USB_GADGET=y ++CONFIG_USB_GADGET_VENDOR_NUM=0x1b8e ++CONFIG_USB_GADGET_PRODUCT_NUM=0xfada ++CONFIG_USB_GADGET_DWC2_OTG=y ++CONFIG_USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8=y ++CONFIG_USB_GADGET_DOWNLOAD=y ++CONFIG_VIDEO=y ++# CONFIG_VIDEO_BPP8 is not set ++# CONFIG_VIDEO_BPP16 is not set ++CONFIG_SYS_WHITE_ON_BLACK=y ++CONFIG_VIDEO_MESON=y ++CONFIG_VIDEO_DT_SIMPLEFB=y ++CONFIG_SPLASH_SCREEN=y ++CONFIG_SPLASH_SCREEN_ALIGN=y ++CONFIG_VIDEO_BMP_RLE8=y ++CONFIG_BMP_16BPP=y ++CONFIG_BMP_24BPP=y ++CONFIG_BMP_32BPP=y ++ ++CONFIG_MTD=y ++CONFIG_MTD_UBI=y ++CONFIG_DM_MTD=y ++CONFIG_DM_SPI_FLASH=y ++CONFIG_SPI_FLASH_XTX=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_MESON_SPIFC=y +-- +2.34.1 + diff --git a/patch/u-boot/v2024.01/board_jethubj200/0003-fix-j200.patch b/patch/u-boot/v2024.01/board_jethubj200/0003-fix-j200.patch new file mode 100644 index 000000000000..9f86d1b8c5e0 --- /dev/null +++ b/patch/u-boot/v2024.01/board_jethubj200/0003-fix-j200.patch @@ -0,0 +1,30 @@ +From 0673b2022ab73c4620896ba2510093bc9a81699a Mon Sep 17 00:00:00 2001 +From: Viacheslav Bocharov +Date: Tue, 23 Jan 2024 12:22:47 +0300 +Subject: [PATCH 3/3] fix j200 + +--- + configs/jethub_j200_defconfig | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/configs/jethub_j200_defconfig b/configs/jethub_j200_defconfig +index 340fbb10da..4d3e9d384b 100644 +--- a/configs/jethub_j200_defconfig ++++ b/configs/jethub_j200_defconfig +@@ -45,6 +45,7 @@ CONFIG_DFU_RAM=y + CONFIG_DM_I2C=y + CONFIG_SYS_I2C_MESON=y + CONFIG_MMC_MESON_GX=y ++CONFIG_MTD_UBI=y + CONFIG_PHY_REALTEK=y + CONFIG_DM_MDIO=y + CONFIG_DM_MDIO_MUX=y +@@ -98,3 +99,5 @@ CONFIG_DM_REGULATOR_GPIO=y + CONFIG_SPI=y + CONFIG_DM_SPI=y + CONFIG_MESON_SPIFC=y ++CONFIG_RANDOM_UUID=y ++CONFIG_CMD_PART=y +-- +2.34.1 + diff --git a/patch/u-boot/v2024.01/board_jethubj200/0004-HACK-mmc-meson-gx-limit-to-24MHz.patch.diff b/patch/u-boot/v2024.01/board_jethubj200/0004-HACK-mmc-meson-gx-limit-to-24MHz.patch.diff new file mode 100644 index 000000000000..865ba5022f9a --- /dev/null +++ b/patch/u-boot/v2024.01/board_jethubj200/0004-HACK-mmc-meson-gx-limit-to-24MHz.patch.diff @@ -0,0 +1,29 @@ +--- /dev/null ++++ b/patch/u-boot/v2024.01/board_jethubj200/0004-HACK-mmc-meson-gx-limit-to-24MHz.patch +@@ -0,0 +1,26 @@ ++From 212179dba7d0cd2d932b086c6c8e440372248ada Mon Sep 17 00:00:00 2001 ++From: Neil Armstrong ++Date: Mon, 2 Sep 2019 15:42:04 +0200 ++Subject: [PATCH 04/20] HACK: mmc: meson-gx: limit to 24MHz ++ ++Signed-off-by: Neil Armstrong ++--- ++ drivers/mmc/meson_gx_mmc.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c ++index fcf4f03d1e2..6ded4b619bf 100644 ++--- a/drivers/mmc/meson_gx_mmc.c +++++ b/drivers/mmc/meson_gx_mmc.c ++@@ -279,7 +279,7 @@ static int meson_mmc_probe(struct udevice *dev) ++ cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT | ++ MMC_MODE_HS_52MHz | MMC_MODE_HS; ++ cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV); ++- cfg->f_max = 100000000; /* 100 MHz */ +++ cfg->f_max = SD_EMMC_CLKSRC_24M; ++ cfg->b_max = 511; /* max 512 - 1 blocks */ ++ cfg->name = dev->name; ++ ++-- ++2.45.1 ++ diff --git a/patch/u-boot/v2024.01/board_jethubj200/enable-DT-overlays-support.patch b/patch/u-boot/v2024.01/board_jethubj200/enable-DT-overlays-support.patch new file mode 100644 index 000000000000..da5cc4420d7f --- /dev/null +++ b/patch/u-boot/v2024.01/board_jethubj200/enable-DT-overlays-support.patch @@ -0,0 +1,15 @@ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 1f3fa15..3f23cc8 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -652,8 +652,10 @@ config ARCH_OMAP2PLUS + + config ARCH_MESON + bool "Amlogic Meson" + select GPIO_EXTRA_HEADER ++ select OF_LIBFDT ++ select OF_LIBFDT_OVERLAY + imply DISTRO_DEFAULTS + imply DM_RNG + help + Support for the Meson SoC family developed by Amlogic Inc., From cd2011fa24ac54414294b1c9e1ae0d7e38d0a788 Mon Sep 17 00:00:00 2001 From: Viacheslav Bocharov Date: Thu, 13 Jun 2024 09:27:04 +0300 Subject: [PATCH 40/53] re-enable jethub j200 config --- config/boards/{jethubj200.eos => jethubj200.wip} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename config/boards/{jethubj200.eos => jethubj200.wip} (100%) diff --git a/config/boards/jethubj200.eos b/config/boards/jethubj200.wip similarity index 100% rename from config/boards/jethubj200.eos rename to config/boards/jethubj200.wip From 27351820c739e37261bb209df9ec9bdb4d9751a7 Mon Sep 17 00:00:00 2001 From: Viacheslav Bocharov Date: Thu, 13 Jun 2024 10:17:52 +0300 Subject: [PATCH 41/53] JetHub D2: Fix patchset --- ...axg-add-support-for-JetHome-JetHub-D.patch | 81 ++++++++----------- ...jethub-j200-add-meson64-reset-driver.patch | 33 ++++++++ 2 files changed, 67 insertions(+), 47 deletions(-) create mode 100644 patch/kernel/archive/meson64-6.9/jethome-0005-jethub-j200-add-meson64-reset-driver.patch diff --git a/patch/kernel/archive/meson64-6.9/jethome-0004-arm64-dts-meson-axg-add-support-for-JetHome-JetHub-D.patch b/patch/kernel/archive/meson64-6.9/jethome-0004-arm64-dts-meson-axg-add-support-for-JetHome-JetHub-D.patch index c38f3e73a714..0d1c51cb30fd 100644 --- a/patch/kernel/archive/meson64-6.9/jethome-0004-arm64-dts-meson-axg-add-support-for-JetHome-JetHub-D.patch +++ b/patch/kernel/archive/meson64-6.9/jethome-0004-arm64-dts-meson-axg-add-support-for-JetHome-JetHub-D.patch @@ -1,10 +1,11 @@ -From 7ad1d0a9aa045348451287ab7538201233c64a5b Mon Sep 17 00:00:00 2001 +From 44819c568dc6156d8a15b48af4dec3f20d484408 Mon Sep 17 00:00:00 2001 From: Viacheslav Bocharov Date: Thu, 16 May 2024 15:14:08 +0300 Subject: [PATCH 2/2] arm64: dts: meson-axg: add support for JetHome JetHub D2 (j200) -JetHome Jethub D2 is a home automation controller with the following features: +JetHome Jethub D2 is a home automation controller with the following +features: - DIN Rail Mounting - Amlogic S905X3 (ARM Cortex-A55) quad-core - micro-HDMI video out @@ -23,8 +24,8 @@ JetHome Jethub D2 is a home automation controller with the following features: Signed-off-by: Viacheslav Bocharov --- arch/arm64/boot/dts/amlogic/Makefile | 1 + - .../amlogic/meson-sm1-jethome-jethub-j200.dts | 632 ++++++++++++++++++ - 2 files changed, 633 insertions(+) + .../amlogic/meson-sm1-jethome-jethub-j200.dts | 618 ++++++++++++++++++ + 2 files changed, 619 insertions(+) create mode 100644 arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile @@ -41,10 +42,10 @@ index 0f29517da5ec..d007b59497d4 100644 dtb-$(CONFIG_ARCH_MESON) += meson-sm1-s905d3-libretech-cc.dtb diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts new file mode 100644 -index 000000000000..fcffbd0e24cc +index 000000000000..c309f25374b3 --- /dev/null +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts -@@ -0,0 +1,632 @@ +@@ -0,0 +1,618 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 JetHome @@ -92,7 +93,7 @@ index 000000000000..fcffbd0e24cc + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + -+ gpio = <&gpio_ao GPIOAO_3 GPIO_OPEN_DRAIN>; // #TODO: check ++ gpio = <&gpio_ao GPIOAO_3 GPIO_OPEN_DRAIN>; + enable-active-high; + regulator-always-on; + }; @@ -109,7 +110,7 @@ index 000000000000..fcffbd0e24cc + enable-active-high; + regulator-always-on; + -+ gpios = <&gpio_ao GPIOAO_6 GPIO_OPEN_SOURCE>; // #TODO: check ++ gpios = <&gpio_ao GPIOAO_6 GPIO_OPEN_SOURCE>; + gpios-states = <0>; + + states = <3300000 0>, @@ -140,7 +141,7 @@ index 000000000000..fcffbd0e24cc + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <&main_12v>; -+ gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>; // #TODO: check ++ gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>; + enable-active-high; + }; + @@ -160,7 +161,6 @@ index 000000000000..fcffbd0e24cc + regulator-max-microvolt = <3300000>; + vin-supply = <&vddao_3v3>; + regulator-always-on; -+ /* FIXME: actually controlled by VDDCPU_B_EN */ + }; + + vddcpu: regulator-vddcpu { @@ -261,16 +261,6 @@ index 000000000000..fcffbd0e24cc + }; + }; + -+ meson64-reboot { -+ compatible = "meson64,reboot"; -+ sys_reset = <0x84000009>; -+ sys_poweroff = <0x84000008>; -+ -+ sd-vqen = <&gpio GPIOE_2 GPIO_ACTIVE_HIGH>; -+ sd-vqsw = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; -+ sd-vmmc = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; -+ }; -+ + leds { + compatible = "gpio-leds"; + @@ -278,7 +268,7 @@ index 000000000000..fcffbd0e24cc + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "activity"; ++ linux,default-trigger = "heartbeat"; + panic-indicator; + }; + @@ -295,8 +285,21 @@ index 000000000000..fcffbd0e24cc + model = "JETHUB-D2"; + }; + -+}; ++ usb-hub { ++ dr_mode = "host"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* USB 2.0 hub with reset gpio */ ++ hub_2_0: hub@1 { ++ compatible = "usb5e3,610"; ++ reg = <1>; ++ reset-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_LOW>; ++ vdd-supply = <&vcc_5v>; ++ }; ++ }; + ++}; + +&arb { + status = "okay"; @@ -424,7 +427,7 @@ index 000000000000..fcffbd0e24cc + "MCU_RESET", /* GPIOAO_4 */ + "POWER_GOOD", /* GPIOAO_5 */ + "", -+ "MCU_BOOT", /* GPIOAO_7 */ ++ "GPIO_EXPANDER", /* GPIOAO_7 */ + "MCU_UART_TX", /* GPIOAO_8 */ + "MCU_UART_RX", /* GPIOAO_9 */ + "BUTTON_USR", /* GPIOAO_10 */ @@ -498,14 +501,8 @@ index 000000000000..fcffbd0e24cc + vqmmc-supply = <&flash_1v8>; +}; + -+/* -+&sd_emmc_c { -+ pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_4b_pins>, <&emmc_ds_pins>; -+ bus-width = <4>; -+}; -+ +&spifc { -+ status = "okay"; ++ status = "disabled"; + pinctrl-0 = <&nor_pins>; + pinctrl-names = "default"; + @@ -517,7 +514,6 @@ index 000000000000..fcffbd0e24cc + spi-max-frequency = <104000000>; + }; +}; -+*/ + +&tdmif_b { + status = "okay"; @@ -555,19 +551,6 @@ index 000000000000..fcffbd0e24cc + vbus-supply = <&usb_pwr_en>; +}; + -+&dwc2 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ /* USB 2.0 hub on otg port */ -+ hub_2_0: hub@1 { -+ compatible = "usb4b4,6504"; /* use 10000us timeout for reset */ -+ reg = <1>; -+ reset-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_LOW>; -+ vdd-supply = <&vcc_5v>; -+ }; -+}; -+ +&usb2_phy0 { + phy-supply = <&vcc_5v>; +}; @@ -585,6 +568,10 @@ index 000000000000..fcffbd0e24cc + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupt-parent = <&gpio_intc>; ++ interrupts = ; + + gpio-line-names = + "RELAY_1", "RELAY_2", @@ -597,9 +584,9 @@ index 000000000000..fcffbd0e24cc + + /* 1-wire */ + w1: onewire@18 { -+ compatible = "maxim,ds2482"; -+ reg = <0x18>; -+ }; ++ compatible = "maxim,ds2482"; ++ reg = <0x18>; ++ }; + +}; + diff --git a/patch/kernel/archive/meson64-6.9/jethome-0005-jethub-j200-add-meson64-reset-driver.patch b/patch/kernel/archive/meson64-6.9/jethome-0005-jethub-j200-add-meson64-reset-driver.patch new file mode 100644 index 000000000000..2543377a400d --- /dev/null +++ b/patch/kernel/archive/meson64-6.9/jethome-0005-jethub-j200-add-meson64-reset-driver.patch @@ -0,0 +1,33 @@ +From d2a9ccf69cfc856f873372784a46b5088dd2aada Mon Sep 17 00:00:00 2001 +From: Viacheslav Bocharov +Date: Thu, 13 Jun 2024 10:17:07 +0300 +Subject: [PATCH 3/3] add meson64-reset driver + +--- + .../boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts +index c309f25374b3..4c84ed0db1cc 100644 +--- a/arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts ++++ b/arch/arm64/boot/dts/amlogic/meson-sm1-jethome-jethub-j200.dts +@@ -213,6 +213,16 @@ codec { + }; + }; + ++ meson64-reboot { ++ compatible = "meson64,reboot"; ++ sys_reset = <0x84000009>; ++ sys_poweroff = <0x84000008>; ++ ++ sd-vqen = <&gpio GPIOE_2 GPIO_ACTIVE_HIGH>; ++ sd-vqsw = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; ++ sd-vmmc = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; ++ }; ++ + leds { + compatible = "gpio-leds"; + +-- +2.45.2 + From 4a84bf07c4ac9cc4607bbdcf3a8fd2be0ef7bda5 Mon Sep 17 00:00:00 2001 From: Ricardo Pardini Date: Sun, 9 Jun 2024 03:24:00 +0200 Subject: [PATCH 42/53] rockchip-rk3588 6.8.y: nanopct6: Add NanoPC T6 SPI Flash (v6.8.y version) --- ...dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 patch/kernel/archive/rockchip-rk3588-6.8/1016-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch diff --git a/patch/kernel/archive/rockchip-rk3588-6.8/1016-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch b/patch/kernel/archive/rockchip-rk3588-6.8/1016-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch new file mode 100644 index 000000000000..7c15da6aa13a --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.8/1016-arm64-dts-rockchip-Add-NanoPC-T6-SPI-Flash.patch @@ -0,0 +1,52 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ricardo Pardini +Date: Thu, 6 Jun 2024 23:00:05 +0200 +Subject: arm64: dts: rockchip: Add NanoPC T6 SPI Flash + +Signed-off-by: Ricardo Pardini +--- + arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts | 14 ++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts +index 997b516c2533c..5ef2cc5fe0679 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-nanopc-t6.dts +@@ -541,20 +541,34 @@ &sdmmc { + cap-sd-highspeed; + disable-wp; + no-mmc; + no-sdio; + sd-uhs-sdr104; + vmmc-supply = <&vcc_3v3_s3>; + vqmmc-supply = <&vccio_sd_s0>; + status = "okay"; + }; + ++&sfc { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&fspim1_pins>; ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0x0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ spi-tx-bus-width = <1>; ++ }; ++}; ++ + &spi2 { + status = "okay"; + assigned-clocks = <&cru CLK_SPI2>; + assigned-clock-rates = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; + num-cs = <1>; + + pmic@0 { + compatible = "rockchip,rk806"; +-- +Armbian + From e127109e2dddb7ed48a9fef0b1b60fc8d064cff0 Mon Sep 17 00:00:00 2001 From: Alex Shumsky Date: Wed, 12 Jun 2024 14:56:07 +0300 Subject: [PATCH 43/53] rockchip64/rk3318-box: move stack further from base addr to allow bigger uboot image --- .../v2024.01/board_rk3318-box/rk3318-box-add-defconfig.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-defconfig.patch b/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-defconfig.patch index 0b16d01552be..2c4a569d8ace 100644 --- a/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-defconfig.patch +++ b/patch/u-boot/v2024.01/board_rk3318-box/rk3318-box-add-defconfig.patch @@ -11,7 +11,7 @@ index 0000000000..d356b21ac6 +CONFIG_TEXT_BASE=0x200000 +CONFIG_NR_DRAM_BANKS=1 +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x300000 ++CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000 +CONFIG_SF_DEFAULT_SPEED=20000000 +CONFIG_ENV_OFFSET=0x3F8000 +CONFIG_DEFAULT_DEVICE_TREE="rk3318-box" From c4d3ff5e34ec1a0b0ade700d410d73f41cc477ec Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Wed, 12 Jun 2024 23:53:00 +0200 Subject: [PATCH 44/53] rk3588: edge: Add H.264 decoder support Add a patch series to support VEPU121/VPU121, which mainly enables hardware decoding for H.264. It can also decode MPEG2 and VP8 as well as do JPEG encoding. --- ...588-Add-VPU121-H.264-Decoder-Support.patch | 347 ++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 patch/kernel/archive/rockchip-rk3588-6.10/0025-RK3588-Add-VPU121-H.264-Decoder-Support.patch diff --git a/patch/kernel/archive/rockchip-rk3588-6.10/0025-RK3588-Add-VPU121-H.264-Decoder-Support.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0025-RK3588-Add-VPU121-H.264-Decoder-Support.patch new file mode 100644 index 000000000000..46eee186ce2b --- /dev/null +++ b/patch/kernel/archive/rockchip-rk3588-6.10/0025-RK3588-Add-VPU121-H.264-Decoder-Support.patch @@ -0,0 +1,347 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 13 Jun 2024 15:48:42 +0200 +Subject: media: dt-bindings: rk3568-vepu: Add RK3588 VEPU121 + +From: Emmanuel Gil Peyrot + +This encoder-only device is present four times on this SoC, and should +support everything the rk3568 vepu supports (so JPEG, H.264 and VP8 +encoding). No fallback compatible has been added, since the operating +systems might already support RK3568 VEPU and want to avoid registering +four of them separately considering they can be used as a cluster. + +Signed-off-by: Emmanuel Gil Peyrot +Signed-off-by: Sebastian Reichel +--- + Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml b/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml +index 111111111111..222222222222 100644 +--- a/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip,rk3568-vepu.yaml +@@ -17,6 +17,7 @@ properties: + compatible: + enum: + - rockchip,rk3568-vepu ++ - rockchip,rk3588-vepu121 + + reg: + maxItems: 1 +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 13 Jun 2024 15:48:43 +0200 +Subject: media: dt-bindings: rockchip-vpu: Add RK3588 VPU121 + +From: Jianfeng Liu + +RK3588 has four Hantro H1 VEPUs (encoder-only) modules and one combined +Hantro H1/G1 VPU (decoder and encoder). These are not described as +separate IP, since they are sharing an internal cache. This adds the +RK3588 specific compatible string for the combined VPU, which seems to +be identical to the version found in the RK3568. + +Signed-off-by: Jianfeng Liu +Acked-by: Conor Dooley +Signed-off-by: Sebastian Reichel +--- + Documentation/devicetree/bindings/media/rockchip-vpu.yaml | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +index 111111111111..222222222222 100644 +--- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml ++++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +@@ -31,6 +31,9 @@ properties: + - items: + - const: rockchip,rk3228-vpu + - const: rockchip,rk3399-vpu ++ - items: ++ - const: rockchip,rk3588-vpu121 ++ - const: rockchip,rk3568-vpu + + reg: + maxItems: 1 +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 13 Jun 2024 15:48:44 +0200 +Subject: media: hantro: Disable multicore support + +Avoid exposing equal Hantro video codecs to userspace. Equal video +codecs allow scheduling work between the cores. For that kernel support +is required, which does not yet exist. Until that is implemented avoid +exposing each core separately to userspace so that multicore can be +added in the future without breaking userspace ABI. + +This was written with Rockchip RK3588 in mind (which has 4 Hantro H1 +cores), but applies to all SoCs. + +Signed-off-by: Sebastian Reichel +--- + drivers/media/platform/verisilicon/hantro_drv.c | 37 ++++++++++ + 1 file changed, 37 insertions(+) + +diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c +index 111111111111..222222222222 100644 +--- a/drivers/media/platform/verisilicon/hantro_drv.c ++++ b/drivers/media/platform/verisilicon/hantro_drv.c +@@ -992,6 +992,39 @@ static const struct media_device_ops hantro_m2m_media_ops = { + .req_queue = v4l2_m2m_request_queue, + }; + ++/* ++ * Some SoCs, like RK3588 have multiple identical Hantro cores, but the ++ * kernel is currently missing support for multi-core handling. Exposing ++ * separate devices for each core to userspace is bad, since that does ++ * not allow scheduling tasks properly (and creates ABI). With this workaround ++ * the driver will only probe for the first core and early exit for the other ++ * cores. Once the driver gains multi-core support, the same technique ++ * for detecting the main core can be used to cluster all cores together. ++ */ ++static int hantro_disable_multicore(struct hantro_dev *vpu) ++{ ++ const char *compatible; ++ struct device_node *node; ++ int ret; ++ ++ /* Intentionally ignores the fallback strings */ ++ ret = of_property_read_string(vpu->dev->of_node, "compatible", &compatible); ++ if (ret) ++ return ret; ++ ++ /* first compatible node found from the root node is considered the main core */ ++ node = of_find_compatible_node(NULL, NULL, compatible); ++ if (!node) ++ return -EINVAL; /* broken DT? */ ++ ++ if (vpu->dev->of_node != node) { ++ dev_info(vpu->dev, "missing multi-core support, ignoring this instance\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ + static int hantro_probe(struct platform_device *pdev) + { + const struct of_device_id *match; +@@ -1011,6 +1044,10 @@ static int hantro_probe(struct platform_device *pdev) + match = of_match_node(of_hantro_match, pdev->dev.of_node); + vpu->variant = match->data; + ++ ret = hantro_disable_multicore(vpu); ++ if (ret) ++ return ret; ++ + /* + * Support for nxp,imx8mq-vpu is kept for backwards compatibility + * but it's deprecated. Please update your DTS file to use +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 13 Jun 2024 15:48:45 +0200 +Subject: media: hantro: Add RK3588 VEPU121 + +RK3588 handling is exactly the same as RK3568. This is not +handled using fallback compatibles to avoid exposing multiple +video devices on kernels not having the multicore disable +patch. + +Signed-off-by: Sebastian Reichel +--- + drivers/media/platform/verisilicon/hantro_drv.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c +index 111111111111..222222222222 100644 +--- a/drivers/media/platform/verisilicon/hantro_drv.c ++++ b/drivers/media/platform/verisilicon/hantro_drv.c +@@ -722,6 +722,7 @@ static const struct of_device_id of_hantro_match[] = { + { .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, }, + { .compatible = "rockchip,rk3568-vepu", .data = &rk3568_vepu_variant, }, + { .compatible = "rockchip,rk3568-vpu", .data = &rk3568_vpu_variant, }, ++ { .compatible = "rockchip,rk3588-vepu121", .data = &rk3568_vpu_variant, }, + { .compatible = "rockchip,rk3588-av1-vpu", .data = &rk3588_vpu981_variant, }, + #endif + #ifdef CONFIG_VIDEO_HANTRO_IMX8M +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 13 Jun 2024 15:48:46 +0200 +Subject: arm64: dts: rockchip: Add VEPU121 to RK3588 + +From: Emmanuel Gil Peyrot + +RK3588 has 4 Hantro G1 encoder-only cores. They are all independent IP, +but can be used as a cluster (i.e. sharing work between the cores). +These cores are called VEPU121 in the TRM. The TRM describes one more +VEPU121, but that is combined with a Hantro H1. That one will be handled +using the VPU binding instead. + +Signed-off-by: Emmanuel Gil Peyrot +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 80 ++++++++++ + 1 file changed, 80 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -1282,6 +1282,86 @@ power-domain@RK3588_PD_SDMMC { + }; + }; + ++ vepu121_0: video-codec@fdba0000 { ++ compatible = "rockchip,rk3588-vepu121"; ++ reg = <0x0 0xfdba0000 0x0 0x800>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER0>, <&cru HCLK_JPEG_ENCODER0>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vepu121_0_mmu>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ ++ vepu121_0_mmu: iommu@fdba0800 { ++ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfdba0800 0x0 0x40>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER0>, <&cru HCLK_JPEG_ENCODER0>; ++ clock-names = "aclk", "iface"; ++ power-domains = <&power RK3588_PD_VDPU>; ++ #iommu-cells = <0>; ++ }; ++ ++ vepu121_1: video-codec@fdba4000 { ++ compatible = "rockchip,rk3588-vepu121"; ++ reg = <0x0 0xfdba4000 0x0 0x800>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER1>, <&cru HCLK_JPEG_ENCODER1>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vepu121_1_mmu>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ ++ vepu121_1_mmu: iommu@fdba4800 { ++ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfdba4800 0x0 0x40>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER1>, <&cru HCLK_JPEG_ENCODER1>; ++ clock-names = "aclk", "iface"; ++ power-domains = <&power RK3588_PD_VDPU>; ++ #iommu-cells = <0>; ++ }; ++ ++ vepu121_2: video-codec@fdba8000 { ++ compatible = "rockchip,rk3588-vepu121"; ++ reg = <0x0 0xfdba8000 0x0 0x800>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER2>, <&cru HCLK_JPEG_ENCODER2>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vepu121_2_mmu>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ ++ vepu121_2_mmu: iommu@fdba8800 { ++ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfdba8800 0x0 0x40>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER2>, <&cru HCLK_JPEG_ENCODER2>; ++ clock-names = "aclk", "iface"; ++ power-domains = <&power RK3588_PD_VDPU>; ++ #iommu-cells = <0>; ++ }; ++ ++ vepu121_3: video-codec@fdbac000 { ++ compatible = "rockchip,rk3588-vepu121"; ++ reg = <0x0 0xfdbac000 0x0 0x800>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER3>, <&cru HCLK_JPEG_ENCODER3>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vepu121_3_mmu>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ ++ vepu121_3_mmu: iommu@fdbac800 { ++ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfdbac800 0x0 0x40>; ++ interrupts = ; ++ clocks = <&cru ACLK_JPEG_ENCODER3>, <&cru HCLK_JPEG_ENCODER3>; ++ clock-names = "aclk", "iface"; ++ power-domains = <&power RK3588_PD_VDPU>; ++ #iommu-cells = <0>; ++ }; ++ + av1d: video-codec@fdc70000 { + compatible = "rockchip,rk3588-av1-vpu"; + reg = <0x0 0xfdc70000 0x0 0x800>; +-- +Armbian + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 13 Jun 2024 15:48:47 +0200 +Subject: arm64: dts: rockchip: Add VPU121 support for RK3588 + +From: Jianfeng Liu + +Enable Hantro G1 video decoder in RK3588's devicetree. + +Tested with FFmpeg v4l2_request code taken from [1] +with MPEG2, H.264 and VP8 samples. + +[1] https://github.com/LibreELEC/LibreELEC.tv/blob/master/packages/multimedia/ffmpeg/patches/v4l2-request/ffmpeg-001-v4l2-request.patch + +Signed-off-by: Jianfeng Liu +Tested-by: Hugh Cole-Baker +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 21 ++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +index 111111111111..222222222222 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -1282,6 +1282,27 @@ power-domain@RK3588_PD_SDMMC { + }; + }; + ++ vpu121: video-codec@fdb50000 { ++ compatible = "rockchip,rk3588-vpu121", "rockchip,rk3568-vpu"; ++ reg = <0x0 0xfdb50000 0x0 0x800>; ++ interrupts = ; ++ interrupt-names = "vdpu"; ++ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; ++ clock-names = "aclk", "hclk"; ++ iommus = <&vpu121_mmu>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ }; ++ ++ vpu121_mmu: iommu@fdb50800 { ++ compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; ++ reg = <0x0 0xfdb50800 0x0 0x40>; ++ interrupts = ; ++ clock-names = "aclk", "iface"; ++ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; ++ power-domains = <&power RK3588_PD_VDPU>; ++ #iommu-cells = <0>; ++ }; ++ + vepu121_0: video-codec@fdba0000 { + compatible = "rockchip,rk3588-vepu121"; + reg = <0x0 0xfdba0000 0x0 0x800>; +-- +Armbian + From dddfa9cc35a0a3f68d18b5c36804b220738279b3 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Wed, 12 Jun 2024 23:53:29 +0200 Subject: [PATCH 45/53] rk3588: edge: Rewrite kernel patches against 6.10-rc3 --- .../0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch | 2 +- ...9-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/patch/kernel/archive/rockchip-rk3588-6.10/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch index b8a394db537d..5bdbf4b672f2 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.10/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.10/0138-arm64-dts-rockchip-Add-HDMI0-bridge-to-rk3588.patch @@ -14,7 +14,7 @@ diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/roc index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -1414,6 +1414,61 @@ i2s9_8ch: i2s@fddfc000 { +@@ -1515,6 +1515,61 @@ i2s9_8ch: i2s@fddfc000 { status = "disabled"; }; diff --git a/patch/kernel/archive/rockchip-rk3588-6.10/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch index a8e80fae127f..80d68c45e7f0 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.10/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.10/0139-arm64-dts-rockchip-Enable-HDMI0-PHY-clk-provider-on-.patch @@ -13,7 +13,7 @@ diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/roc index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -2883,6 +2883,7 @@ hdptxphy_hdmi0: phy@fed60000 { +@@ -2984,6 +2984,7 @@ hdptxphy_hdmi0: phy@fed60000 { reg = <0x0 0xfed60000 0x0 0x2000>; clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>; clock-names = "ref", "apb"; From bc8ee4861937432178506016b1f06ad3c9e9149e Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Thu, 13 Jun 2024 11:31:56 +0200 Subject: [PATCH 46/53] rk3588: edge: Update RGA patch Remove vpu nodes from RGA patch since these are already included in the H.264 support patch. --- ...4-dts-rockchip-rk3588-add-RGA2-node.patch} | 27 +++---------------- 1 file changed, 3 insertions(+), 24 deletions(-) rename patch/kernel/archive/rockchip-rk3588-6.10/{0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch => 0147-arm64-dts-rockchip-rk3588-add-RGA2-node.patch} (57%) diff --git a/patch/kernel/archive/rockchip-rk3588-6.10/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch b/patch/kernel/archive/rockchip-rk3588-6.10/0147-arm64-dts-rockchip-rk3588-add-RGA2-node.patch similarity index 57% rename from patch/kernel/archive/rockchip-rk3588-6.10/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch rename to patch/kernel/archive/rockchip-rk3588-6.10/0147-arm64-dts-rockchip-rk3588-add-RGA2-node.patch index 7174475bea6d..e2b7486d10d3 100644 --- a/patch/kernel/archive/rockchip-rk3588-6.10/0147-arm64-dts-rockchip-rk3588-add-VDPU-and-RGA2-nodes.patch +++ b/patch/kernel/archive/rockchip-rk3588-6.10/0147-arm64-dts-rockchip-rk3588-add-RGA2-node.patch @@ -4,38 +4,17 @@ Date: Mon, 13 May 2024 20:29:49 +0300 Subject: arm64: dts: rockchip: rk3588: add VDPU and RGA2 nodes --- - arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 32 ++++++++++ - 1 file changed, 32 insertions(+) + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 11 ++++++++++ + 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi index 111111111111..222222222222 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi -@@ -726,6 +726,38 @@ mmu600_php: iommu@fcb00000 { +@@ -726,6 +726,17 @@ mmu600_php: iommu@fcb00000 { status = "disabled"; }; -+ vpu: video-codec@fdb50000 { -+ compatible = "rockchip,rk3568-vpu"; -+ reg = <0x0 0xfdb50000 0x0 0x800>; -+ interrupts = ; -+ interrupt-names = "vdpu"; -+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; -+ clock-names = "aclk", "hclk"; -+ iommus = <&vdpu_mmu>; -+ power-domains = <&power RK3588_PD_VDPU>; -+ }; -+ -+ vdpu_mmu: iommu@fdb50800 { -+ compatible = "rockchip,rk3568-iommu"; -+ reg = <0x0 0xfdb50800 0x0 0x40>; -+ interrupts = ; -+ clock-names = "aclk", "iface"; -+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>; -+ power-domains = <&power RK3588_PD_VDPU>; -+ #iommu-cells = <0>; -+ }; -+ + rga: rga@fdb80000 { + compatible = "rockchip,rk3568-rga", "rockchip,rk3288-rga"; + reg = <0x0 0xfdb80000 0x0 0x1000>; From 5b1a3b8ff6542eced3ddc9a02a0d8d9105560e4f Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:43:18 +0200 Subject: [PATCH 47/53] actions: Fix actions/labeler correctly labeling desktop folders --- .github/labeler.yml | 9 ++++++--- .github/labels.yml | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index efff988c06ba..589dba8c55d5 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -14,16 +14,19 @@ - all: - changed-files: - any-glob-to-any-file: ['patch/**/*','config/**/*'] - - all-globs-to-all-files: ['!config/cli/*','!config/desktop/*','!config/distributions/*'] + - any-globs-to-all-files: ['!config/cli/*','!config/desktop/*','!config/distributions/*'] + "Framework": - all: - changed-files: - any-glob-to-any-file: ['lib/*','tools/*','config/cli*','packages/*','extensions/*'] -"Action scripts": + +"Actions scripts": - all: - changed-files: - any-glob-to-any-file: ['.github/workflows/*'] + "Desktop": - - all: +- all: - changed-files: - any-glob-to-any-file: ['config/desktop/*'] diff --git a/.github/labels.yml b/.github/labels.yml index 05590a36f36e..c4b25f5ad4fd 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -52,9 +52,9 @@ - name: "Framework" color: "bfd4f2" description: "Framework components" -- name: "Action scripts" +- name: "Actions scripts" color: "bfd4f2" - description: "GitHub Action scripts" + description: "GitHub Actions scripts" - name: "Work in progress" color: "29E414" description: "Unfinished / work in progress" From cf5363c2aff056c181b12478acc83ccb2f07a5c0 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:45:20 +0200 Subject: [PATCH 48/53] actions: Add "Patches" label category to actions/labeler --- .github/labeler.yml | 5 +++++ .github/labels.yml | 3 +++ 2 files changed, 8 insertions(+) diff --git a/.github/labeler.yml b/.github/labeler.yml index 589dba8c55d5..aefd1b71d064 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -30,3 +30,8 @@ - all: - changed-files: - any-glob-to-any-file: ['config/desktop/*'] + +"Patches": +- all: + - changed-files: + - any-glob-to-any-file: ['patch/*'] diff --git a/.github/labels.yml b/.github/labels.yml index c4b25f5ad4fd..1ddaf637ab4b 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -55,6 +55,9 @@ - name: "Actions scripts" color: "bfd4f2" description: "GitHub Actions scripts" +- name: "Patches" + color: "bfd4f2" + description: "Patches related to kernel, U-Boot, ..." - name: "Work in progress" color: "29E414" description: "Unfinished / work in progress" From 1a468dc39021e8447f6fcb49b8ffa6c2ab249f6a Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:55:31 +0200 Subject: [PATCH 49/53] actions: Add "Documentation" label category to actions/labeler --- .github/labeler.yml | 5 +++++ .github/labels.yml | 3 +++ 2 files changed, 8 insertions(+) diff --git a/.github/labeler.yml b/.github/labeler.yml index aefd1b71d064..ad8aabfdceac 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -35,3 +35,8 @@ - all: - changed-files: - any-glob-to-any-file: ['patch/*'] + +# Add 'Documentation' label to any change to .md files within the entire repository +"Documentation": +- changed-files: + - any-glob-to-any-file: '**/*.md' diff --git a/.github/labels.yml b/.github/labels.yml index 1ddaf637ab4b..0492b3f2cd19 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -58,6 +58,9 @@ - name: "Patches" color: "bfd4f2" description: "Patches related to kernel, U-Boot, ..." +- name: "Documentation" + color: "bfd4f2" + description: "Documentation changes or additions" - name: "Work in progress" color: "29E414" description: "Unfinished / work in progress" From 8d7d6f44c7b93eca6ba9c4f5c7bc24234f3c8694 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:56:28 +0200 Subject: [PATCH 50/53] actions: Fix typo in actions/labeler labeler.yml --- .github/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index ad8aabfdceac..5ef0264783e3 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -19,7 +19,7 @@ "Framework": - all: - changed-files: - - any-glob-to-any-file: ['lib/*','tools/*','config/cli*','packages/*','extensions/*'] + - any-glob-to-any-file: ['lib/*','tools/*','config/cli/*','packages/*','extensions/*'] "Actions scripts": - all: From f28bb4e5ae7700a4d5145b77f10ca9dff89fa52e Mon Sep 17 00:00:00 2001 From: Muhammed Efe Cetin Date: Fri, 14 Jun 2024 18:06:43 +0300 Subject: [PATCH 51/53] extlinux: add DEFAULT_OVERLAYS support --- lib/functions/rootfs/distro-agnostic.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/functions/rootfs/distro-agnostic.sh b/lib/functions/rootfs/distro-agnostic.sh index d9a54f5d939e..69ce3f9f44b5 100644 --- a/lib/functions/rootfs/distro-agnostic.sh +++ b/lib/functions/rootfs/distro-agnostic.sh @@ -146,6 +146,15 @@ function install_distribution_agnostic() { else echo " fdtdir ${bootpart_prefix}dtb/" >> "$SDCARD/boot/extlinux/extlinux.conf" fi + + if [[ -n $DEFAULT_OVERLAYS ]]; then + DEFAULT_OVERLAYS=(${DEFAULT_OVERLAYS//,/ }) + DEFAULT_OVERLAYS=("${DEFAULT_OVERLAYS[@]/%/".dtbo"}") + DEFAULT_OVERLAYS=("${DEFAULT_OVERLAYS[@]/#/"${bootpart_prefix}dtb/${BOOT_FDT_FILE%%/*}/overlay/${OVERLAY_PREFIX}-"}") + + display_alert "Adding to extlinux.conf" "fdtoverlays=${DEFAULT_OVERLAYS[@]}" "debug" + echo " fdtoverlays ${DEFAULT_OVERLAYS[@]}" >> "$SDCARD/boot/extlinux/extlinux.conf" + fi else # ... not extlinux ... if [[ -n "${BOOTSCRIPT}" ]]; then # @TODO: && "${BOOTCONFIG}" != "none" From 5ea4a2c428bbbd781f01cf86472f23b8a4eefb49 Mon Sep 17 00:00:00 2001 From: Igor Pecovnik Date: Fri, 14 Jun 2024 14:49:05 +0200 Subject: [PATCH 52/53] Disable autosuspend on Gnome based desktops --- config/desktop/bookworm/environments/budgie/debian/postinst | 3 +++ config/desktop/bookworm/environments/gnome/debian/postinst | 3 +++ config/desktop/common/environments/budgie/debian/postinst | 3 +++ config/desktop/common/environments/gnome/debian/postinst | 3 +++ 4 files changed, 12 insertions(+) diff --git a/config/desktop/bookworm/environments/budgie/debian/postinst b/config/desktop/bookworm/environments/budgie/debian/postinst index c5240bb0e790..71890b44f6d3 100755 --- a/config/desktop/bookworm/environments/budgie/debian/postinst +++ b/config/desktop/bookworm/environments/budgie/debian/postinst @@ -66,6 +66,9 @@ exec='/usr/bin/terminator' [org/cinnamon/desktop/default-applications/terminal] exec='/usr/bin/terminator' +[org/gnome/settings-daemon/plugins/power] +sleep-inactive-ac-timeout='0' + [org/gnome/desktop/wm/preferences] button-layout='appmenu:minimize,maximize,close' num-workspaces=2 diff --git a/config/desktop/bookworm/environments/gnome/debian/postinst b/config/desktop/bookworm/environments/gnome/debian/postinst index 22b150e1e296..d19f4438df72 100644 --- a/config/desktop/bookworm/environments/gnome/debian/postinst +++ b/config/desktop/bookworm/environments/gnome/debian/postinst @@ -18,6 +18,9 @@ picture-options='zoom' primary-color='#456789' secondary-color='#FFFFFF' +[org/gnome/settings-daemon/plugins/power] +sleep-inactive-ac-timeout='0' + [org/gnome/desktop/screensaver] picture-uri='file:///usr/share/backgrounds/armbian/armbian03-Dre0x-Minum-dark-3840x2160.jpg' picture-options='zoom' diff --git a/config/desktop/common/environments/budgie/debian/postinst b/config/desktop/common/environments/budgie/debian/postinst index c5240bb0e790..52b1c31324a5 100755 --- a/config/desktop/common/environments/budgie/debian/postinst +++ b/config/desktop/common/environments/budgie/debian/postinst @@ -47,6 +47,9 @@ picture-options='stretched' picture-uri='file:////usr/share/backgrounds/armbian/armbian03-Dre0x-Minum-dark-3840x2160.jpg' primary-color='#008094' +[org/gnome/settings-daemon/plugins/power] +sleep-inactive-ac-timeout='0' + [org/gnome/desktop/interface] cursor-theme='DMZ-White' document-font-name='Noto Sans UI 11' diff --git a/config/desktop/common/environments/gnome/debian/postinst b/config/desktop/common/environments/gnome/debian/postinst index 29f8aa64b9a0..e37219bbae61 100644 --- a/config/desktop/common/environments/gnome/debian/postinst +++ b/config/desktop/common/environments/gnome/debian/postinst @@ -17,6 +17,9 @@ echo " [org/gnome/shell] favorite-apps = ['terminator.desktop', 'org.gnome.Nautilus.desktop', 'google-chrome.desktop', 'thunderbird.desktop', 'code.desktop', 'Zoom.desktop'] +[org/gnome/settings-daemon/plugins/power] +sleep-inactive-ac-timeout='0' + [org/gnome/desktop/background] picture-uri='file:///usr/share/backgrounds/armbian/armbian03-Dre0x-Minum-dark-3840x2160.jpg' picture-options='zoom' From 5dcb33a960f14c3d53349a71e58f8be7c9f4c2f4 Mon Sep 17 00:00:00 2001 From: ColorfulRhino <131405023+ColorfulRhino@users.noreply.github.com> Date: Sat, 15 Jun 2024 07:44:48 +0000 Subject: [PATCH 53/53] actions: Fix typo in actions/labeler labeler.yml (#6745) It's not "any-globs-to-all-files", but "any-glob-to-all-files" --- .github/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 5ef0264783e3..aab2b7266d7f 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -14,7 +14,7 @@ - all: - changed-files: - any-glob-to-any-file: ['patch/**/*','config/**/*'] - - any-globs-to-all-files: ['!config/cli/*','!config/desktop/*','!config/distributions/*'] + - any-glob-to-all-files: ['!config/cli/*','!config/desktop/*','!config/distributions/*'] "Framework": - all: